ล่าม RoboZZle


10

งานของคุณคือการเขียนล่าม RoboZZle หากคุณไม่คุ้นเคยกับเกมนี้โปรดดูวิดีโอที่ robozzle.comหรืออ่านคำอธิบายของฉันด้านล่าง

หุ่นยนต์อาศัยอยู่บนกริดสี่เหลี่ยมของสี่เหลี่ยมสีแดงเขียวน้ำเงินหรือดำ สี่เหลี่ยมสีดำไม่สามารถเข้าถึงได้ คนอื่นสามารถเข้าถึงได้และบางคนก็มีดาว เป้าหมายคือการรวบรวมดาวทั้งหมดโดยไม่ต้องเหยียบบนช่องสี่เหลี่ยมสีดำหรือตกจากแผนที่ หุ่นยนต์ใช้พื้นที่หนึ่งตารางเมตรและหันไปทิศทางใดทิศทางหนึ่ง - ซ้าย, ขวา, ขึ้นหรือลง มันทำตามคำแนะนำเหมือนการประกอบที่จัดกลุ่มเป็นรูทีนย่อย F1, F2, ... , F5 คำสั่งเป็นคู่ของคำกริยา ("ไม่มี", "ถ้าเป็นสีแดง", "ถ้าเป็นสีเขียว", "ถ้าเป็นสีน้ำเงิน") และการกระทำ ("ไปข้างหน้า", "เลี้ยวซ้าย", "เลี้ยวขวา", "วาดสี่เหลี่ยมจัตุรัสสีแดงปัจจุบัน", "ทาสีเขียว", "ทาสีฟ้า", "ไม่ทำอะไรเลย", "เรียก F1", ... , "เรียก F5") การเรียกรูทีนย่อยใช้ stack และสามารถเรียกซ้ำได้ เช่นเดียวกับในการเขียนโปรแกรมทั่วไปหลังจากคำสั่งสุดท้ายของรูทีนย่อยเสร็จสมบูรณ์การดำเนินการจะดำเนินต่อจากจุดที่เรียกรูทีนย่อย การประหารเริ่มต้นจากคำสั่งแรกของ F1 และดำเนินต่อไปจนกระทั่งทั้งหุ่นยนต์ได้เยี่ยมชมช่องสี่เหลี่ยมที่มีดาวทั้งหมดหรือเมื่อหุ่นยนต์เหยียบบนสี่เหลี่ยมสีดำหรือนอกแผนที่หรือมีการดำเนินการคำสั่ง 1,000 ครั้ง (เพรดิเคตที่ล้มเหลว ไม่นับ) หรือไม่มีคำแนะนำในการดำเนินการอีกต่อไป (stack underflow)

ปัจจัยการผลิต:

  • a- เมทริกซ์อักขระขนาด 12x16 (ตามปกติในภาษาของคุณเช่นอาร์เรย์ของสตริง) ที่เข้ารหัสแผนที่ - '#'สำหรับสี่เหลี่ยมที่ไม่สามารถเข้าถึงได้ (สีดำ) '*'สำหรับสี่เหลี่ยมที่มีดาว'.'สำหรับส่วนที่เหลือ

  • c- เมทริกซ์อักขระ 12x16 อธิบายสีของช่องสี่เหลี่ยมที่สามารถเข้าถึงได้ - 'R'(แดง), 'G'(เขียว) หรือ'B'(น้ำเงิน) สี่เหลี่ยมที่ไม่สามารถเข้าถึงได้จะถูกแสดงด้วยตัวอักษรโดยพลการจากทั้งสาม

  • yและx- แถวและคอลัมน์ที่ใช้ 0 ของหุ่นยนต์ a[y][x]รับประกันว่าจะเป็น'.'

  • d- ทิศทางที่หุ่นยนต์จะหัน: 0 1 2 3ผู้มีสิทธิลงซ้ายขึ้นคือต่อ(y,x+1), (y+1,x), (y,x-1),(y-1,x)

  • f- สตริงเดียวการประยุกต์ใช้แบบต่อเนื่องของ F1 ... F5 แต่ละการดำเนินงานเป็น (อาจจะเป็นที่ว่างเปล่า) ลำดับของคู่กริยาการกระทำ (พักได้สูงสุด 10 คู่ต่อ subroutine) '|'สิ้นสุดลงด้วย

    • เพรดิเคต: '_'ไม่มี, 'r'แดง, 'g'เขียว, 'b'น้ำเงิน

    • การดำเนินการ: 'F'ไปข้างหน้า'L'เลี้ยวซ้าย'R'เลี้ยวขวา'r'ทาสีแดง'g'ทาสีเขียว'b'ทาสีฟ้า'1'โทร F1, ... , '5'โทร F5 '_'ไม่ต้องทำอะไรเลย

คุณไม่จำเป็นต้องตั้งชื่อที่คุณป้อนเช่นด้านบน แต่ค่าของพวกเขาจะต้องเป็นไปตามที่ระบุไว้

เอาท์พุท: 1(หรือtrue) ถ้าหุ่นยนต์รวบรวมดาวทั้งหมดตามกฎ0( false) มิฉะนั้น

ตัวอย่าง :

a=["################","################","##*....*...*#.##","##.####.#####.##","##.####.#####.##","##.####*...*#.##","##.########.####","##*........*#.##","################","################","################","################"]
c=["RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR","RRRBBBBRGGGGRRRR","RRBRRRRGRRRRRRRR","RRBRRRRGRRRRRRRR","RRBRRRRRGGGBRRRR","RRBRRRRRRRRGRRRR","RRRBBBBGGGGBRBRR","RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR"]
y=2; x=6; d=2

// and then depending on "f":
f="_FrLg2_1|_FbLrR_2||||" // result:1
f="_FrRg2_1|_FbLrR_2||||" // result:0 (stepped on a black square)
f="_FrLrL_1|_FbLrR_2||||" // result:0 (1000-step limit exceeded)
f="_FrLg2__|________||||" // result:0 (stack underflow)

อีกตัวอย่างหนึ่งที่เกี่ยวข้องกับคำแนะนำ "สี":

a=["#***************","#*###*###*###*##","#*###*###*###*##","***#***#***#***#","***#***#***#***#","*###*###*###*###","***#***#***#***#","***#***#***#***#","***#***#***#***#","*###*###*###*###","*.*#***#***#***#","***#***#***#***#"]
c=["RGGGGGGGGGGGGGGG","RBRRRGRRRGRRRGRR","RBRRRGRRRGRRRGRR","RBRRGGGRGGGRGGGR","BRRRGGGRGGGRGGGR","BRRRGRRRGRRRGRRR","BRRRGGGRGGGRGGGR","RBRRGGGRGGGRGGGR","BRRRGGGRGGGRGGGR","BRRRGRRRGRRRGRRR","BGRRGGGRGGGRGGGR","RBRRGGGRGGGRGGGR"]
y=10; x=1; d=0
f="_2_R_R_1|_FgRgFgFg3rRr4b2_Fgb|_F_F_R|_2_L_r||"
// result:1

หากต้องการสร้างการทดสอบของคุณเองไปที่ตัวต่อจากรายการที่ robozzle.comลองแก้ปัญหา (หรือไม่แก้) กด F12 ในเบราว์เซอร์ของคุณพิมพ์ในคอนโซล JS:

r=robozzle;s=JSON.stringify;with(r.level)console.log('a='+s(Items)+'\nc='+s(Colors)+'\ny='+RobotRow+'\nx='+RobotCol+'\nd='+RobotDir+'\nf='+s(r.encodeSolution()))

และจัดรูปแบบผลลัพธ์ใหม่สำหรับภาษาของคุณ

ชนะสั้นที่สุด ไม่มีช่องโหว่


1
เราสามารถใช้อักขระที่แตกต่างเพื่อแสดงข้อมูลแทนอักขระที่ให้ไว้ได้หรือไม่?
HyperNeutrino

1
สำหรับคำตอบ APL ของคุณต่อความท้าทาย "วนรอบ" คุณสามารถเรียงลำดับค่ามุมสุดท้ายได้โดยลดขนาดที่ซับซ้อน
user202729

1
@ user202729 เอ่อฉันไม่ได้คาดหวังว่าจะมีความคิดเห็นเกี่ยวกับความท้าทายที่นี่ :) ความคิดของคุณใช้งานได้ขอบคุณ! ฉันจะพยายามใช้มันโดยไม่ทำให้ตัวละครน่าอับอายเกินไป
ngn

1
เราสามารถใช้เมทริกซ์ของตัวละครเป็นรายการคู่ของที่ตั้งและตัวละครได้หรือไม่?
0

1
@ 0 'หลักการที่ฉันติดตามที่นี่ (ดูความคิดเห็นของ HyperNeutrino) คือให้อยู่ใกล้ที่สุดกับรูปแบบอินพุตที่ใช้จริงที่ robozzle.com ดังนั้นฉันจึงกลัวว่ามันไม่ควรเป็นรายการคู่
ngn

คำตอบ:


5

Prolog (SWI) , 574 ไบต์

Z*A:-findall(X^Y-D,(nth0(Y,Z,O),nth0(X,O,C),plus(32,C,D)),L),list_to_assoc(L,A).
N^C^G^[P,I|R]^F^X^Y^D:-map_assoc(\=(74),G);N<1e3,get_assoc(X^Y,G,J),J>67,put_assoc(X^Y,G,78,H),T=N+1,((I\=95,(P=95;get_assoc(X^Y,C,P)))->(between(49,53,I),plus(48,M,I),nth1(M,F,Q),append(Q,R,S),T^C^H^S^F^X^Y^D;member(I,`RL`),E is(D-I//3)mod 4,T^C^H^R^F^X^Y^E;I=70,(D=0,U is X+1;D=1,V is Y+1;D=2,U is X-1;D=3,V is Y-1),(U=X;V=Y),T^C^H^R^F^U^V^D;I>97,put_assoc(X^Y,C,I,W),T^W^H^R^F^X^Y^D);N^C^H^R^F^X^Y^D).
A+C+F+L:-A*G,C*B,split_string(F,"|","",P),maplist(string_codes,P,[M|N]),0^B^G^M^[M|N]^L.

ลองออนไลน์!

คำจำกัดความนี้จะกำหนดว่าเมื่อมีการเรียกสำเร็จถ้าดาวทั้งหมดถูกรวบรวมและล้มเหลวเป็นอย่างอื่น a+c+f+x^y^d.คำกริยาจะเกิดการขัดแย้งเป็นเช่น: aและcจะต้องเป็นรายการของสตริงที่ยกมา backtick ในขณะที่fจะต้องเป็นสตริงที่ยกมาสองครั้ง

คำอธิบาย

โปรแกรมนี้มีสามภาค, */2, และ^/2 +/2เพรดิเคต*/2ที่กำหนดไว้ในบรรทัดแรกรับผิดชอบส่วนของการประมวลผลอินพุต เพรดิเคตจะ^/2คำนวณซ้ำว่าหุ่นยนต์เคลื่อนที่ทีละขั้นตอนอย่างไรและประสบความสำเร็จถ้าหุ่นยนต์รวบรวมดาวทั้งหมดอย่างถูกกฎหมายและล้มเหลวเป็นอย่างอื่น เพรดิเคต+/2เป็นเพรดิเคตหลักของโปรแกรมและเตรียมอินพุตสำหรับเพรดิเคต^/2ด้วยความช่วยเหลือจากเพ*/2รดิเคต โปรดทราบว่าแต่ละภาคแสดงใช้เทคนิคเพียงสองข้อโต้แย้ง แต่ใช้ตัวดำเนินการและการจับคู่รูปแบบพวกเขาสามารถทำงานราวกับว่าพวกเขามีข้อโต้แย้งมากขึ้น (ฉันพูดถึงปรากฏการณ์นี้ในเชิงลึกที่นี่ )

*/2

Z*A:-findall(X^Y-D,(nth0(Y,Z,O),nth0(X,O,C),plus(32,C,D)),L),list_to_assoc(L,A).

เพรดิเคตนี้ใช้สองอาร์กิวเมนต์ รายการแรกคือรายการของรหัสอักขระ (นี่คือวิธีที่ Prolog วิเคราะห์สตริงที่อ้างถึง backtick) ที่สองคือแผนที่เชื่อมโยงจากจุดในแผนที่ 12x16 (แสดงเป็นX^Y) ถึง 32 บวกรหัสตัวละครที่เก็บไว้ที่จุดนั้นในรายการของรายการของรหัสตัวละคร 32 ถูกเพิ่มเข้ากับรหัสอักขระแต่ละตัวเพื่อให้เมทริกซ์สีจะเปลี่ยนอักขระสีตัวพิมพ์ใหญ่เป็นอักขระสีตัวพิมพ์เล็ก

findall/3วิธีการนี้จะเป็นสร้างรายการของคู่ของจุดและรหัสตัวอักษรที่จุดที่ใช้ จากนั้นจะใช้list_to_assoc/2เพื่อสร้างแผนที่เชื่อมโยงที่สอดคล้องกันจากจุดไปยังรหัสตัวอักษร ณ จุดนั้น

เพรดิเคตfindall/3เป็นบิลด์อินจะใช้ "เทมเพลต" เป็นอาร์กิวเมนต์แรกเป้าหมายเป็นอาร์กิวเมนต์ที่สองและรายการเป็นอาร์กิวเมนต์ที่สาม เพรดิเคตจะเติมรายการด้วยค่าที่เป็นไปได้ทั้งหมดของเทมเพลตที่ทำให้เป้าหมายสำเร็จ เนื่องจากความสำคัญประกอบแม่แบบที่จะถูกส่งไปfindall/3ในจะแยกเป็น*/2 (X^Y)-Dตัว-ดำเนินการแทนค่าสองค่าใน Prolog ดังนั้นเทมเพลตจึงแสดงตำแหน่งของจุด ( X^Y) ที่จับคู่กับ 32 บวกรหัสอักขระของจุด ( D) โปรดทราบว่า^ใช้ในการเป็นตัวแทนของจุดที่ไม่ได้เชื่อมต่อกับภาค^/2แสดง

ให้เราพิจารณาเป้าหมายที่ส่งผ่านไปยังเพfindall/3รดิเคต

nth0(Y,Z,O),nth0(X,O,C),plus(32,C,D) % Note that the O (oh) is not a 0 (zero)

เป้าหมายประกอบด้วยสามภาคซึ่งแต่ละภาคจะต้องประสบความสำเร็จเพื่อให้เป้าหมายสำเร็จ เพรดิเคตnth0/3ที่ใช้สองครั้งจะถูกใช้เพื่อรับค่าที่ดัชนีเฉพาะของรายการ ( 0ในชื่อระบุว่าเป็นศูนย์ดัชนี) การเรียกครั้งแรกไปที่มันจะเก็บYแถว th ของเมทริกซ์อักขระในOขณะที่การเรียกที่สองจะเก็บXอักขระ th ในแถวCนั้น เพรดิเคตสุดท้ายplus/3สำเร็จถ้าอาร์กิวเมนต์สองตัวแรกรวมกับอาร์กิวเมนต์ที่สาม สิ่งนี้ใช้เพื่อทำให้รหัสตัวละครในคู่มากกว่า 32 รหัสตัวละครในเมทริกซ์ตัวละครซึ่งตามที่ระบุข้างต้นจะเปลี่ยนตัวอักษรตัวพิมพ์ใหญ่ทั้งหมดเป็นตัวอักษรตัวเล็ก

ในที่สุดก็findall/3เก็บX^Y-Dชุดค่าผสมทั้งหมดที่ทำให้เป้าหมายประสบความสำเร็จในรายการLที่สร้างแผนที่เชื่อมโยง

เร็ว ๆ นี้ ...


4

JavaScript (ES6), 298 276 264 ไบต์

บันทึก 8 ไบต์ขอบคุณ @ngn

รับอินพุตเป็น(a,c,x,y,d,f)โดยที่aและcเป็นอาร์เรย์ของอักขระ ผลตอบแทนหรือ01

(a,c,x,y,d,f,k=1e3)=>(g=(F,p=0,s=f.split`|`[F],r=a[y])=>!k|!r|x&16||r[x]<'$'?2:/\*/.test(a)?(r[x]=o=0,(I=s[p+1],P=s[p])&&(P<'b'|P==c[y][x].toLowerCase()&&I!='_'&&k--?+I?o=g(I-1):I=='L'?d--:I=='R'?d++:I<'b'?y+=(d&=3,x-=~-d%2,2-d)%2:c[y][x]=I:0,o||g(F,p+2))):1)(0)&1

กรณีทดสอบ

แสดงความคิดเห็น

(                                           // main function taking:
  a, c, x, y, d, f,                         //   - input variables
  k = 1e3                                   //   - k = instruction counter
) => (                                      //
  g = (                                     // g = recursive execution function, taking:
    F,                                      //   - F = subroutine id
    p = 0,                                  //   - p = instruction pointer
    s = f.split`|`[F],                      //   - s = instruction string
    r = a[y]                                //   - r = current row in a[]
  ) =>                                      //
    !k |                                    // if we've executed 1000 instructions
    !r | x & 16 ||                          // or we've felt out of the map
    r[x] < '$' ?                            // or we've reached a black square:
      2                                     //   exit with error code 2
    :                                       // else:
      /\*/.test(a) ? (                      //   if there are still some stars:
        r[x] = o = 0,                       //     mark the current cell as visited
        (I = s[p + 1], P = s[p]) &&         //     I = instruction, P = predicate
        (                                   //     if P is defined:
          P < 'b' |                         //       if the predicate is '_'
          P == c[y][x].toLowerCase()        //       or it matches the color of the cell
          && I != '_'                       //       and the instruction is not '_',
          && k-- ?                          //       then decrement k and:
            +I ?                            //         if I is '1' ... '5':
              o = g(I - 1)                  //           process call to subroutine
            :                               //         else:
              I == 'L' ?                    //           if I is 'L':
                d--                         //             turn left
              :                             //           else:
                I == 'R' ?                  //             if I is 'R':
                  d++                       //               turn right
                :                           //             else:
                  I < 'b' ? (               //               if I is not a color:
                    y += (                  //                 I must be 'F',
                      d &= 3,               //                 so make the bot advance
                      x -= ~-d % 2,         //                 by updating x
                      2 - d                 //                 and y
                    ) % 2                   //
                  ) :                       //               else:
                    c[y][x] = I             //                 paint the current cell
          :                                 //       else:
            0,                              //         do nothing
          o ||                              //       provided that o is equal to 0,
          g(F, p + 2)                       //       go on with the next instruction
        )                                   //     end of instruction execution
      ) :                                   //   else:
        1                                   //     success: return 1
  )(0) & 1                                  // initial call to the subroutine F1

x+='2101'[d&3]-1,y+='1210'[d&3]-1->d&=3,x+=(1-d)%2,y+=(2-d)%2
ngn

1
xเปลี่ยนแปลงโดยมากที่สุด 1 ดังนั้นฉันคิดว่าคุณสามารถแทนที่x&~15ด้วยx&16
ngn

1

APL (Dyalog Classic) , 236 233 ไบต์

-3 ขอบคุณ Erik the Outgolfer

ตอนนี้ฉันได้ให้โบนัสไปแล้วฉันกำลังโพสต์ตัวอย่างโซลูชันสำหรับความท้าทายของตัวเอง มีห้องสำหรับการปรับปรุงที่นี่ - อย่าลังเลที่จะคัดลอกและเล่นกอล์ฟเพิ่มเติม

a c r d f←⎕⋄c819cF0,('|'1f)/⍳≢ftn0
{~(⊂r)∊⍳⍴a:0'#'=ra:0p q2f↓⍨⊃⌽t⋄(_p'|')∧×≢t:0_:∇t↓←¯1⋄(⊃⌽t)+←2⋄~p'_',rc:∇0n+←1n>999:0⋄(ra)←'.'⋄~'*'a:1r+←(q'F'11 90j1*dd+←4|'.R.L'qq'rgb':∇(rc)←qq∊⎕d:∇t,←F[⍎q]⋄∇0}0

ลองออนไลน์!

เหมือนกับข้างต้นขยายด้วยความคิดเห็น:

io0                    0-based indices (not counted in the score)
a c r d f←⎕              decompose eval'ed input (⎕) into variables
c←819⌶c                 ⍝ make c lowercase
F←0,('|'=¯1⌽f)/⍳≢f      ⍝ split f at the '|'-s
t←n←0                   ⍝ t:stack, n:step counter
{                       ⍝ lambda
  ~(⊂r)∊⍳⍴a:0           ⍝ if the robot is off the map, return 0
  '#'=r⌷a:0             ⍝ if the robot is on a wall, return 0
  p q2f↓⍨⊃⌽t           current instruction - p:predicate, q:action
  (_p'|')∧1≥≢t:0       if at end of func and stack is empty, return 0
  _:∇t↓←¯1               if at end of func, pop from stack and recurse
  (⊃⌽t)+←2               increment program counter (top of stack)
  ~p'_',rc:∇0          if predicate doesn't match cell colour, recurse
  n+←1⋄n>999:0          ⍝ if too meany steps, return 0
  (r⌷a)←'.'             ⍝ consume star
  ~'*'∊a:1              ⍝ if no more stars left, return 1
  r+←(q≡'F')×11 9○0j1*d ⍝ if action is F, move forward
  d+←4|'.R.L'⍳q         ⍝ if action is L or R, turn left or right
  q∊'rgb':∇(r⌷c)←q      ⍝ if action is paint (r,g,b), do it
  q∊⎕d:∇t,←F[⍎q]        ⍝ if action is F1...F5, push on stack and recurse
  ∇0                    ⍝ action is nop (_), recurse
}0                      ⍝ call the lambda (argument will be ignored)


@EriktheOutgolfer ใช้การเปลี่ยนแปลงขอขอบคุณ
ngn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.