Ais523 için bir BackFlip yapın!


16

Bu meydan okuma için bir ödüldür ais523 için kazanan " Yılın Çaylağı " kategoriye " PPCG 2016 Best of ". Tebrikler!


BackFlip kullanıcı tarafından yapılan bir ezoterik programlama dilidir ais523 yarattı, aşkın 30 diğer ilginç esolangs .

BackFlip, Befunge veya > <> gibi bir 2D dildir ; burada yönerge işaretçisi, üzerinde bulunan karaktere bağlı olarak yönü değiştirerek yukarı, aşağı, sola ve sağa hareket ederek bir metin ızgarasını (program) hareket ettirir. Kritik olarak, bir BackFlip programındaki ızgara, çapraz hareket ederken, Langton'ın Ant'i gibi biraz değişir .

Bu meydan okuma için bir BackFlip programının her zaman en az 1 × 1 boyutunda, yalnızca karakterleri içeren dikdörtgen bir metin ızgarası olduğunu varsayabilirsiniz ./\<>^V. ( .alan yerine görünürlük için kullanılır.) Anlamsal olarak, burada kullanacağımız BackFlip orijinal spesifikasyonla aynıdır .

BackFlip'teki yönerge işaretçisi (IP) her zaman programın sol üst köşesinin hemen solunda, sağa doğru başlar. Karşılaşabileceği üç tür komut vardır:

  1. .hayır-op. IP devam ettiği yönde devam eder. No-op, no-op olarak kalır.

  2. /ve \aynalar. IP'yi açılarıyla belirtilen yönde yansıtırlar, daha sonra diğer ayna türüne dönüşürler .

    • Örneğin, IP kafaları a 'ya bırakılırsa \, sol yerine yukarı doğru hareket etmeye başlar ve \a olur /.
  3. <, >, ^Ve Voklar. IP'yi işaret ettikleri yöne yönlendirirler, ardından IP'nin geldiği yönü (IP'nin hareket ettiği yönün karşısında) gösteren bir oka dönüşürler .

    • Örneğin, IP aşağı >doğru ilerlerse, aşağı doğru yerine sağa doğru hareket etmeye başlar ve bu IP'nin geldiği yön olduğu için >a olur ^.

Bir BackFlip programı IP sınırların dışına çıktığında, yani şebekeden çıktığında sona erer. Sonsuz döngüler imkansız olduğu için tüm BackFlip programlarının sonunda sona erdiği ortaya çıkıyor . (Bunun doğru olduğunu varsayabilirsiniz.)

Bu meydan okumadaki amacınız, bir BackFlip programında yer alan ve yönerge işaretçisinin program sona ermeden önce aldığı hamle sayısını veren bir program veya işlev yazmaktır. Yani, IP bir programı çalıştırırken kaç adım atar? Bu, ızgara üzerindeki ilk adımı ve son adımını içerir.

Örneğin, talimat işaretçisi önemsiz ızgarada 5 adım atar ....:

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

İçin çıkış Yani ....DİR 5.

Daha karmaşık 4 × 2 ızgarada

\...
\.><

IP 9. adımda ızgaradan çıkar, dolayısıyla çıktı 9:

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

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

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

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

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

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

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

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

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

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

Bayt cinsinden en kısa kod kazanır.

İsterseniz girdiyi çok satırlı dize yerine satır dizisi veya karakter matrisi olarak alabilirsiniz, ancak karakterleri kullanmalısınız ./\<>^V(tamsayı opcode değil). .Tercih edilirse boşluk kullanabilirsiniz . Gibi karakterlerin \girişte kaçması gerekiyorsa sorun yok. Çıktı her zaman birden fazla tamsayıdır.

Test Durumları

....
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
Böyle bir
BackFlip

Aynalar hakkında şaşkın ... sola doğru yönler mi döndürüyor / çeviriyor => yukarı ve yukarı => sol ,?
officialaimm

1
@officialaimm Soldan içeri /doğru ilerlemek IP'nin yukarı çıkmasını ve yukarı doğru ilerlemesinin /sanki bir duvardan sıçrayan bir topmuş gibi sağa gitmesini sağlayacaktır. (Ancak /IP ona dokunduktan sonra ters eğik çizgi üzerindeki değişiklikleri hatırlayın .)
Calvin'in Hobileri

neden '\\' <LF> '\ /' 6 yerine 7?
tsh

Yanıtlar:


3

JavaScript (ES6), 158 bayt

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

Şaşırtıcı derecede benzer olmasına rağmen @ tsh'ın cevabından bağımsız olarak geliştirildi.

^<v>Yönlerin 0-3 tamsayılarına eşlenmesi , bir regexp metakarakter olduğu için .search('^')0 döndüren gerçeğiyle yönetilir ^.


Kendimi çok hırpalanmış hissediyorum. Ben x ve y beklediğimden daha çevrilmiş olduğunu fark edinceye kadar orada sonunda oldukça karıştı.
Ørjan Johansen

@ ØrjanJohansen Bu iyi bir nokta; belki daha kolay anlaşılması için x'i y ile değiştirmeliyim.
Neil

2

Haskell , 333 325 bayt

DÜZENLE:

  • -8 bayt: fPointfree yapıldı ve birleştirildi b.

bStrings listesini alır ve an döndürür 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))

Çevrimiçi deneyin!

Nasıl çalışır

  • C aHaskell, bir türün açıkça bildirmeden özyinelemesine izin vermediği için kullanılan bir veri türüdür. Caynı zamanda bir sargı yapıcısıdır ve ckarşılık gelen açma fonksiyonudur. Sadece ile kullanılır a=[Int].
    • Tür C [Int], bir yön ( [Int]) argümanı alan ve bir çift yeni yön ve yeni bir C [Int]değer döndüren bir işlev olarak bir hücre komutunu temsil eder .
  • bana işlevdir. Her karakteri bir Cdeğere dönüştürür , sonra çağırır #.
    • g dizelerin listesi olarak kılavuzdur.
    • Kaçınılması \gerektiğinden ve bahsedilmesi gereken en uzun karakter olduğu için, sonuç bunun yerine liste araması için varsayılan değer olarak kullanılır.
  • #ana simülasyonu çalıştırır, sınırları kontrol eder &ve yeni ızgaralar oluşturur ?. [y,x]geçerli konum, dgeçerli yön ve ggeçerli ızgaradır. [f,e]bir sonraki yön ve nbir çift ve bir sonraki ızgaradır.
  • l&idizinin iliste için sınırların dışında olup olmadığını kontrol eder l. (Sınır dışı Trueiçin geri döner , çünkü bu bir kukla koruma koşulunu önler #.)
  • Ne zaman f(l!!i)==(d,x), th öğesinin (f?i)l==(d,m)bulunduğu mliste nerede lile ideğiştirilir x.
    • Teknik (?i)olarak, bu durumda (,) [Int]functor örneğiyle kullanılan bir listenin i öğesine odaklanan daha genel bir mercektir .
  • n bir noktayı temsil eden işlevdir.
  • a vbir oku gösteren bir işlevdir v.
  • m sbir aynayı temsil eden bir işlevdir; s==1için \\ve s==-1için /.

1

JavaScript, 172 bayt

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

Ama son testcase'i test edemiyorum çünkü makinemde yığın taşması var. (daha büyük koçlu bir makine varsa çalışmalıdır)

Yön için bir sayı kullanıyoruz:

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

Izin vermek dyön numarası ...

  • bir '/' ile karşılaşırsak, d = 3 - d'ye ihtiyacımız var;
  • bir '\' ile karşılaşırsak d = d ^ 1'e ihtiyacımız var;
  • bir '^ <V>' ile karşılaşırsak d = '^ <V>' .indexOf'a (not) ihtiyacımız var

Izin (x, y)anki pozisyon, bir sonraki pozisyon: x+(t&1&&t-2),y+(~t&1&&t-1)

Not:

Fonksiyon aşağıdaki formatta bir parametre alır:

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

Burada test edin

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>


Sadece belgelemek Uncaught RangeError: Maximum call stack size exceedediçin 16GB RAM ile alıyorum .
Zeb McCorkle

1
@ZebMcCorkle aha, sadece "katı kullanın" ve bazı varbildirimlerin son test
çantasını

1

Cı, 232 221 bayt

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

İlk argümanda girdi alır, sonucu yazdırır. Girdinin en az 1 yeni satır içermesi gerekir (bu nedenle yalnızca 1 satır varsa, yeni satırla bitmelidir)

Örnek kullanım:

./backflip '....
';

Yıkmak:

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 bayt

[f () şeklinde girdi alır, {(0,0):'/',(0,1):'.'}bu yüzden ben de bir dizi satır bu forma dönüştürmek için bir fonksiyon g () yazdım]

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

Çevrimiçi deneyin!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.