Вовки та кури


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)?
Magic Octopus Urn

@carusocomputing Це не працює, тому що вовків більше, ніж курей. Тож рішення немає.
0WJYxW9FMN

Ааа ... Можливо, позначте входи як W = 3, C = 2 або щось таке; був незрозумілий процес, окрім того, що це виглядає круто.
Чарівна восьминога урна

@carusocomputing Я б хотів, але думаю, що це було б більш заплутано, оскільки вхід 3,2, а не W = 3, C = 2.
0WJYxW9FMN

1
Сподіваючись на рішення курячого
Роберт Фрейзер

Відповіді:


5

Perl, 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 2та 3 3( 4 4і вище не мають рішення). Але це була б нудна програма.

Пояснення

Поточний стан поля зберігається як один рядок, що складається з:

  • w за вовка на березі з човна
  • c для курки на березі з човна
  • \x88(трохи перевернуто w) для вовка на іншому березі
  • \x9c(трохи оберненою c) для курки на іншому березі
  • Символ, який вказує на бічну сторону човна 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 тварин на боці з човном. Це cі wсимволи. (Тварини з іншого боку не збігаються \w) /(\w?)(.*)(c|w)(.+)\n(?{code})^/. Потім біт переверніть всю струну перед \nвинятком тварин, яких відібрали для човна push@F,$1.$3.~"$`$2$4\xf5". Додайте вибраних тварин до ходів, додавши їх верхнє:uc"$'$1$3\n"

Процес відбору тварин ефективно переміщує струнну частину, представляючи їх багатьма способами. Так, наприклад, wcwcі wwccобидва можуть представити 2 вовків і 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 курка. Гра закінчена
Тон Євангелія

Так, погано, я неправильно зрозумів частину проблеми.

4

JavaScript (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.. тому я не думаю, що це правильне рішення
Тон Євангелія

@Arnauld ОП, щоб відповісти на що ? Я думаю, що зрозуміло, що потрібно виводити лише найкоротші рішення, а не інші.
Ерік Аутгольфер

@Arnauld Тон Євангелія має рацію.
0WJYxW9FMN

@Arnauld Якщо ви зробите так, щоб він не роздруковував інші рішення - просто найкоротше рішення, тоді це повинно бути добре.
0WJYxW9FMN

@ J843136028 Сподіваюся, я цього разу зрозуміла. ^^
Арнольд

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

Perl 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(zip) та X(cross) метаоператори, як ZZ-і ZX*тут - начебто здивований, що насправді спрацювало.

(Нові рядки просто додаються для відображення і не входять до числа байтів.)


0

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.