Thực hiện BackFlip cho ais523!


16

Thách thức này là một phần thưởng cho ais523 cho chiến thắng các " Rookie of the Year " mục trong " Best of PPCG 2016 ". Xin chúc mừng!


BackFlip là một ngôn ngữ lập trình bí truyền được tạo bởi người dùng ais523 , người đã tạo ra hơn 30 esolang thú vị khác .

BackFlip là ngôn ngữ 2D như Befunge hoặc > <> trong đó con trỏ lệnh đi ngang qua lưới văn bản (chương trình), di chuyển lên, xuống, trái và phải, thay đổi hướng tùy thuộc vào ký tự. Quan trọng, lưới trong chương trình BackFlip thay đổi khi nó đang đi qua, giống như Ant của Langton .

Đối với thử thách này, bạn có thể cho rằng chương trình BackFlip luôn là một lưới văn bản hình chữ nhật (tất cả các dòng có cùng độ dài), kích thước tối thiểu 1 × 1, chỉ chứa các ký tự ./\<>^V. ( .được sử dụng cho khả năng hiển thị thay vì không gian.) Về mặt ngữ nghĩa, BackFlip chúng tôi sẽ sử dụng ở đây giống hệt với thông số ban đầu .

Con trỏ lệnh (IP) trong BackFlip luôn bắt đầu ở bên trái góc trên cùng bên trái của chương trình, hướng sang phải. Có ba loại lệnh nó có thể gặp:

  1. .là một không-op. IP tiếp tục theo hướng nó đang đi. Các no-op vẫn là một no-op.

  2. /\là những tấm gương. Chúng phản xạ IP theo hướng được chỉ định bởi góc của chúng, sau đó chúng thay đổi thành loại gương khác .

    • Ví dụ, nếu các đầu IP trái sang a \, nó bắt đầu di chuyển lên trên thay vì trái và \trở thành a /.
  3. <, >, ^, Và Vlà mũi tên. Họ chuyển hướng IP theo hướng họ chỉ vào, sau đó họ đổi thành một mũi tên chỉ theo hướng IP đến (ngược với hướng IP đang di chuyển) .

    • Ví dụ, nếu IP hướng xuống dưới >, nó bắt đầu di chuyển sang phải thay vì đi xuống và >trở thành ^vì đó là hướng mà IP xuất phát.

Chương trình BackFlip chấm dứt khi IP di chuyển ra khỏi giới hạn, tức là tắt khỏi lưới. Hóa ra tất cả các chương trình BackFlip cuối cùng đều kết thúc vì các vòng lặp vô hạn là không thể. (Bạn có thể cho rằng điều này là đúng.)

Mục tiêu của bạn trong thử thách này là viết một chương trình hoặc hàm thực hiện trong chương trình BackFlip và đưa ra số lần di chuyển mà con trỏ lệnh thực hiện trước khi chương trình kết thúc. Đó là, IP thực hiện bao nhiêu bước trong quá trình chạy chương trình? Điều này bao gồm bước ban đầu lên lưới và bước cuối cùng của nó.

Ví dụ, con trỏ lệnh thực hiện 5 bước trong lưới tầm thường ....:

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

Vì vậy, đầu ra ....5.

Trong lưới 4 × 2 phức tạp hơn

\...
\.><

IP thoát khỏi lưới ở bước thứ 9 của nó, vì vậy đầu ra là 9:

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

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

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

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

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

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

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

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

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

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

Mã ngắn nhất tính bằng byte thắng.

Bạn có thể lấy đầu vào dưới dạng một mảng các dòng hoặc ma trận ký tự thay vì một chuỗi nhiều dòng nếu muốn, nhưng bạn phải sử dụng các ký tự ./\<>^V(không phải là số nguyên). Bạn có thể sử dụng không gian thay vì .nếu thích. Sẽ ổn nếu các ký tự như \cần được thoát trong đầu vào. Đầu ra luôn là một số nguyên nhiều hơn một.

Các trường hợp thử nghiệm

....
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
Thật xấu hổ khi bạn không thể tạo ra giải pháp BackFlip cho điều này ...
HyperNeutrino

Nhầm lẫn về các gương ... không / lật hướng như trái => lên và lên => trái ,?
chính thức

1
@officialaimm Tiêu đề từ bên trái vào /sẽ làm cho IP đi lên và đi lên /sẽ làm cho IP đi đúng, như thể nó là một quả bóng nảy ra từ một bức tường. (Nhưng hãy nhớ những /thay đổi của dấu gạch chéo ngược sau khi IP chạm vào nó.)
Sở thích của Calvin

tại sao '\' <LF> '\ /' là 7 thay vì 6?
tsh

Câu trả lời:


3

JavaScript (ES6), 158 byte

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

Được phát triển độc lập từ câu trả lời của @ tsh mặc dù rất giống nhau.

Việc ánh xạ các hướng ^<v>tới các số nguyên 0-3 bị chi phối bởi thực tế là .search('^')trả về 0 vì ^là một metacharacter regrec.


Tôi cảm thấy rất tuyệt vời. Tôi đã khá bối rối ở cuối đó cho đến khi tôi nhận ra x và y bị lật so với những gì tôi mong đợi.
Ørjan Johansen

@ RjanJohansen Đó là một điểm tốt; có lẽ tôi nên trao đổi x với y ở mọi nơi để dễ hiểu hơn.
Neil

2

Haskell , 333 325 byte

BIÊN TẬP:

  • -8 byte: Được tạo điểm fmiễn phí và được hợp nhất vào b.

blấy một danh sách Strings và trả về một Integer.

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

  • C alà một kiểu dữ liệu được sử dụng vì Haskell sẽ không cho phép một kiểu đệ quy mà không khai báo rõ ràng. Ccũng là một hàm tạo và clà hàm hủy ghép tương ứng của nó. Nó chỉ được sử dụng với a=[Int].
    • Kiểu C [Int]đại diện cho một lệnh ô, như là một hàm lấy một [Int]đối số hướng ( ) và trả về một cặp hướng mới và một C [Int]giá trị mới .
  • blà chức năng chính. Nó chuyển đổi mỗi ký tự thành một Cgiá trị, sau đó nó gọi #.
    • g là lưới dưới dạng một danh sách các chuỗi.
    • \cần phải thoát và là ký tự dài nhất để đề cập, thay vào đó, kết quả của nó được sử dụng làm giá trị mặc định cho việc tra cứu danh sách.
  • #chạy mô phỏng chính, kiểm tra giới hạn với &và tạo lưới mới với ?. [y,x]là vị trí hiện tại, dhướng hiện tại và glưới hiện tại. [f,e]là hướng tiếp theo, và nlà một cặp của nó và lưới tiếp theo.
  • l&ikiểm tra nếu chỉ số inằm ngoài giới hạn cho danh sách l. (Nó quay trở lại Truengoài giới hạn, vì điều đó tránh được tình trạng bảo vệ giả trong #.)
  • Khi f(l!!i)==(d,x), (f?i)l==(d,m)nơi mđây là danh sách lvới các inguyên tố thứ thay thế bằng x.
    • Về mặt kỹ thuật (?i)là một ống kính tổng quát hơn, tập trung vào yếu tố thứ i của danh sách, trong trường hợp này được sử dụng với đối tượng (,) [Int]functor.
  • n là hàm đại diện cho một dấu chấm.
  • a vlà một hàm đại diện cho một mũi tên theo hướng v.
  • m slà một chức năng đại diện cho một tấm gương; s==1cho \\s==-1cho /.

1

JavaScript, 172 byte

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

Nhưng tôi không thể kiểm tra testcase cuối cùng vì tôi đã bị tràn stack trên máy của mình. (nên hoạt động nếu có máy có ram lớn hơn)

Chúng tôi sử dụng một số cho hướng:

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

Hãy dlà số chỉ đường ...

  • nếu chúng ta gặp một '/', chúng ta cần d = 3 - d;
  • nếu chúng ta gặp một '\', chúng ta cần d = d ^ 1;
  • nếu chúng ta gặp một '^ <V>', chúng ta cần d = '^ <V>'. indexOf (lưu ý)

Đặt (x, y)vị trí hiện tại, vị trí tiếp theo là : x+(t&1&&t-2),y+(~t&1&&t-1)

Ghi chú:

Hàm lấy một tham số với định dạng sau:

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

Kiểm tra nó ở đây

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>


Chỉ cần để tài liệu, tôi nhận được Uncaught RangeError: Maximum call stack size exceededvới 16GB RAM.
Zeb McCorkle

1
@ZebMcCorkle aha, chỉ cần tìm ra rằng "sử dụng nghiêm ngặt" và một số vartuyên bố làm cho nó vượt qua thử nghiệm cuối cùng (trình thông dịch js thực hiện tối ưu hóa cuộc gọi đuôi trong chế độ nghiêm ngặt)
tsh

1

C, 232 221 byte

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);}

Đưa đầu vào trong đối số đầu tiên, in kết quả. Yêu cầu đầu vào chứa ít nhất 1 dòng mới (vì vậy nếu chỉ có 1 hàng thì nó phải kết thúc bằng một dòng mới)

Ví dụ sử dụng:

./backflip '....
';

Phá vỡ:

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 byte

[f () nhận đầu vào ở dạng {(0,0):'/',(0,1):'.'}vì vậy tôi cũng đã viết một hàm g () để chuyển đổi một mảng các dòng thành dạng đó]

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

Hãy thử trực tuyến!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.