Chó sói và gà


16

Có một dòng sông và có một con sói và gà ở một bên bờ sông. Họ có một chiếc bè và tất cả họ cần phải sang bên kia. Tuy nhiên, chiếc bè không thể tự đi. Chiếc bè sẽ chìm nếu có nhiều hơn hai con vật trên đó. Không ai trong số các động vật muốn bị ướt vì dòng sông lạnh và bẩn. Không ai trong số các động vật có thể nhảy hoặc bay qua sông. Ngoài ra, nếu có một con gà ở một bên, không thể có nhiều con sói ở bên đó hơn những con gà ở bên đó - những con sói sau đó sẽ quyết định ăn thịt gà. Điều này có nghĩa là bạn không thể đưa hai con sói lên bè sang một bên với một con gà.

Nhiệm vụ của bạn là tạo ra một chương trình / chức năng lấy một số con sói và một số con gà (lớn hơn hoặc bằng số lượng con sói) làm đầu vào và tìm ra số lần nhỏ nhất mà bè phải di chuyển qua sông. Nếu tác vụ là không thể, chương trình / hàm sẽ xuất / trả về một chuỗi rỗng. Sau đó, nó sẽ in / trả về một phương thức như cách thực hiện theo cách sau:

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

Như bạn có thể suy luận, chiếc bè sẽ tự động di chuyển theo các hướng xen kẽ (trái và phải, bắt đầu từ trái sang phải khi một hoặc hai con vật đầu tiên băng qua sông). Điều này không cần phải xuất / trả lại. 'W', 'C', 'CW', 'CC' hoặc 'WW' trong đầu ra có thể được phân tách bằng ít nhất một trong các cách sau:

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

Ngoài ra, bạn có thể lưu trữ chỉ đường dưới dạng các mục trong danh sách (danh sách trống có nghĩa là không có giải pháp).

Các trường hợp thử nghiệm (đầu ra được phân tách bằng dấu phẩy - đầu vào có dạng 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

Cố gắng làm cho mã của bạn càng ngắn theo byte càng tốt.


Giải pháp cho (3,2)?
Bạch tuộc ma thuật Urn

@carusocomputing Nó không hoạt động, vì có nhiều sói hơn gà. Vì vậy, không có giải pháp.
0WJYxW9FMN

À ... Có thể gắn nhãn các đầu vào là W = 3, C = 2 hoặc một cái gì đó; là một chút khó hiểu để xử lý, ngoài ra điều này có vẻ mát mẻ.
Bạch tuộc ma thuật Urn

@carusocomputing Tôi sẽ, nhưng tôi nghĩ rằng nó sẽ khó hiểu hơn vì đầu vào là 3,2 chứ không phải W = 3, C = 2.
0WJYxW9FMN

1
Hy vọng cho một giải pháp ở
Robert Fraser

Câu trả lời:


6

Perl, 179 165 164 163 157 156 byte

Bao gồm +4 cho -p

Cho sói theo sau là gà trên STDIN

river.pl <<< "2 3"

Xuất ra nội dung thuyền trên mỗi dòng. Đối với ví dụ này, nó cung cấp:

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}{

Hoạt động như được hiển thị, nhưng thay thế \xhh\nbằng các phiên bản nghĩa đen của chúng để có được số điểm yêu cầu.

Điều này có thể sẽ bị đánh bại bởi một chương trình giải quyết trường hợp chung (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`

Thêm vào đó là các giải pháp tầm thường chỉ dành cho chó sói và chỉ gà và trường hợp đặc biệt được mã hóa cứng 2 23 3( 4 4và cao hơn không có giải pháp). Nhưng đó sẽ là một chương trình nhàm chán.

Giải trình

Trạng thái hiện tại của trường được lưu trữ dưới dạng một chuỗi bao gồm:

  • w cho một con sói trên bờ với chiếc thuyền
  • c cho một con gà trên bờ với chiếc thuyền
  • \x88(bit đảo ngược w) cho một con sói ở ngân hàng khác
  • \x9c(bit đảo ngược c) cho một con gà ở ngân hàng khác
  • Một ký tự chỉ ra phía bên của thuyền được bật Pcho bờ phải, \xaf(bit đảo ngược P) cho bờ trái (phía bắt đầu)
  • một dòng mới \n
  • tất cả các động thái đã được thực hiện cho đến nay chấm dứt với dòng mới, ví dụ như một cái gì đó như WC\nW\nWC\nC\n(chú ý chữ Ws và Cđược viết hoa ở đây)

Các mảng @Fsẽ chứa tất cả các trạng thái có thể truy cập. Nó được khởi tạo bởi chuỗi bắt đầuwolves times "w", chickens times "c", \xaf \n

Chương trình sau đó lặp lại @Fsẽ được mở rộng trong quá trình lặp để các trạng thái mới cũng được xử lý. Đối với mọi yếu tố thì nó sẽ:

  • Nhìn vào phần dây bên trái của phần đầu tiên \nđại diện cho vị trí hiện tại của động vật và thuyền. Nếu điều đó đã được nhìn thấy trước khi bỏ qua$a{$`x/\n/}++
  • Kiểm tra nếu có gà cùng với nhiều con sói ở bất kỳ bên nào. Bỏ qua nếu vậygrep(y/c//<y/w//&/c/,$_,~$_)
  • Kiểm tra nếu thuyền là phía xa cùng với tất cả các động vật. Nếu vậy chúng ta có một giải pháp. Lưu trữ trong đó $\và giữ nó vì giải pháp đầu tiên được tìm thấy là ngắn nhất$\||=$' x/^\w*\n/
  • Nếu không, hãy thử tất cả các cách chọn 1 hoặc 2 con vật ở bên cạnh thuyền. Đây là cvà các wnhân vật. (Các động vật ở phía bên kia sẽ không khớp \w) /(\w?)(.*)(c|w)(.+)\n(?{code})^/. Sau đó bit đảo ngược toàn bộ chuỗi trước khi \nngoại trừ các động vật được chọn cho thuyền push@F,$1.$3.~"$`$2$4\xf5". Thêm các động vật được chọn vào di chuyển bằng cách vượt qua chúng:uc"$'$1$3\n"

Quá trình chọn động vật có hiệu quả xáo trộn phần chuỗi đại diện cho chúng theo nhiều cách. Vì vậy, ví dụ wcwcwwcccả hai có thể đại diện cho 2 con sói và 2 con gà. Kiểm tra trạng thái $a{$`x/\n/}++sẽ phân biệt rõ ràng hai trạng thái này để nhiều trạng thái hơn mức cần thiết sẽ được tạo và kiểm tra. Do đó, chương trình sẽ hết bộ nhớ và thời gian ngay khi số lượng động vật khác nhau lớn hơn. Điều này chỉ được giảm nhẹ một chút bởi thực tế là phiên bản hiện tại sẽ ngừng thêm trạng thái mới sau khi tìm thấy giải pháp


trừ khi tôi hiểu sai những gì bạn nói 4 4 và số lượng bằng nhau cao hơn có giải pháp, tức là (4,4) = WC, C, WC, W, WC, W, WW, W, WC, W, WW, W, WC
JustinM - Tái lập Monica

@PHeze: Sau khi WC,C,WCcó 2 con sói và 1 con gà ở bờ phải. Trò chơi kết thúc
TonMedel

Vâng xấu của tôi, tôi đã hiểu nhầm một phần của vấn đề.
JustinM - Tái lập Monica

5

JavaScript (ES6), 251 264 ... 244 240 byte

Lấy số lượng sói và gà (w, c)và trả về một trong những giải pháp tối ưu, hoặc undefinednếu không có giải pháp.

(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

Định dạng và nhận xét

Chức năng bao bọc:

(                                    // 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

Hàm đệ quy chính:

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

Các trường hợp thử nghiệm


Thử thách nói and finds the smallest number of times the raft has to move across the river.. Vì vậy, tôi không nghĩ rằng đây là một giải pháp hợp lệ
TonMedel

@Arnauld OP trả lời ? Tôi nghĩ rõ ràng rằng bạn chỉ phải đưa ra giải pháp ngắn nhất chứ không phải giải pháp khác.
Erik the Outgolfer

@Arnauld TonMedel là đúng.
0WJYxW9FMN

@Arnauld Nếu bạn thực hiện nó để nó không in ra các giải pháp khác - chỉ là giải pháp ngắn nhất, thì nó sẽ ổn thôi.
0WJYxW9FMN

@ J843136028 Hy vọng tôi đã hiểu đúng lúc này. ^^
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*

Dùng thử trực tuyến

Giải trình:

Về cơ bản chương trình thực hiện BFS và ghi nhớ mọi trạng thái mà nó đạt được để tránh các chu kỳ vô hạn. Các trạng thái làm việc được biểu diễn như [[Wl Cl] [Wr Cr] M1 M2 triệt Mn] trong đó W = sói, C = gà, l = bên trái, r = bên phải, M = di chuyển được thực hiện cho đến nay (ban đầu không có), và các bước di chuyển như "C", "WC" hoặc "WW", v.v (thực tế giống như ["" "C"], ["W" "C"], ["WW" ""], nhưng nó giống nhau khi in). Các trạng thái được nhớ được biểu diễn như [[Wl Cl] [Wr Cr] S] trong đó S là cạnh của thuyền (0 = trái, 1 = phải).

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

Perl 6 , 268 byte

->*@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]//()}

Tạo ra các chuỗi (wolf count, chicken count)trạng thái ngày càng dài hơn cho ngân hàng bên trái và trả về trạng thái đầu tiên phù hợp với tất cả các quy tắc.

Hóa ra cách tiếp cận này không hiệu quả cũng không ngắn gọn, nhưng ít nhất nó cũng rất vui khi viết.
Tôi không nghĩ rằng tôi chưa bao giờ xếp chồng các toán tử meta Z(zip) và X(chéo) trước đây, như ZZ-ZX*ở đây - hơi ngạc nhiên khi nó thực sự hoạt động.

(Các dòng mới chỉ được thêm vào cho mục đích hiển thị và không phải là một phần của số byte.)


0

JavaScript (ES6), 227 237

Về cơ bản, nó thực hiện BFS và ghi nhớ mọi trạng thái mà nó đạt được để tránh các chu kỳ vô hạn. Không giống như @ aditsu, tôi không nghĩ có chỗ nào để chơi gôn

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")

Ít chơi gôn

(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
}

Kiểm tra

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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.