늑대와 닭


15

강이 있고 강 한쪽에는 늑대와 닭이 있습니다. 그들은 뗏목을 가지고 있으며 모두 반대편으로 가야합니다. 그러나 뗏목은 스스로 여행 할 수 없습니다. 두 마리 이상의 동물이 있으면 뗏목이 가라 앉습니다. 강이 차갑고 더러워서 젖어 있기를 원하는 동물은 없습니다. 어느 동물도 강을 뛰어 넘거나 날 수 없습니다. 또한 한쪽에 닭이 있으면 그쪽에 닭보다 늑대가 더 많을 수 없습니다. 그러면 늑대가 닭을 먹기로 결정합니다. 이것은 당신이 뗏목에서 두 마리의 늑대를 한 마리의 닭과 함께 옆으로 데려 갈 수 없다는 것을 의미합니다.

당신의 임무는 입력으로 많은 늑대와 많은 닭 (늑대보다 크거나 같은)을 가지고 뗏목이 강을 가로 질러 움직여야하는 최소 횟수를 찾는 프로그램 / 기능을 만드는 것입니다. 작업이 불가능한 경우 프로그램 / 기능은 빈 문자열을 출력 / 반환해야합니다. 그런 다음 다음과 같은 방법으로이 방법을 인쇄 / 반환합니다.

W if a wolf crosses the river on its own
C if a chicken crosses the river on its own
CW if a chicken and a wolf cross the river -- WC is also fine
CC if two chickens cross the river
WW if two wolves cross the river

추론 할 수 있듯이 뗏목은 자동으로 교대 방향으로 움직입니다 (처음 한 두 마리의 동물이 강을 건너 왼쪽에서 오른쪽으로 시작). 이것은 출력 / 반환 할 필요가 없습니다. 출력에서 'W', 'C', 'CW', 'CC'또는 'WW'는 다음 중 하나 이상으로 구분 될 수 있습니다.

spaces (' ')
commas (',')
newlines

또는 길 찾기를 목록에 항목으로 저장할 수 있습니다 (빈 목록은 해결책이 없음을 의미 함).

테스트 사례 (쉼표로 구분 된 출력-입력 형식 wolves,chickens)

1,1 -> CW

2,2 -> CW,C,CC,C,CW

1,2 -> CW,W,CW

0,10 -> CC,C,CC,C,CC,C,CC,C,CC,C,CC,C,CC,C,CC,C,CC

3,2 -> no solution

코드를 가능한 짧게 바이트로 만드십시오.


(3,2)에 대한 해결책?
매직 문어 Urn

@carusocomputing 닭보다 늑대가 많기 때문에 작동하지 않습니다. 따라서 해결책이 없습니다.
0WJYxW9FMN

Ahh ... 입력을 W = 3, C = 2 또는 다른 것으로 레이블을 지정하십시오. 이 과정이 멋지다는 것 외에는 혼란 스러웠습니다.
매직 문어 Urn

@ carusocomputing 것입니다.하지만 입력이 W = 3, C = 2가 아니라 3,2이기 때문에 더 혼란 스러울 것이라고 생각합니다.
0WJYxW9FMN

답변:


5

179 165 164 163 157 156 바이트

에 +4 포함 -p

STDIN에서 늑대와 닭을 줘

river.pl <<< "2 3"

한 줄에 보트 내용을 출력합니다. 이 예제에서는 다음을 제공합니다.

WC
C
CC
C
CC
W
WW

river.pl:

#!/usr/bin/perl -p
/ /;@F=w x$`.c x$'."\xaf\n";$a{$`x/\n/}++||grep(y/c//<y/w//&/c/,$_,~$_)or$\||=$' x/^\w*\n|(\w?)(.*)(c|w)(.+)\n(?{push@F,$1.$3.~"$`$2$4\xf5".uc"$'$1$3\n"})^/ for@F}{

표시,하지만 교체로 작동 \xhh하고 \n그대로의 버전으로 주장 점수를 얻을.

이것은 아마도 일반적인 경우를 해결하는 프로그램에 의해 극복 될 것입니다 (C> W> 0)

* output `WC W WC C` until there is only one wolf left on the left bank (--w, --c)
* output `CC C` until there is only one chicken left on the left bank (--c)
* output `WC`

에 추가 만이 늑대 만 닭과에 대한 하드 코딩 특별한 경우에 대한 사소한 솔루션 2 23 3( 4 4와 더 높은 해결책이 없다). 그러나 그것은 지루한 프로그램이 될 것입니다.

설명

필드의 현재 상태는 다음으로 구성된 단일 문자열로 저장됩니다.

  • w 보트와 함께 은행에 늑대를 위해
  • c 보트와 함께 은행에 닭을 위해
  • \x88w다른 은행의 늑대에 대해서는 (비트 반전 )
  • \x9cc다른 은행의 닭고기에 대한 (비트 반전 )
  • P오른쪽 뱅크 에서 보트가있는 쪽을 표시하는 문자 \xaf( P왼쪽 뱅크의 경우 비트가 반전 됨 ) (시작 측)
  • 개행 \n
  • 지금까지 수행 된 모든 동작은 줄 바꿈으로 종료됩니다 WC\nW\nWC\nC\n( 예 : Ws를 통지하고 C대문자로 표시)

배열 @F에는 도달 가능한 모든 상태가 포함됩니다. 시작 문자열로 초기화됩니다.wolves times "w", chickens times "c", \xaf \n

그런 다음 프로그램 @F은 루핑 중에 확장되어 새로운 상태도 처리됩니다. 모든 요소에 대해 다음을 수행합니다.

  • \n동물과 보트의 현재 위치를 나타내는 첫 번째 줄의 왼쪽 부분을보십시오 . 건너 뛰기 전에 본 적이 있다면$a{$`x/\n/}++
  • 어느쪽에 더 많은 늑대와 함께 닭이 있는지 확인하십시오. 그렇다면 건너 뛰십시오grep(y/c//<y/w//&/c/,$_,~$_)
  • 보트가 모든 동물과 함께 먼쪽에 있는지 확인하십시오. 그렇다면 해결책이 있습니다. 그것을 저장하고 $\발견 된 첫 번째 해결책이 가장 짧기 때문에 유지하십시오$\||=$' x/^\w*\n/
  • 그렇지 않으면 배 옆에서 1 ~ 2 마리의 동물을 선택하는 모든 방법을 시도하십시오. 이들은 cw문자입니다. (다른 쪽의 동물은 일치하지 않습니다 \w) /(\w?)(.*)(c|w)(.+)\n(?{code})^/. 그런 다음 \n보트로 선택된 동물을 제외하고는 줄 전체를 약간 뒤집습니다 push@F,$1.$3.~"$`$2$4\xf5". 선택한 동물을 대문자로 이동에 추가하십시오.uc"$'$1$3\n"

동물 선택 과정은 여러 방법으로 그들을 나타내는 끈 부분을 효과적으로 섞습니다. 예를 들어, 그래서 wcwc하고 wwcc모두 2 늑대와이 닭을 나타내는 얻을 수 있습니다. 상태 확인 $a{$`x/\n/}++은이 두 가지를 불필요하게 구분하여 필요한 것보다 많은 상태를 생성하고 확인합니다. 따라서 다른 동물의 수가 많아지면 프로그램에 메모리와 시간이 부족합니다. 솔루션이 발견되면 현재 버전이 새로운 상태 추가를 중단한다는 사실로 인해 약간만 완화됩니다.


내가 말한 것을 잘못 이해하지 않는 한 4 4 이상 등가에는 솔루션이 있습니다. (4,4) = WC, C, WC, W, WC, W, WW, W, WC, W, WW, W, WC

@ Phaeze : WC,C,WC오른쪽 은행에 늑대 2 마리와 닭 1 마리가 있습니다. 게임 종료
Ton Hospel

그래, 내 나쁜 문제의 일부를 오해했다.

4

자바 스크립트 (ES6), 251 264 ... 244 240 바이트

늑대와 닭의 수를 (w, c)취하여 최적의 솔루션 중 하나를 반환하거나 undefined솔루션이없는 경우 반환 합니다.

(w,c,v={},B=1/0,S)=>(r=(s,w,c,W=0,C=0,d=1,N=0,k=w+'|'+c+d)=>v[k]|c*w>c*c|C*W>C*C|w<0|c<0|W<0|C<0?0:w|c?[v[k]=1,2,4,8,5].map(n=>r(s+'C'.repeat(b=n>>2)+'W'.repeat(a=n&3)+' ',w-d*a,c-d*b,W+d*a,C+d*b,-d,N+1))&(v[k]=0):N<B&&(B=N,S=s))('',w,c)||S

형식화 및 의견

랩퍼 기능 :

(                                    // given:
  w,                                 // - w : # of wolves
  c,                                 // - c : # of chickens
  v = {},                            // - v : object keeping track of visited nodes
  B = 1 / 0,                         // - B : length of best solution
  S                                  // - S : best solution
) => (                               //
r = (...) => ...                     // process recursive calls (see below)
)('', w, c) || S                     // return the best solution

주요 재귀 함수 :

r = (                                // given:
  s,                                 // - s : current solution (as text)
  w, c,                              // - w/c : # of chickens/wolves on the left side
  W = 0, C = 0,                      // - W/C : # of chickens/wolves on the right side
  d = 1,                             // - d : direction (1:left to right, -1:right to left)
  N = 0,                             // - N : length of current solution
  k = w + '|' + c + d                // - k : key identifying the current node
) =>                                 //
v[k] |                               // abort if this node was already visited
c * w > c * c | C * W > C * C |      // or there are more wolves than chickens somewhere
w < 0 | c < 0 | W < 0 | C < 0 ?      // or we have created antimatter animals 
  0                                  //
:                                    // else:
  w | c ?                            //   if there are still animals on the left side:
    [v[k] = 1, 2, 4, 8, 5].map(n =>  //     set node as visited and do a recursive call
      r(                             //     for each combination: W, WW, C, CC and CW
        s + 'C'.repeat(b = n >> 2) + //     append used combination to current solution
        'W'.repeat(a = n & 3) + ' ', //     wolves = bits 0-1 of n / chickens = bits 2-3
        w - d * a,                   //     update wolves on the left side
        c - d * b,                   //     update chickens on the left side
        W + d * a,                   //     update wolves on the right side
        C + d * b,                   //     update chickens on the right side
        -d,                          //     use opposite direction for the next turn
        N + 1                        //     increment length of current solution
      )                              //
    ) &                              //     once we're done,
    (v[k] = 0)                       //     set this node back to 'not visited'
  :                                  //   else:
    N < B &&                         //     save this solution if it's shorter than the
    (B = N, S = s)                   //     best solution encountered so far

테스트 사례


도전은 말한다 and finds the smallest number of times the raft has to move across the river.. 그래서 이것이 유효한 해결책이라고 생각하지 않습니다
Ton Hospel

@Arnauld OP는 무엇 에 대답 하는가 ? 다른 솔루션이 아닌 가장 짧은 솔루션 만 출력해야한다는 것이 분명하다고 생각합니다.
Outgolfer Erik

@Arnauld Ton Hospel이 옳습니다.
0WJYxW9FMN

@Arnauld 만약 당신이 다른 솔루션을 인쇄하지 못하도록한다면 – 가장 짧은 해결책이라면 괜찮을 것입니다.
0WJYxW9FMN

잘만되면 나는 이번에 그것을 올바르게 얻었다. ^^
Arnauld

2

CJam, 133

q~[0_]]_0+a:A;a{{28e3Zb2/{[YT2*(f*_Wf*]X..+:Bs'-&B2<{~_@<*},+{B2<T!+a:CA&{AC+:A;BY"WC".*a+}|}|}fY}fX]T!:T;__!\{0=:+!},e|:R!}g;R0=2>S*

온라인으로 사용해보십시오

설명:

기본적으로 프로그램은 BFS를 수행하며 무한 사이클을 피하기 위해 도달 한 모든 상태를 기억합니다. 작업 상태는 [[Wl Cl] [Wr Cr] M1 M2… Mn]과 같이 표현됩니다. 여기서 W = 늑대, C = 닭, l = 왼쪽, r = 오른쪽, M = 지금까지 한 움직임 (처음에는 없음), 이동은 "C", "WC"또는 "WW"등 (실제로는 [ "" "C"], [ "W" "C"], [ "WW" ""]과 유사)과 동일하지만 인쇄시). 기억 된 상태는 [[Wl Cl] [Wr Cr] S]와 같이 표현됩니다. 여기서 S는 보트의 측면입니다 (0 = 왼쪽, 1 = 오른쪽).

q~                 read and evaluate the input ([Wl Cl] array)
[0_]               push [0 0] as the initial [Wr Cr] array
]_                 wrap both in an array (initial working state) and duplicate it
0+a                append 0 (representing left side) and wrap in an array
:A;                store in A and pop; this is the array of remembered states
a                  wrap the working state in an array
{…}g               do … while
  {…}fX            for each working state X
    28e3Zb2/       convert 28000 to base 3 and group the digits into pairs
                    this generates [[1 1] [0 2] [1 0] [2 0] [0 1]]
                    which are all possible moves represented as [Wb Cb] (b=boat)
    {…}fY          for each "numeric move" pair Y
      […]          make an array of…
        YT2*(f*    Y negated if T=0 (T is the current boat side, initially 0)
        _Wf*       and the (arithmetic) negation of the previous pair
      X..+         add the 2 pairs to X, element by element
                    this performs the move by adding & subtracting the numbers
                    from the appropriate sides, determined by T
      :Bs          store the updated state in B, then convert to string
      '-&          intersect with "-" to see if there was any negative number
      B2<          also get just the animal counts from B (first 2 pairs)
      {…},         filter the 2 sides by checking…
        ~_@<*      if W>C>0 (it calculates (C<W)*C)
      +            concatenate the results from the negative test and eating test
      {…}|         if it comes up empty (valid state)…
        B2<        get the animal counts from B (first 2 pairs)
        T!+        append !T (opposite side)
        a:C        wrap in an array and store in C
        A&         intersect with A to see if we already reached that state
        {…}|       if not, then…
          AC+:A;   append C to A
          BY       push B and Y (updated state and numeric move)
          "WC".*   repeat "W" and "C" the corresponding numbers of times from Y
                    to generate the alphabetic move
          a+       wrap in array and append to B (adding the current move)
  ]                collect all the derived states in an array
  T!:T;            reverse the side with the boat
  __!              make 2 copies of the state array, and check if it's empty
  \{…},            filter another copy of it, checking for each state…
    0=:+!          if the left side adds up to 0
  e|:R             logical "or" the two and store the result in R
  !                (logically) negate R, using it as a do-while condition
                    the loop ends when there are no more working states
                    or there are states with the left side empty
;                  after the loop, pop the last state array
R0=2>S*            if the problem is solved, R has solution states,
                    and this extracts the moves from the first state
                    and joins them with space
                   if there's no solution, R=1
                    and this repeats a space 0 times, resulting in empty string

0

펄 6 , 268 바이트

->*@a {(
[X](0 X..@a)[1..*-2]
.grep({![>](|$_,0)&![>](|(@a Z-$_),0)})
.combinations(2)
.combinations
.map(|*.permutations)
.map({.map(|*)»[*]})
.map({((|$_,(0,0)ZZ-@a,|$_)ZX*|(-1,1)xx*)»[*]})
.grep({.all.&{.all>=0&&3>.sum>0}})
.map({.map:{[~](<W C>Zx$_)}})
if [<=] @a
)[0]//()}

(wolf count, chicken count)왼쪽 은행에 대해 점점 더 긴 국가 체인을 생성하고 모든 규칙과 일치하는 첫 번째 체인을 반환합니다.

이 접근법은 효율적이지도 간결하지도 않지만, 작성하는 것은 재미있었습니다.
내가 스택 적이 생각하지 않는다 Z(우편)와 X등, 전 (크로스) 메타 사업자 ZZ-ZX*좀 실제로 일한 놀라게 - 여기.

줄 바꿈은 표시 목적으로 추가되었으며 바이트 수의 일부가 아닙니다.


0

자바 스크립트 (ES6) 227 237

기본적으로 BFS를 수행하고 무한 사이클을 피하기 위해 도달 한 모든 상태를 기억합니다. @aditsu와 달리 골프를 할 여지가 없다고 생각합니다.

v=>g=>eval("o=[],s=[[v,g,0,k=[]]];for(i=0;y=s[i++];k[y]=k[y]||['WW','C','CC','W','CW'].map((u,j)=>(r=w-(j?j/3|0:2),q=c-j%3,d=g-q,e=v-r,r<0|q<0|!!q&r>q|!!d&e>d)||s.push([e,d,!z,[...p,u]])))o=([w,c,z,p]=y,y[3]=!z|c-g|w-v)?o:i=p")

덜 골프

(v,g) => {
  o = []; // output
  k = []; // hashtable to check states already seen
  s=[[v, g, 0, []]]; // states list: each element is wolves,chickens,side,path
  for(i = 0; 
      y = s[i++]; // exit loop when there are no more states to expand
     )
  {
    [w, c, z, p] = x; // wolves on this side, chickens on this side, side, path
    if (z && c==g && w==v) // if all chicken and wolves on the other side
      o = p, // the current path is the output
      i = p  // this will force the loop to terminate
    y[3] = 0; // forget the path, now I can use y as the key to check state and avoid cycles
    if (! k[y]) // it's a new state
    {
       k[y] = 1; // remember it
       ['WW','C','CC','W','CW'].map( (u,j)=> (
          a = j ? j/3|0 : 2, // wolves to move
          b = j % 3, // chicken to move  
          r = w - a, // new number of wolves on this side 
          q = c - b, // new number of chickens on this side
          e = v - r, // new number of wolves on other side
          d = g - q, // new number of chickens on other side
          // check condition about the number of animals together
          // if ok, push a new state
          r<0 |q<0 | !!q&r>q | !!d&e>d || 
            s.push([e, d, !z, [...p,u]) 
       )
    }
  }
  return o
}

테스트

F=
v=>g=>eval("o=[],s=[[v,g,0,k=[]]];for(i=0;y=s[i++];k[y]=k[y]||['WW','C','CC','W','CW'].map((u,j)=>(r=w-(j?j/3|0:2),q=c-j%3,d=g-q,e=v-r,r<0|q<0|!!q&r>q|!!d&e>d)||s.push([e,d,!z,[...p,u]])))o=([w,c,z,p]=y,y[3]=!z|c-g|w-v)?o:i=p")

function update() {
  var c=+C.value, w=+W.value
  O.textContent=F(w)(c)
}

update()
input { width: 4em }
Chickens <input id=C value=2 type=number min=0 oninput='update()'>
Wolves <input id=W value=2 type=number min=0 oninput='update()'>
<pre id=O></pre>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.