Kurtlar ve Tavuklar


15

Bir nehir var ve nehrin bir tarafında kurtlar ve tavuklar var. Bir salları var ve hepsinin diğer tarafa gitmesi gerekiyor. Bununla birlikte, sal kendi başına seyahat edemez. Sal, ikiden fazla hayvan varsa, batar. Nehrin soğuk ve kirli olması nedeniyle hiçbir hayvan ıslanmak istemiyor. Hiçbir hayvan nehrin üzerinden atlayamaz veya uçamaz. Ayrıca, bir tarafta tavuk varsa, o tarafta tavuklardan daha fazla kurt olamaz - kurtlar daha sonra tavukları yemeye karar verecektir. Bu, salda iki kurdu bir tavukla bir tarafa alamayacağınız anlamına gelir.

Göreviniz girdi olarak birkaç kurt ve birkaç tavuk (kurt sayısına eşit veya daha fazla) alan ve salın nehir boyunca hareket etmesinin en az sayısını bulan bir program / işlev yapmaktır. Görev mümkün değilse, program / işlev boş bir dize çıktısı almalı / döndürmelidir. Daha sonra bunun nasıl yapıldığına ilişkin bir yöntemi aşağıdaki şekilde yazdırır / döndürür:

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

Çıkarabileceğiniz gibi, sal otomatik olarak alternatif yönlerde hareket edecektir (sol ve sağ, ilk bir veya iki hayvan nehri geçtikçe soldan sağa doğru). Bunun çıktısı / iadesi gerekmez. Çıktıdaki 'W', 'C', 'CW', 'CC' veya 'WW' aşağıdakilerden en az biri ile ayrılabilir:

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

Alternatif olarak, yönergeleri bir listede öğe olarak saklayabilirsiniz (boş bir liste çözüm olmadığı anlamına gelir).

Test senaryoları (çıktılar virgülle ayrılmış - girdi biçimi alır 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

Kodunuzu mümkün olduğunca bayt cinsinden kısaltmaya çalışın.


(3,2) için çözüm?
Sihirli Ahtapot Urn

@carusocomputing Çalışmıyor, çünkü tavuklardan daha fazla kurt var. Yani çözüm yok.
0WJYxW9FMN

Ahh ... Belki girdileri W = 3, C = 2 ya da başka bir şey olarak etiketleyin; işlenmesi biraz kafa karıştırıcıydı, bunun dışında havalı görünüyor.
Sihirli Ahtapot Urn

@ carusocomputing Yapardım, ama daha karmaşık olacağını düşünüyorum çünkü giriş 3,2 ve W = 3, C = 2 değil.
0WJYxW9FMN

1
Sorununa çözüm umuduyla tavuk
Robert Fraser

Yanıtlar:


5

Perl, 179 165 164 163 157 156 bayt

İçin +4 içerir -p

STDIN'de kurtlar ve ardından tavuklar verin

river.pl <<< "2 3"

Her satıra tekne içeriğini verir. Bu örnek için:

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

Gösterilen, ancak onların yerini olarak çalışır \xhhve \nonların edebi sürümleri tarafından talep edilen puanı almak için.

Bu muhtemelen genel durumu çözen bir program tarafından yenilecektir (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`

Buna sadece kurtlar ve sadece tavuklar için önemsiz çözümlerin yanı sıra 2 2ve 3 3( 4 4ve daha yüksekleri için sabit kodlu özel bir durum) da ekleyin . Ama bu sıkıcı bir program olurdu.

açıklama

Alanın geçerli durumu aşağıdakilerden oluşan tek bir dize olarak saklanır:

  • w tekne ile bankada bir kurt için
  • c tekne ile bankada bir tavuk için
  • \x88(biraz ters döndü w) diğer bankadaki bir kurt için
  • \x9c(biraz ters c) diğer bankadaki bir tavuk için
  • PSağ sıra için teknenin yan tarafını , sol sıra için başlangıç \xafbitini (bit Ptarafı) gösteren karakter
  • yeni satır \n
  • kadar yapılmış tüm hamle şimdi, yeni satır olduğu gibi mesela şey sonlandırıldı WC\nW\nWC\nC\n(haber Ws ve Cburada büyük harf bulunmaktadır)

Dizi @Ferişilebilir tüm durumları içerecektir. Başlangıç ​​dizesi tarafından başlatılırwolves times "w", chickens times "c", \xaf \n

Program daha sonra döngüler @Fsırasında genişletilecek ve böylece yeni durumlar da işlenecektir. Her element için şunları yapar:

  • İlkinin solundaki \nhayvanların ve teknenin mevcut konumunu temsil eden ip kısmına bakın . Atlamadan önce görülmüşse$a{$`x/\n/}++
  • Herhangi bir tarafta daha fazla kurtla birlikte tavuk olup olmadığını kontrol edin. Öyleyse atlagrep(y/c//<y/w//&/c/,$_,~$_)
  • Teknenin tüm hayvanlarla birlikte uzak tarafta olup olmadığını kontrol edin. Eğer öyleyse bir çözümümüz var. Bunu $\saklayın ve bulunan ilk çözüm en kısa olduğu için saklayın$\||=$' x/^\w*\n/
  • Aksi takdirde, teknenin yan tarafında 1 veya 2 hayvan seçmenin tüm yollarını deneyin. Bunlar cve wkarakterleri. (Diğer taraftaki hayvanlar eşleşmez \w) /(\w?)(.*)(c|w)(.+)\n(?{code})^/. Sonra \ntekne için seçilen hayvanlar hariç tüm ipi biraz ters çevirin push@F,$1.$3.~"$`$2$4\xf5". Seçilen hayvanları hamlelere ekleyerek onları ekleyin:uc"$'$1$3\n"

Hayvan seçim süreci, onları temsil eden ip parçasını etkili bir şekilde birçok şekilde karıştırır. Yani örneğin wcwcve wwccher ikisi de 2 kurt ve 2 tavuğu temsil edebilir. Durum kontrolü $a{$`x/\n/}++, bu iki durumu gerekenden çok daha farklı bir şekilde ayırt edecektir, bu nedenle gerekenden çok daha fazla durum üretilecek ve kontrol edilecektir. Bu nedenle, farklı hayvanların sayısı arttıkça programın belleği ve zamanı bitecektir. Bu, mevcut sürümün bir çözüm bulunduğunda yeni durumlar eklemeyi durduracağı gerçeği ile biraz azaltılır.


4 4 ve daha yüksek eşit sayıların söylediklerini yanlış anlamadım çözümler var, yani (4,4) = WC, C, WC, W, WC, W, WW, W, WC, W, WW, W, WC

@Phaeze: WC,C,WCSağ tarafta 2 kurt ve 1 tavuk var. Oyun bitti
Ton Hospel

Evet, kötülerim sorunun bir kısmını yanlış anladım.

4

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

Kurtların ve tavukların sayısını alır ve (w, c)en uygun çözümlerden birini veya çözüm undefinedyoksa döndürür .

(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

Biçimlendirilmiş ve yorumlanmış

Sarıcı işlevi:

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

Ana özyinelemeli fonksiyon:

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

Test senaryoları


Zorluk diyor and finds the smallest number of times the raft has to move across the river.. bu yüzden bunun geçerli bir çözüm olduğunu düşünmüyorum
Ton Hospel

@Arnauld OP ne cevap verecek ? Bence sadece en kısa çözümü çıkarmanız gerekiyor, diğerleri değil.
Outgolfer Erik

@Arnauld Ton Hospel haklı.
0WJYxW9FMN

@Arnauld Diğer çözümleri yazdırmayacak şekilde yaparsanız - en kısa çözüm, o zaman iyi olmalıdır.
0WJYxW9FMN

Umarım bu sefer doğru anladım. ^^
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*

Çevrimiçi deneyin

Açıklama:

Temel olarak program bir BFS yapar ve sonsuz döngülerden kaçınmak için ulaştığı her durumu hatırlar. Çalışma durumları, W = kurtlar, C = tavuklar, l = sol taraf, r = sağ taraf, M = şimdiye kadar yapılan hamle (başlangıçta hiçbiri), [[Wl Cl] [Wr Cr] M1 M2… Mn] gibi temsil edilir, ve hareketler "C", "WC" veya "WW" vb. gibidir (pratik olarak daha çok ["" "C"], ["W" "C"], ["WW" ""] gibi ama aynı yazdırırken). Hatırlanan durumlar [[Wl Cl] [Wr Cr] S] gibi temsil edilir, burada S teknenin bulunduğu taraftır (0 = sol, 1 = sağ).

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 bayt

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

Giderek daha uzun zincirler üretir (wolf count, chicken count)Sol banka için devlet ve tüm kurallara uyan ilk döndürür.

Bu yaklaşımın ne verimli ne de özlü olduğu ortaya çıktı, ancak en azından yazmak eğlenceliydi.
Daha önce hiç Z(zip) ve X(cross) meta operatörleri istiflemediğimi sanmıyorum ZZ-veZX* burada burada olduğu - gerçekten işe yaradı.

(Yeni satırlar yalnızca görüntüleme amacıyla eklenir ve bayt sayısının bir parçası değildir.)


0

JavaScript (ES6), 227 237

Temel olarak bir BFS yapar ve sonsuz döngülerden kaçınmak için ulaştığı her durumu hatırlar. @ Aditsu'nun aksine, golf oynamak için yer olduğunu düşünmüyorum

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

Daha az golf

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

Ölçek

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>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.