หมาป่าและไก่


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 หรืออะไรบางอย่าง ตาดสับสนกับกระบวนการอื่นนอกเหนือจากที่ดูดี
Magic Octopus Urn

@carusocomputing ฉันจะ แต่ฉันคิดว่ามันจะสับสนมากขึ้นเพราะการป้อนข้อมูลเป็น 3,2 และไม่ใช่ W = 3, C = 2
0WJYxW9FMN

1
หวังทางออกสำหรับไก่
Robert Fraser

คำตอบ:


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`

เพิ่มไปที่การแก้ปัญหาเล็กน้อยสำหรับหมาป่าและไก่เท่านั้นและกรณีพิเศษ hardcoded สำหรับ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 ตัวที่ฝั่งขวา จบเกม
Ton Hospel

ใช่ฉันไม่ดีฉันเข้าใจผิดเป็นส่วนหนึ่งของปัญหา

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

จัดรูปแบบและแสดงความคิดเห็น

ฟังก์ชั่น W Rapper:

(                                    // 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 สหกรณ์ที่จะตอบว่าอะไร ? ฉันคิดว่ามันชัดเจนว่าคุณจะต้องส่งออกทางออกที่สั้นที่สุดไม่ใช่คนอื่น
Erik the Outgolfer

@Anauld Ton Hospel ถูกต้อง
0WJYxW9FMN

@Annauld ถ้าคุณทำเพื่อที่จะไม่ได้พิมพ์โซลูชั่นอื่น ๆ - เพียงแค่ทางออกที่สั้นที่สุดก็ควรจะดี
0WJYxW9FMN

@ J843136028 หวังว่าฉันเข้าใจถูกแล้ว ^^
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 = wolves, 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(ข้าม) มาก่อนเช่น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")

น้อย golfed

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