Lupi e Polli


16

C'è un fiume e ci sono lupi e galline su un lato del fiume. Hanno una zattera e devono tutti arrivare dall'altra parte. Tuttavia, la zattera non può viaggiare da sola. La zattera affonderà se ci sono più di due animali. Nessuno degli animali vuole bagnarsi perché il fiume è freddo e sporco. Nessuno degli animali può saltare o volare sopra il fiume. Inoltre, se ci sono polli da una parte, non ci possono essere più lupi da quella parte di quelli da quella parte - i lupi decideranno quindi di mangiare le galline. Ciò significa che non puoi portare due lupi sulla zattera da un lato con un pollo.

Il tuo compito è creare un programma / funzione che impieghi un numero di lupi e un numero di polli (maggiore o uguale al numero di lupi) come input e trova il minor numero di volte in cui la zattera deve muoversi attraverso il fiume. Se l'attività non è possibile, il programma / funzione dovrebbe generare / restituire una stringa vuota. Quindi stamperà / restituirà un metodo su come farlo nel modo seguente:

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

Come puoi dedurre, la zattera si sposterà automaticamente in direzioni alternate (sinistra e destra, a partire da sinistra a destra quando i primi uno o due animali attraversano il fiume). Questo non deve essere emesso / restituito. 'W', 'C', 'CW', 'CC' o 'WW' nell'output possono essere separati da almeno uno dei seguenti:

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

In alternativa, è possibile memorizzare le indicazioni come elementi in un elenco (un elenco vuoto significa nessuna soluzione).

Casi di test (output separato da virgole - l'input assume la forma 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

Cerca di rendere il tuo codice il più breve possibile in byte.


La soluzione per (3,2)?
Magic Octopus Urn,

@carusocomputing Non funziona, perché ci sono più lupi che galline. Quindi non c'è soluzione.
0WJYxL9FMN

Ahh ... Forse etichettare gli ingressi come W = 3, C = 2 o qualcosa del genere; è stato un po 'confuso da elaborare, a parte questo sembra bello.
Magic Octopus Urn,

@carusocomputing Lo farei, ma penso che sarebbe più confuso perché l'ingresso è 3,2 e non W = 3, C = 2.
0WJYxL9FMN

1
Sperando in una soluzione nel pollo
Robert Fraser,

Risposte:


6

Perl, 179 165 164 163 157 156 byte

Include +4 per -p

Dai lupi seguiti da polli su STDIN

river.pl <<< "2 3"

Emette il contenuto dell'imbarcazione per riga. Per questo esempio fornisce:

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

Funziona come mostrato, ma sostituisci \xhhe \ncon le loro versioni letterali per ottenere il punteggio richiesto.

Questo sarà probabilmente battuto da un programma che risolve il caso generale (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`

Aggiungete a ciò le banali soluzioni per soli lupi e solo polli e un caso speciale hardcoded per 2 2e 3 3( 4 4e superiori non hanno soluzione). Ma sarebbe un programma noioso.

Spiegazione

Lo stato corrente del campo è memorizzato come una singola stringa composta da:

  • w per un lupo sulla riva con la barca
  • c per un pollo sulla riva con la barca
  • \x88 (bit invertito w ) per un lupo sull'altra sponda
  • \x9c(bit invertito c) per un pollo sull'altra sponda
  • Un personaggio che indica il lato su cui si trova la barca Pper la riva destra, \xaf(bit invertito P) per la riva sinistra (lato iniziale)
  • una nuova riga \n
  • tutte le mosse che sono state fatte fino ad ora sono terminate con una nuova riga, ad esempio qualcosa di simile WC\nW\nWC\nC\n(notare le Ws e Csono maiuscole qui)

L'array @Fconterrà tutti gli stati raggiungibili. Viene inizializzato dalla stringa inizialewolves times "w", chickens times "c", \xaf \n

Il programma quindi @Fesegue il loop su ciò che verrà esteso durante il loop in modo da elaborare anche i nuovi stati. Per ogni elemento quindi fa:

  • Guarda la parte di stringa a sinistra della prima \n che rappresenta la posizione corrente degli animali e della barca. Se questo è stato visto prima di saltare$a{$`x/\n/}++
  • Controlla se ci sono polli insieme a più lupi su ogni lato. Salta se è cosìgrep(y/c//<y/w//&/c/,$_,~$_)
  • Controlla se la barca è il lato opposto insieme a tutti gli animali. In tal caso, abbiamo una soluzione. Conservalo $\e conservalo dal momento che la prima soluzione trovata è la più breve$\||=$' x/^\w*\n/
  • Altrimenti, prova tutti i modi per selezionare 1 o 2 animali sul lato della barca. Questi sono i personaggi ce w. (Gli animali dall'altra parte non combaciano \w) /(\w?)(.*)(c|w)(.+)\n(?{code})^/. Quindi muovere in senso inverso l'intera corda prima \ndegli animali selezionati per la barca push@F,$1.$3.~"$`$2$4\xf5". Aggiungi gli animali selezionati alle mosse aumentandole:uc"$'$1$3\n"

Il processo di selezione degli animali mescola efficacemente la parte di stringa che li rappresenta in molti modi. Quindi, ad esempio, wcwce wwccpuò ottenere sia per rappresentare 2 lupi e 2 polli. Il controllo dello stato $a{$`x/\n/}++distinguerà inconsapevolmente questi due tanti più stati del necessario che verranno generati e controllati. Pertanto, il programma esaurirà la memoria e il tempo non appena il numero di diversi animali aumenta. Ciò è mitigato solo un po 'dal fatto che la versione corrente smetterà di aggiungere nuovi stati una volta trovata una soluzione


a meno che non fraintenda quello che stai dicendo 4 4 e un numero uguale uguale hanno soluzioni, cioè (4,4) = WC, C, WC, W, WC, W, WW, W, WC, W, WW, W, WC
JustinM - Ripristina Monica il

@Phaeze: dopo WC,C,WCci sono 2 lupi e 1 pollo sulla riva destra. Game over
Ton Hospel,

Sì, mio ​​male, ho frainteso parte del problema.
JustinM - Ripristina Monica il

5

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

Prende il numero di lupi e polli (w, c)e restituisce una delle soluzioni ottimali, o undefinedse non c'è soluzione.

(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

Formattato e commentato

Funzione wrapper:

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

Principale funzione ricorsiva:

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

Casi test


La sfida dice and finds the smallest number of times the raft has to move across the river.. quindi non credo che questa sia una soluzione valida
Ton Hospel,

@Arnauld L'OP per rispondere cosa ? Penso che sia chiaro che devi solo produrre la soluzione più breve, non altre.
Erik the Outgolfer,

@Arnauld Ton Hospel ha ragione.
0WJYxL9FMN

@Arnauld Se lo fai in modo che non stampi altre soluzioni - solo la soluzione più breve, allora dovrebbe andare bene.
0WJYxL9FMN

@ J843136028 Speriamo di aver capito bene questa volta. ^^
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*

Provalo online

Spiegazione:

Fondamentalmente il programma esegue un BFS e ricorda ogni stato raggiunto per evitare cicli infiniti. Gli stati di funzionamento sono rappresentati come [[Wl Cl] [Wr Cr] M1 M2… Mn] dove W = lupi, C = polli, l = lato sinistro, r = lato destro, M = mosse effettuate finora (inizialmente nessuna), e le mosse sono come "C", "WC" o "WW" ecc. (praticamente più come ["" "C"], ["W" "C"], ["WW" ""], ma è lo stesso durante la stampa). Gli stati ricordati sono rappresentati come [[Wl Cl] [Wr Cr] S] dove S è il lato con la barca (0 = sinistra, 1 = destra).

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

Genera catene di (wolf count, chicken count)stati sempre più lunghe per la riva sinistra e restituisce la prima che soddisfa tutte le regole.

Risulta che questo approccio non è né efficiente né molto conciso, ma almeno è stato divertente scrivere.
Non credo di non aver mai accatastato i meta-operatori Z(zip) e X(incrociati) prima, come il qui ZZ-e ZX*qui - un po 'sorpresi che in realtà ha funzionato.

(Le nuove righe vengono appena aggiunte a scopo di visualizzazione e non fanno parte del conteggio dei byte.)


0

JavaScript (ES6), 227 237

Fondamentalmente fa un BFS e ricorda ogni stato che ha raggiunto al fine di evitare cicli infiniti. A differenza di @aditsu, non credo che ci sia spazio per il golf

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

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

Test

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>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.