ทำ BackFlip สำหรับ ais523!


16

ความท้าทายนี้เป็นรางวัลสำหรับais523สำหรับการชนะหมวด " Rookie of the Year " ใน " Best of PPCG 2016 " ขอแสดงความยินดี!


BackFlipเป็นภาษาการเขียนโปรแกรมลึกลับที่ทำโดยผู้ใช้ais523ผู้สร้างได้ดีกว่า 30 esolangs ที่น่าสนใจอื่น ๆรายการ

BackFlip เป็นภาษา 2D เช่นBefungeหรือ> <>ที่ตัวชี้คำแนะนำลัดไปตามตารางข้อความ (โปรแกรม) เลื่อนขึ้นลงซ้ายซ้ายและขวาเปลี่ยนทิศทางขึ้นอยู่กับตัวละครที่ใช้ ในทางกลับกันกริดในโปรแกรม BackFlip จะเปลี่ยนไปในขณะที่มันกำลังเคลื่อนที่อยู่เช่นAnt ของ Langtonแลงตันของมด

สำหรับความท้าทายนี้คุณอาจสมมติว่าโปรแกรม BackFlip เป็นตารางสี่เหลี่ยมของข้อความเสมอ (ทุกบรรทัดมีความยาวเท่ากัน) ขนาด 1 × 1 อย่างน้อยที่สุดมีเพียงอักขระ./\<>^Vเท่านั้น ( .ใช้สำหรับการมองเห็นมากกว่าที่ว่าง) ความหมาย BackFlip ที่เราจะใช้ที่นี่เหมือนกับสเปคดั้งเดิมสเปคเดิม

ตัวชี้คำสั่ง (IP) ใน BackFlip เริ่มต้นเสมอที่มุมซ้ายบนของโปรแกรมมุ่งหน้าไปทางขวาเสมอ คำสั่งมีสามประเภทที่สามารถพบได้:

  1. .เป็น no-op IP ยังคงดำเนินต่อไปในทิศทางที่เป็นไป No-op ยังคงไม่มีการใช้งาน

  2. /และ\กระจก พวกเขาสะท้อนให้เห็นถึงทรัพย์สินทางปัญญาในทิศทางที่ระบุโดยมุมของพวกเขาแล้วพวกเขาเปลี่ยนเป็นชนิดอื่น ๆ ของกระจก

    • ตัวอย่างเช่นถ้าหัว IP ที่เหลือเป็น\ก็จะเริ่มย้ายขึ้นไปแทนซ้ายและกลายเป็น\/
  3. <, >, ^และVมีลูกศร พวกเขาเปลี่ยนเส้นทาง IP ไปยังทิศทางที่พวกเขาชี้ไปในแล้วพวกเขาเปลี่ยนเป็นลูกศรที่ชี้ไปในทิศทางที่ IP ที่มาจาก (ตรงข้ามกับทิศทาง IP ถูกย้าย)

    • ตัวอย่างเช่นถ้า IP หัวลง>มันจะเริ่มย้ายขวาแทนที่จะลงและ>กลายเป็น^เพราะนั่นคือทิศทางที่ IP มาจาก

โปรแกรม BackFlip จะหยุดทำงานเมื่อ IP เคลื่อนออกจากขอบเขตนั่นคือดับลงที่กริด ปรากฎว่าโปรแกรม BackFlip ทั้งหมดจบลงในที่สุดเพราะลูปไม่มีที่สิ้นสุดเป็นไปไม่ได้ (คุณอาจถือว่านี่เป็นเรื่องจริง)

เป้าหมายของคุณในการท้าทายนี้คือการเขียนโปรแกรมหรือฟังก์ชั่นที่ใช้ในโปรแกรม BackFlip และส่งออกจำนวนการเคลื่อนไหวที่ตัวชี้คำสั่งใช้ก่อนที่โปรแกรมจะยุติ นั่นคือIP ใช้เวลากี่ขั้นตอนในการเรียกใช้โปรแกรมหรือไม่ ซึ่งรวมถึงขั้นตอนเริ่มต้นสู่กริดและขั้นตอนสุดท้ายของมัน

ตัวอย่างเช่นตัวชี้คำสั่งใช้เวลา 5 ขั้นตอนในตารางเล็ก ๆ น้อย ๆ....:

 ....  <- empty 4×1 grid
012345 <- step number of the IP

ดังนั้นการส่งออกจะมี....5

ในตาราง 4 × 2 ที่ซับซ้อนมากขึ้น

\...
\.><

IP ออกจากกริดในขั้นตอนที่ 9 ดังนั้นเอาต์พุตคือ9:

step  grid  IP position (@)
0     \...  @....
      \.><   ....

1     \...   @...
      \.><   ....

2     /...   ....
      \.><   @...

3     /...   ....
      /.><   .@..

4     /...   ....
      /.><   ..@.

5     /...   ....
      /.<<   ...@

6     /...   ....
      /.<<   ..@.

7     /...   ....
      /.><   .@..

8     /...   ....
      /.><   @...

9     /...   ....
      \.><   ....
             @

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ

คุณอาจรับอินพุตเป็นอาร์เรย์ของบรรทัดหรือเมทริกซ์ของอักขระแทนสตริงหลายบรรทัดหากต้องการ แต่คุณต้องใช้อักขระ./\<>^V(ไม่ใช่ opcodes ที่เป็นจำนวนเต็ม) คุณอาจใช้พื้นที่แทน.ถ้าต้องการ ไม่เป็นไรถ้าตัวละครชอบ\จำเป็นต้องหลีกเลี่ยงในอินพุต เอาต์พุตจะเป็นจำนวนเต็มมากกว่าหนึ่งเสมอ

กรณีทดสอบ

....
5

\...
\.><
9

.
2

..
3

.
.
2

\
2

^
2

.^.
3

<.
2

\\
\/
7

>V
^<
6

>\
>/
6

\><
2

\><
\><
7

\><
\><
\><
12

\.V.
\.\<
5

\.V.
\./<
9

V./\
V./\
>./<
..\/
14

\V..
.^..
\/><
.V..
.^..
20

\.V.V.
\./.\<
.>\<..
..^.^.
31

\.V.V.V.
\./>/.\<
.>\>\<..
..^.^.^.
69

\.V.V.V.V.
\./>/>/.\<
.>\>\>\<..
..^.^.^.^.
145

\.V.V.V.V.V.V.V.V.V.V.
\./>/>/>/>/>/>/>/>/.\<
.>\>\>\>\>\>\>\>\>\<..
..^.^.^.^.^.^.^.^.^.^.
9721

1
มันเป็นความอัปยศดังกล่าวที่คุณไม่สามารถทำให้การแก้ปัญหา Backflip ไปนี้ ...
HyperNeutrino

เกิดความสับสนเกี่ยวกับกระจกเงา ... / เปลี่ยนทิศทางเป็น left => up and up => left หรือไม่?
อย่างเป็นทางการเมื่อ

1
@officialaimm การมุ่งหน้าจากด้านซ้ายไปทางด้านบน/จะทำให้ IP ขึ้นไปและการเข้าสู่ทางด้านบน/จะทำให้ IP นั้นถูกต้องราวกับว่ามันเป็นลูกบอลที่กระดอนจากกำแพง ( แต่จำได้ว่า/การเปลี่ยนแปลงทับขวาหลังจากที่ IP สัมผัสมัน.)
คาลวินอดิเรก

ทำไม '\\' <LF> '\ /' คือ 7 แทนที่จะเป็น 6
tsh

คำตอบ:


3

JavaScript (ES6), 158 ไบต์

f=(a,x=0,y=0,d=3)=>a[x]&&(c=a[x][y])?(a[x][y]=c=='.'?c:c=='/'?(d^=3,'\\'):c=='\\'?(d^=1,'/'):'v>^<'[d][d='^<v>'.search(c),0],f(a,d<3?x+d-1:x,d?y+d-2:y,d)+1):1

พัฒนาเป็นอิสระจากคำตอบของ @ tsh แม้ว่าจะคล้ายกันมาก

การแมปเส้นทาง^<v>ไปยังจำนวนเต็ม 0-3 อยู่ภายใต้ข้อเท็จจริงที่.search('^')ส่งกลับค่า 0 เนื่องจาก^เป็นตัวบ่งชี้ regexp


ฉันรู้สึกถูกทุบตี ฉันค่อนข้างสับสนในตอนท้ายนั่นจนกระทั่งฉันรู้ว่า x และ y ถูกพลิกเมื่อเทียบกับสิ่งที่ฉันคาด
Ørjan Johansen

@ ØrjanJohansenนั่นเป็นจุดที่ดี บางทีฉันควรสลับ x กับ y ทุกที่เพื่อให้เข้าใจง่ายขึ้น
Neil

2

Haskell , 333 325 ไบต์

แก้ไข:

  • -8 ไบต์: สร้างfpointfree และรวมเข้าbด้วยกัน

bใช้เวลารายการและส่งกลับStringInteger

data C a=C{c::a->(a,C a)}
b g=[0,0]#([0,1],map(maybe(C$m 1)C.(`lookup`zip"./^>V<"[n,m(-1),a[-1,0],a[0,1],a[1,0],a[0,-1]]))<$>g)
[y,x]#(d,g)|g&y||g!!0&x=1|n@([f,e],_)<-(($d).c)?x?y$g=1+[y+f,x+e]#n
l&i=i<0||i>=length l
(f?i)l|(p,a:r)<-splitAt i l=(p++).(:r)<$>f a
n d=(d,C n)
a v d=(v,C$a$(0-)<$>d)
m s[d,e]=([s*e,s*d],C$m(-s))

ลองออนไลน์!

มันทำงานอย่างไร

  • C aเป็นประเภทข้อมูลที่ใช้เนื่องจาก Haskell จะไม่อนุญาตให้เรียกใช้ประเภทซ้ำโดยไม่ต้องประกาศอย่างชัดเจน Cนอกจากนี้ยังเป็นตัวสร้างการห่อและcเป็นฟังก์ชั่นแกะที่สอดคล้องกัน a=[Int]มันจะใช้เฉพาะกับ
    • ประเภทC [Int]หมายถึงคำสั่งเซลล์เป็นฟังก์ชันที่รับ[Int]อาร์กิวเมนต์direction ( ) และส่งคืนคู่ของทิศทางใหม่และC [Int]ค่าใหม่
  • bเป็นหน้าที่หลัก มันจะแปลงตัวละครแต่ละตัวเป็นมูลค่าแล้วมันเรียกร้อง C#
    • g คือกริดเป็นรายการสตริง
    • เนื่องจาก\จะต้องมีการหลบหนีและดังนั้นจึงเป็นตัวละครที่ยาวที่สุดที่จะพูดถึงผลของมันจะถูกใช้แทนเป็นค่าเริ่มต้นสำหรับการค้นหารายการ
  • #วิ่งจำลองหลักตรวจสอบขอบเขตด้วยและสร้างกริดใหม่ที่มี& คือตำแหน่งปัจจุบันทิศทางปัจจุบันและกริดปัจจุบัน เป็นทิศทางต่อไปและเป็นคู่ของมันและกริดถัดไป?[y,x]dg[f,e]n
  • l&iตรวจสอบว่าดัชนีiอยู่นอกขอบเขตสำหรับรายการlหรือไม่ (มันกลับTrueมาจากนอกขอบเขตเนื่องจากหลีกเลี่ยงเงื่อนไขของตัวป้องกันหุ่นจำลอง#)
  • เมื่อf(l!!i)==(d,x), (f?i)l==(d,m)ที่mเป็นรายการlที่มีiองค์ประกอบ TH xแทนที่ด้วย
    • ในทางเทคนิคแล้ว(?i)เป็นเลนส์ทั่วไปที่เน้นองค์ประกอบของรายการในกรณีนี้ใช้กับ(,) [Int]อินสแตนซ์ของ functor
  • n เป็นฟังก์ชั่นที่แสดงถึงจุด
  • a vvเป็นฟังก์ชั่นที่เป็นตัวแทนของลูกศรในทิศทาง
  • m sเป็นฟังก์ชั่นที่ใช้แทนกระจกเงา s==1สำหรับ\\และสำหรับs==-1/

1

จาวาสคริปต์, 172 ไบต์

f=(a,d=3,x=0,y=0,n=1)=>(p=a[y]||[],q=p[x])?(p[x]=~(t='^<V>'.indexOf(q))?'^<V>'[d^2]:q=='/'?(t=3-d,'\\'):q=='\\'?(t=d^1,'/'):(t=d,q),f(a,t,x+(t&1&&t-2),y+(~t&1&&t-1),n+1)):n

แต่ฉันไม่สามารถทดสอบ testcase ครั้งสุดท้ายได้เนื่องจากฉันมี stack overflow บนเครื่องของฉัน (ควรทำงานหากมีเครื่องที่มี ram ขนาดใหญ่)

เราใช้หมายเลขในการบอกทิศทาง:

  • 0: ^
  • 1: <
  • 2: V
  • 3:>

อนุญาตdเป็นหมายเลขทิศทาง ...

  • ถ้าเราพบ '/' เราต้องการ d = 3 - d;
  • หากเราพบ '\' เราต้องการ d = d ^ 1;
  • หากเราพบ '^ <V>' เราต้องการ d = '^ <V>' .indexOf (หมายเหตุ)

อนุญาต(x, y)เป็นตำแหน่งปัจจุบันตำแหน่งต่อไปคือ: x+(t&1&&t-2),y+(~t&1&&t-1)

บันทึก:

ฟังก์ชั่นรับหนึ่งพารามิเตอร์ด้วยรูปแบบต่อไปนี้:

[ [ '\\', '.', 'V', '.', 'V', '.', 'V', '.', 'V', '.' ],
  [ '\\', '.', '/', '>', '/', '>', '/', '.', '\\', '<' ],
  [ '.', '>', '\\', '>', '\\', '>', '\\', '<', '.', '.' ],
  [ '.', '.', '^', '.', '^', '.', '^', '.', '^', '.' ] ]

ทดสอบที่นี่

f=(a,d=3,x=0,y=0,n=1)=>(p=a[y]||[],q=p[x])?(p[x]=~(t='^<V>'.indexOf(q))?'^<V>'[d^2]:q=='/'?(t=3-d,'\\'):q=='\\'?(t=d^1,'/'):(t=d,q),f(a,t,x+(t&1&&t-2),y+(~t&1&&t-1),n+1)):n

    ;k=x=>x.split('\n').map(t=>t.split(''));
<textarea id=v>\.V.V.V.V.
\./>/>/.\<
.>\>\>\<..
..^.^.^.^.</textarea><br/><button onclick="r.textContent=f(k(v.value))">Solve</button>
<p>Result: <output id=r></output></p>


เพียงเพื่อเอกสารฉันได้รับUncaught RangeError: Maximum call stack size exceededกับ RAM 16GB
Zeb McCorkle

1
@ZebMcCorkle AHA เพียงพบว่า "ใช้อย่างเข้มงวด" และบางส่วนvarประกาศให้มันผ่าน testcase ที่ผ่านมา (js ล่ามจะเพิ่มประสิทธิภาพการโทรหางในโหมดเข้มงวด)
TSH

1

C, 232 221 ไบต์

d,n,t,m[4]={1,-1};char*w="><^V/\\.",*P;main(o,v)char**v;{for(P=v[1],m[2]=-(m[3]=strchr(P,10)-P+1);P>=v[1]&&P<strchr(v[1],0)&&*P^10;++n)*P=w[((o=d,t=strchr(w,*P)-w)<4)?d=t,o^1:(t<6)?d^=t-2,9-t:6],P+=m[d];printf("%d",n+1);}

รับอินพุตในอาร์กิวเมนต์แรกพิมพ์ผลลัพธ์ ต้องการอินพุตนั้นมีอย่างน้อย 1 บรรทัดใหม่ (ดังนั้นหากมีเพียง 1 แถวนั้นจะต้องลงท้ายด้วยการขึ้นบรรทัดใหม่)

ตัวอย่างการใช้งาน:

./backflip '....
';

ชำรุด:

d,                                          // Direction
n,                                          // Step counter
t,
m[4]={1,-1};                                // Movement offsets
char*w="><^V/\\.",                          // Command lookup
*P;                                         // Cursor location
main(o,v)char**v;{
    for(P=v[1],                             // Begin at 0,0
        m[2]=-(m[3]=strchr(P,10)-P+1);      // Find width of grid
        P>=v[1]&&P<strchr(v[1],0)&&*P^10;   // While inside grid:
        ++n)                                //  Increment step
        *P=w[                               //  Update the current cell
            ((o=d,t=strchr(w,*P)-w)         //  (store current direction & command)
              <4)?d=t,o^1:                  //   If <>^V, write backflip & set dir
            (t<6)?d^=t-2,9-t:               //   If / or \, write flip & bounce
            6],                             //   If ., write unchanged & continue
        P+=m[d];                            //  Move
    printf("%d",n+1);                       // Print result
}

1

Python 3 , 286 ไบต์

[f () รับอินพุตในรูปของ{(0,0):'/',(0,1):'.'}ดังนั้นฉันจึงได้เขียนฟังก์ชัน g () สำหรับแปลงอาร์เรย์ของบรรทัดเป็นรูปแบบนั้น]

def f(r):
 x=y=0;d='>';s=1
 while 1:
  try:c=r[y,x];m='>^<V'.find(d)
  except:break
  if(c=="\\"):d='V<^>'[m];r[y,x]="/"
  elif(c=="/"):d='^>V<'[m];r[y,x]="\\"
  elif(c!="."):r[y,x]='<V>^'[m];d=c
  x+=1if(d=='>')else-1if(d=='<')else 0;y+=1if(d=='V')else-1if(d=='^')else 0;s+=1
 return s

ลองออนไลน์!

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