Altıgen labirent zamanı!


27

Başka bir labirent mücadelesi zamanı, ama bildiğiniz gibi değil.

Bu meydan okuma için kurallar çoğu labirent meydan okumalarından biraz farklıdır. Döşeme tipleri şu şekilde tanımlanmıştır:

  • S: Başladığınız labirentteki konum
  • E: Almaya çalıştığınız konum
  • 0: Geçemediğiniz duvar
  • +: Geçebileceğiniz Zemin

Altı yönden birinde seyahat edebilirsiniz: yukarı-sol, yukarı-sağ, sol, sağ, aşağı-sol veya aşağı-sağ.

\ /
-S-
/ \

Labirent sarılmaz. Amaç almak en kısa yol dizesini bulmaktır Siçin E.

Giriş:

Giriş, gösterilen labirentler gibi boşlukla ayrılmış çizgilerdir. Hiç bir iz bırakmayan boşluk bir çizgi izlemez.

Çıktı:

Bir dize içinde R, Lve Fnerede

  • R sağa döndürür (saat yönünde) 60 derece
  • L sizi sola döndürür (saat yönünün tersine) 60 derece
  • F sizi işaret ettiğiniz yönde bir boşluk taşır

Sen işaret etmeye başla left-up

En kısa yol, ziyaret edilen pozisyonların sayısı değil, üretilen dizenin uzunluğu ile sayılır. Programınız, çözüm olarak en kısa yolu yazdırmalıdır.

Labirent çözülemez ise, çıktı almalısınız Invalid maze!.

( >>>çıktı)

     0 0 0 0
    0 + 0 + 0
   0 0 0 + + 0
  0 + 0 + 0 + 0
 0 0 + + 0 0 + 0
0 0 + 0 + 0 0 + 0
 E 0 + 0 0 + + 0 
  + + 0 + 0 + 0
   0 0 0 0 0 +
    + 0 + + +
     0 S 0 0

>>>RFRFFLFLFRFFLFFFLFLFFRFLFLFRFRFRF

  + 0 0 0 0 0 0
 0 0 0 0 0 + + 0
0 0 E 0 + 0 0 + 0
 0 0 0 0 0 0 0 +
  0 + 0 0 + + +
   0 0 + + 0 0
    S + 0 0 0

>>>Invalid maze!

0 E S

>>>LF


 E + 0
0 + + +
 0 0 S
  + +

>>>FFLF

  E
 0 +
0 + +
 0 +
  S

>>>RFFLFF

 0 E + 0 0
0 + 0 0 + +
 + 0 + + + 0
  + 0 + 0 + 0
   + + + 0 S

>>>FFLFLFFRFRFFRFF

 E 0 + + 0
0 + 0 + + 0
 + + + 0 + 0
  + 0 0 0 0 0
   + + + + 0
    + 0 S 0

>>>FLFFRFFRFLF

(Labirentlerin bazılarının aynı uzunluktaki fakat burada listelenmeyen başka çözümleri olduğunu unutmayın)


27
Bir Hexagony çözümü için umut ...
bkul

3
Bir Hexagony çözümüne 500 puan ödül vereceğim.
lirtosiast

@ lirtosiast2 yıl sonra, altıgenliğin bu sorun için bir gerginlik olabileceğini düşünüyorum;)
J Atkin

Birkaç yıl daha bekleyelim.
user202729

Sonunda yeni bir satır olabilir mi?
user202729

Yanıtlar:


17

Python 2,291 bayt

def f(M):
 Y=map(max,M).index("S");X=M[Y].find("S");V={()};Q=[(0,0,0,1,"")]
 while Q:
    try:x,y,u,v,p=s=Q.pop(0);c=(Y>=y<=X-2*x)*ord(M[Y-y][X-2*x-y])
    except:c=0
    if c==69:return p
    if{c%2*s[:4]}-V:V|={s[:4]};Q+=(x+u,y+v,u,v,p+"F"),(x,y,-v,u+v,p+"R"),(x,y,u+v,-u,p+"L")
 return"Invalid maze!"

fLabirenti bir satır listesi olarak alan ve varsa bir çözüm döndüren bir işlev .

açıklama

Gerçekleştirir bir genişliği birinci bir kısa yol bulmak için pozisyon / yön çiftlerinin grafikte arama Siçin E.

İlginç olan, basit bir "adımlama" (yani, belirli bir yöne hareket etme) ve döndürme kabul eden altıgen bir ızgaradaki konumları ve yönleri temsil etmek için kompakt bir yol bulmaktır. Burada, "gerçek" altıgen bir ızgaradaki koordinatları temsil etmek için karmaşık sayıları kullanmak cazip gelir, ancak bu, en ciddi olanı √3'ü bağlamamız gereken gerçeği olan bir dizi nedenden dolayı pek iyi bir fikir değildir. kayan nokta sayılarını kullanırken mutlak bir kesinlik (örneğin, daha önce ziyaret ettiğimiz durumları takip etmek; JavaScript konsolunuzu kapatmayı ve yazarak Math.sqrt(3)*Math.sqrt(3) == 3kendiniz görmeyi deneyebilirsiniz .

Ama küçük bir numara kullanabiliriz! Karmaşık sayıları kullanmak yerine, benzer bir damardaki altıgen sayıları , a + bh gerçek sayıları çifti olarak tanımlayalım ; burada h , karmaşık sayılarla uğraşırken hayali i ile benzer bir rol oynar . Tıpkı karmaşık sayılarla olduğu gibi, çifti ( a , b ) düzlemdeki bir noktayla ilişkilendirebiliriz; gerçek eksen doğru, hayali eksen 60 ° yukarı bakar ve her ikisi de birim normal altıgenle kesişir. hayali parçalar sırasıyla 1'e eşit. Bu koordinat sistemini labirentin hücrelerine eşlemek önemsizdir.

Şekil 1

Aksine i , sabit h ilişki ile tanımlanır h 2 = h - 1 (için çözme h . Bazı görüşleri ortaya gelebilir) Ve o kadar! Altıgen numaraları ilave edildi ve çarpılır, yukarıda ilişkisi kullanılarak, çok karmaşık sayılar gibi olabilir: ( a + bh ) + ( C + dh ) = ( a + c ) + ( B + D ) h ,
ve ( bir + bh ) · ( c + dh ) = ( ac - bd) + ( ad + bc + bd ) h . Bu işlemler, karmaşık meslektaşları ile aynı geometrik yoruma sahiptir: toplama, vektör toplama ve çarpma, ölçeklendirme ve döndürmedir. Özellikle, saat yönünün tersine 60 ° 'lik altıgen bir sayı döndürmek için, onu h :
( a + bh ) · h = - b + ( a + b ) h olarak çarpın ve aynı sayıyı saat yönünde 60 ° döndürün, bölelim. tarafından h :
( a + bh ) / h = ( a +bh ) · (1 - s ) = (a + b) - ah . Örneğin, işaret birimi altıgen numarasını alabilir sağ, 1 = (1, 0), tam bir daire, ile çarpılarak, saat yönünün tersine gidiş h altı kez:
(1, 0) · h = (0, 1 ); (0, 1) · h = (-1, 1); (-1, 1) · h = (-1, 0); (-1, 0) · h = (0, -1); (0, -1) · h = (1, -1);
(1, -1) · h = (1, 0).

Program, bu şekilde labirentteki mevcut konumu ve mevcut yönü temsil etmek, belirtilen yönde ilerlemek ve yönü sola ve sağa döndürmek için altıgen sayıları kullanır.


31

Altıgen , 2437 bayt

Uzun zamandır beklenen program burada:

(.=$>({{{({}}{\>6'%={}{?4=$/./\_><./,{}}{<$<\?{&P'_("'"#<".>........_..\></</(\.|/<>}{0/'$.}_.....><>)<.$)).><$./$\))'"<$_.)><.>%'2{/_.>(/)|_>}{{}./..>#/|}.'/$|\})'%.<>{=\$_.\<$))<>(|\4?<.{.%.|/</{=....$/<>/...'..._.>'"'_/<}....({{>%'))}/.><.$./{}{\>$\|$(<><$?..\\<.}_>=<._..\(/.//..\}\.)))))<...2/|$\){}/{..><>).../_$..$_>{0#{{((((/|#.}><..>.<_.\(//$>))<(/.\.\})'"#4?#\_=_-..=.>(<...(..>(/\")<((.\=}}}\>{}{?<,|{>/...(...>($>{)<.>{=P&/(>//(_.)\}=#=\4#|)__.>"'()'\.'..".(\&P'&</'&\$_></}{)<\<0|\<.}.\"\.(.(.(/(\..{.>}=P/|><.(...(..."/<.{"_{{=..)..>})<|><$}}/\}}&P<\(/._...>\$'/.>}/{}}{)..|/(\'.<(\''"")$/{{}})<..'...}}>3#./\$<}|.}|..$.><${{}/>.}}{{<>(""''/..>){<}\?=}{\._=/$/=_>)\{_\._..>)</{\=._.....>(($>}}<.>5#.\/}>)<>-/(.....{\<>}}{{/)\$>=}}}))<...=...(\?{{{?<\<._...}.><..\}}/..>'P&//(\......(..\})"'/./&P'&P{}}&P'<{}\{{{({{{(.\&P=<.><$"&1}(./'"?&'&"\.|>}{?&"?&'P&/|{/&P''</(\..>P&{/&/}{}&'&},/"&P'&?<.|\}{&?"&P'&P'<._.>"&}\(>))<\=}{}<.{/}&?"&"&/"&"?&}\.|>?&"?&{{}}?&//x'&{((<._\($|(}.\/}{/>=&'P&"&/".{3?<.|\"&P'&P}{}&P'<.>&{}}?&"&'P&\=}}<.}/2?".?''5?"/?1{(}\."..../{},<../&//&"&P'&P'&"&"</{}}{{/>"?1''?.'({/}}{}<..>?&"?&}}$>)|P/<.>"&'P&'P&"&"&{/........._/"\$#1}/._.........|,($<'"}'?/_$P#"$0'${)$})$)|........(>/\.#1?<$<|.....>?&}$>=?&"?&/1$..>I;n;v;a;l;i;d;P0;m;a\|\"(}}({=/..$_...\"&P=},}}&P'<.|><....................;...>1"(}}){=/_....>'P&'P&}}_?&/#.>}?4'%\/<...@;1P;e;z<._><>"))'?=<.$$=..\&P}{&</\"><_'|/'&=}<.>{{.<.........|>(/>3")}}){=/=/_.>}P&"?/"<).}_.>?4{=:<.|_...........\$\2$'>4")}}({/."\{&P'&?/><.?|>P...."/=(>(/./(}{{\..>(<>(<>?5'"((..'/...#,</,}{{\.......;.F>..\(...}....._.._..._..._........__..'$......\.<R..$.>))<$}{{&P'&?}<.\$$.\...................$\.<>L\.\(('_"\>}P&"?&{/__/=(.(<.>_)..<...>....\..._.<.....&?=\}=&?"&<.."'>.\>))<.|>))\.|$.>&"?&{{}=P&}?&=}/{\.>&{{P/{">)<|\{<(|\(_(<>\_\?"&P'&P}{{{&<=_.>\&\?"&?<|'{/(/>{{/_>.{/=/\\.>'P&"?&"?&"?/._(\)\\>?&"/_|.>/.$/|$..\\><..\&?}{{}&P'&<}.._>{<|\{}<._$>-")<.>_)<|{)$|..>}=P&"?&"?/...{"./>'P&/=_\{?(/>(<>\(|)__.\&?}}{}&P<}.$.\&P'&P'&<\})))&=<\)<'.'_,><.>"?&'P&'/.|>?&{{}?&"?/>&"?&"?&}}<.".(\\\&?={&P<{..\"&?"&P'&<.?....|.$'\$/\"/.,.>{}{}=/..>&'P&}{{}P/\{}&P{(&?"&?"<'.(\&?"&<}..\?"&?"&<.>P&={}}?&}}P&'P&/.'.>&"?/..>P&}}{{P/\}&P'&?={&?<$}=\"."\P'<{..\'&P'&<....>'P&{}P&"?&{{<\\..>&/$.>}{?&"?/|'$&.P&$P\$'&P={(/..\P\\.\{&?"&?\...\?{{}=<$&P'&P<.,./<?\...{}=P\"&<.>=P&""'?&'P&'/$.#1.>{?1#=$\&'P/\}&P'&?={(,}<._?_&\&?{=&{*=}4<.>P&"?&"?&'P&/1_$>}?&}}=?&){?/\{}&P'&?={&?#<$

Çevrimiçi deneyin!

"Okunabilir" versiyonu:

                             ( . = $ > ( { { { ( { } } { \ > 6 ' % = { } { ? 4 = $ / .
                            / \ _ > < . / , { } } { < $ < \ ? { & P ' _ ( " ' " # < " .
                           > . . . . . . . . _ . . \ > < / < / ( \ . | / < > } { 0 / ' $
                          . } _ . . . . . > < > ) < . $ ) ) . > < $ . / $ \ ) ) ' " < $ _
                         . ) > < . > % ' 2 { / _ . > ( / ) | _ > } { { } . / . . > # / | }
                        . ' / $ | \ } ) ' % . < > { = \ $ _ . \ < $ ) ) < > ( | \ 4 ? < . {
                       . % . | / < / { = . . . . $ / < > / . . . ' . . . _ . > ' " ' _ / < }
                      . . . . ( { { > % ' ) ) } / . > < . $ . / { } { \ > $ \ | $ ( < > < $ ?
                     . . \ \ < . } _ > = < . _ . . \ ( / . / / . . \ } \ . ) ) ) ) ) < . . . 2
                    / | $ \ ) { } / { . . > < > ) . . . / _ $ . . $ _ > { 0 # { { ( ( ( ( / | #
                   . } > < . . > . < _ . \ ( / / $ > ) ) < ( / . \ . \ } ) ' " # 4 ? # \ _ = _ -
                  . . = . > ( < . . . ( . . > ( / \ " ) < ( ( . \ = } } } \ > { } { ? < , | { > /
                 . . . ( . . . > ( $ > { ) < . > { = P & / ( > / / ( _ . ) \ } = # = \ 4 # | ) _ _
                . > " ' ( ) ' \ . ' . . " . ( \ & P ' & < / ' & \ $ _ > < / } { ) < \ < 0 | \ < . }
               . \ " \ . ( . ( . ( / ( \ . . { . > } = P / | > < . ( . . . ( . . . " / < . { " _ { {
              = . . ) . . > } ) < | > < $ } } / \ } } & P < \ ( / . _ . . . > \ $ ' / . > } / { } } {
             ) . . | / ( \ ' . < ( \ ' ' " " ) $ / { { } } ) < . . ' . . . } } > 3 # . / \ $ < } | . }
            | . . $ . > < $ { { } / > . } } { { < > ( " " ' ' / . . > ) { < } \ ? = } { \ . _ = / $ / =
           _ > ) \ { _ \ . _ . . > ) < / { \ = . _ . . . . . > ( ( $ > } } < . > 5 # . \ / } > ) < > - /
          ( . . . . . { \ < > } } { { / ) \ $ > = } } } ) ) < . . . = . . . ( \ ? { { { ? < \ < . _ . . .
         } . > < . . \ } } / . . > ' P & / / ( \ . . . . . . ( . . \ } ) " ' / . / & P ' & P { } } & P ' <
        { } \ { { { ( { { { ( . \ & P = < . > < $ " & 1 } ( . / ' " ? & ' & " \ . | > } { ? & " ? & ' P & /
       | { / & P ' ' < / ( \ . . > P & { / & / } { } & ' & } , / " & P ' & ? < . | \ } { & ? " & P ' & P ' <
      . _ . > " & } \ ( > ) ) < \ = } { } < . { / } & ? " & " & / " & " ? & } \ . | > ? & " ? & { { } } ? & /
     / x ' & { ( ( < . _ \ ( $ | ( } . \ / } { / > = & ' P & " & / " . { 3 ? < . | \ " & P ' & P } { } & P ' <
    . > & { } } ? & " & ' P & \ = } } < . } / 2 ? " . ? ' ' 5 ? " / ? 1 { ( } \ . " . . . . / { } , < . . / & /
   / & " & P ' & P ' & " & " < / { } } { { / > " ? 1 ' ' ? . ' ( { / } } { } < . . > ? & " ? & } } $ > ) | P / <
  . > " & ' P & ' P & " & " & { / . . . . . . . . . _ / " \ $ # 1 } / . _ . . . . . . . . . | , ( $ < ' " } ' ? /
 _ $ P # " $ 0 ' $ { ) $ } ) $ ) | . . . . . . . . ( > / \ . # 1 ? < $ < | . . . . . > ? & } $ > = ? & " ? & / 1 $
  . . > I ; n ; v ; a ; l ; i ; d ; P 0 ; m ; a \ | \ " ( } } ( { = / . . $ _ . . . \ " & P = } , } } & P ' < . |
   > < . . . . . . . . . . . . . . . . . . . . ; . . . > 1 " ( } } ) { = / _ . . . . > ' P & ' P & } } _ ? & / #
    . > } ? 4 ' % \ / < . . . @ ; 1 P ; e ; z < . _ > < > " ) ) ' ? = < . $ $ = . . \ & P } { & < / \ " > < _ '
     | / ' & = } < . > { { . < . . . . . . . . . | > ( / > 3 " ) } } ) { = / = / _ . > } P & " ? / " < ) . } _
      . > ? 4 { = : < . | _ . . . . . . . . . . . \ $ \ 2 $ ' > 4 " ) } } ( { / . " \ { & P ' & ? / > < . ? |
       > P . . . . " / = ( > ( / . / ( } { { \ . . > ( < > ( < > ? 5 ' " ( ( . . ' / . . . # , < / , } { { \
        . . . . . . . ; . F > . . \ ( . . . } . . . . . _ . . _ . . . _ . . . _ . . . . . . . . _ _ . . ' $
         . . . . . . \ . < R . . $ . > ) ) < $ } { { & P ' & ? } < . \ $ $ . \ . . . . . . . . . . . . . .
          . . . . . $ \ . < > L \ . \ ( ( ' _ " \ > } P & " ? & { / _ _ / = ( . ( < . > _ ) . . < . . . >
           . . . . \ . . . _ . < . . . . . & ? = \ } = & ? " & < . . " ' > . \ > ) ) < . | > ) ) \ . | $
            . > & " ? & { { } = P & } ? & = } / { \ . > & { { P / { " > ) < | \ { < ( | \ ( _ ( < > \ _
             \ ? " & P ' & P } { { { & < = _ . > \ & \ ? " & ? < | ' { / ( / > { { / _ > . { / = / \ \
              . > ' P & " ? & " ? & " ? / . _ ( \ ) \ \ > ? & " / _ | . > / . $ / | $ . . \ \ > < . .
               \ & ? } { { } & P ' & < } . . _ > { < | \ { } < . _ $ > - " ) < . > _ ) < | { ) $ | .
                . > } = P & " ? & " ? / . . . { " . / > ' P & / = _ \ { ? ( / > ( < > \ ( | ) _ _ .
                 \ & ? } } { } & P < } . $ . \ & P ' & P ' & < \ } ) ) ) & = < \ ) < ' . ' _ , > <
                  . > " ? & ' P & ' / . | > ? & { { } ? & " ? / > & " ? & " ? & } } < . " . ( \ \
                   \ & ? = { & P < { . . \ " & ? " & P ' & < . ? . . . . | . $ ' \ $ / \ " / . ,
                    . > { } { } = / . . > & ' P & } { { } P / \ { } & P { ( & ? " & ? " < ' . (
                     \ & ? " & < } . . \ ? " & ? " & < . > P & = { } } ? & } } P & ' P & / . '
                      . > & " ? / . . > P & } } { { P / \ } & P ' & ? = { & ? < $ } = \ " . "
                       \ P ' < { . . \ ' & P ' & < . . . . > ' P & { } P & " ? & { { < \ \ .
                        . > & / $ . > } { ? & " ? / | ' $ & . P & $ P \ $ ' & P = { ( / . .
                         \ P \ \ . \ { & ? " & ? \ . . . \ ? { { } = < $ & P ' & P < . , .
                          / < ? \ . . . { } = P \ " & < . > = P & " " ' ? & ' P & ' / $ .
                           # 1 . > { ? 1 # = $ \ & ' P / \ } & P ' & ? = { ( , } < . _ ?
                            _ & \ & ? { = & { * = } 4 < . > P & " ? & " ? & ' P & / 1 _
                             $ > } ? & } } = ? & ) { ? / \ { } & P ' & ? = { & ? # < $

Ezoterik IDE'de Test Edildi: TIO bazı büyük test durumlarında zaman aşımına uğrayabilir, ancak hepsi doğrulandı. Timwi'ye çok teşekkürler, bu IDE olmadan mümkün olmazdı.

Oldukça fazla boş alan var, bu yüzden bunu bir yan 28 uzunluğuna (yan uzunluk 29 yerine) sığdırabilirim ama bu büyük bir iş olacak, muhtemelen denemeyeceğim.

Temel açıklama

Daha büyük ve daha ayrıntılı sürüm için resimlere tıklayın.

Fonksiyonlar

Fonksiyonlar
Not: Bölünmeler genellikle doğrudur, ancak zaman zaman kaba bir tahmin olabilir.

Bu kod oldukça "işlevsel" - Hexagony'in izin verdiği ölçüde. Bu kodda, yukarıdaki diyagramda etiketlendikleri, adlandırıldıkları numaralarla adlandırılmış sekiz ana işlev vardır (bu nedenle komut gösterici numaraları, bu sayı mod 6'dır). (Kaba) çağrı sırasına göre bunlar (alıntı isimler bellekte daha sonra açıklanacak yerlerdir):

  • S: Başlangıç fonksiyonu - daha sonra üç yolları ile "yol yığını" başlar, "referans dizisi" yukarı giriş ve set okur F, Rve Lana işleme hazır. Uygulama işaretçisi 0, yürütme işlev 1'e taşınırken işlev 0'a hareket eder.
  • 1 (-11): Ana işlev - bir yol elde etmek için 2'yi, geçerliliğini kontrol etmek için 3'ü, geçerli ise yeni yolu "yoluna kopyalamak için -110 / -10 işlevine iki kez ve ardından 4 üç kez gider" istif ", kendine dönerek bitirme. Yol son konumdaysa, işlev 5'i çağırabilir.
  • 2: Bir sonraki yolu "yol yığını" ndan işlemeye hazır hale getirir, yığın üzerinde yol kalmadıysa -1 işlevini çağırır. 1. işleve geri döner.
  • 3: Hareket sayısının yanı sıra bir çift değer alır ve geçerli yolun geçerli bir yerde bitip bitmediğini görmek için "referans dizisini" kontrol eder. Geçerli bir konum ya ilk 3 hamlede başlangıç ​​ya da ilk +iki hamlede ulaşılmasıdır. 1. işleve geri döner.
  • -10 / -110: Geçerli yolu kopyalar. 1. işleve geri döner.
  • 0: İşlev 1'in hareket yönünü yönetmesine yardımcı olur F. 1. işleve geri döner.
  • 4: Mevcut yolun bir kopyasını alır ve aynı yoluna 1 değişiklikler bunu ya işleviyle birbirine F, Rya da Leklenir. 1. işleve geri döner.
  • 5: Yolu alır ve doğru yolu yazdırır (örn. FFLF), Sonra programı sonlandırır.
  • -1: Yazdırır Invalid maze!ve sonlandırır.
  • (Çift oklar): Boşluk olmaması nedeniyle, 1 / -11 fonksiyonunun -1 fonksiyonunun üstündeki boşluğa geçmesi gerekiyordu.

Bellek

Bellek düzeni
Not: Diyagram için tekrar Ezoterik IDE sayesinde

Hafıza üç ana bölümden oluşur:

  • Referans dizisi: Izgara, her adımda bir değere sahip 2 ayrı sütunda saklanır:
    • 0 ya temsil , 0daha hamle önce herhangi bir yönde yer çıkmak için ihtiyaç duyulacak olandan erişilen veya geçerli bir yer.
    • 1 +, henüz ulaşılmayanı temsil eder .
    • (daha yüksek sayı), herhangi bir yönde yerden çıkmak için yeterli hareketin olacağı hareket numarasını gösterir.
    • 10 aynı zamanda yeni bir çizgiyi temsil eder: en son beyaz boşluk olmayan karakteri hemen takip ettiklerini varsayarsak bunlara asla ulaşılmaz.
  • Demiryolu: Solda -1bir tane -2bulunan s'dan oluşur, bellek işaretçisinin hızlı bir şekilde çekirdek işleme alanına geri dönmesini sağlar.
  • Yol yığını: Test edilmemiş yolların her birini yol kimliğine göre sıralar (bu, kısa yolların ilk önce test edilmesi için doğrudan hareket numarasıyla ilişkilidir). Yol aşağıdaki gibi saklanır:
    Yol düzeni
    • Rot: Geçerli yolun sonundaki rotasyon: yukarı-sol için 0 ve saat yönünde 5'e yükselme
    • Taşı: geçerli taşıma numarası (talimatlar - 1)
    • Yol: akım yolu, kuaterner depolanan F, R, Lyanı 1, 2, 3sırasıyla
    • x / y: geçerli yolun sonundaki koordinatlar: x + 1 -1s sağ sonra y değeri (yine de y = 0, rayı referans verilerinden ayırmak amacıyla 1 olarak işlenir)

Diğer önemli hafıza konumları:

  1. X / y Eburada saklanır.
  2. Bu boşluk, hafızaya giren ve çıkan yolları değiştirmek için kullanılır.
  3. Bu konum, işlem sırasında her yolun depolandığı merkezdir.

Bir sonraki adım, en kısa labirent yolunu bulmak için programınızı programınız üzerinden geçirmektir.
Veskah

Birinin göndereceğini biliyorum. Sonunda ... / Farklı bir planım var, ki muhtemelen sizinkinden daha az kod almalı. Aslında bunu uygulamak için zamanınız yok.
user202729

@ user202729 bunu duymak ilginç olurdu. Bu yöntem muhtemelen en az 2 beden aşağıya golf atılabileceğini söyleyebilirim, ama orada kesinlikle daha iyi bir şey var.
boboquack

1
@ Lirtosiast'ı bekliyorum.
J Atkin

1
Gecikme için özür dilerim.
lirtosiast

6

Python 3, 466 bayt

Derinlik ilk arama veya başka bir şey kullansaydım muhtemelen daha küçük olurdu. Bu canavarlık Dijkstra'yı kullanıyor ve oldukça hızlı, ama çok uzun.

Kod S, labirentin çok satırlı bir dize alan ve sonucu döndüren bir işlevi tanımlar .

def F(M,L,c):y=M[:M.index(c)].count("\n");return L[y].index(c),y
def S(M):
 L=M.split("\n");Q=[("",)+F(M,L,"S")+(0,)];D={};R=range;H=len;U=R(2**30)
 while Q:
  C,*Q=sorted(Q,key=H);w,x,y,d=C
  for e in R(H(L)>y>-1<x<H(L[y])>0<H(D.get(C[1:],U))>H(w)and(L[y][x]in"+SE")*6):D[C[1:]]=w;E=(d+e)%6;Q+=[(w+",R,RR,RRR,LL,L".split(",")[e]+"F",x+[-1,1,2,1,-1,-2][E],y+[-1,-1,0,1,1,0][E],E)]
 J=min([D.get(F(M,L,"E")+(d,),U)for d in R(6)],key=H);return[J,"Invalid maze!"][J==U]

İşte kodun bir testi.

Ungolfed

def find_char(maze, lines, char):
    y = maze[:maze.index(char)].count("\n")
    return lines[y].index(char), y
def solve(maze):
    lines = maze.split("\n")
    x, y = find_char(maze, lines, "S")
    queue = [("", x, y, 0)]
    solutions = {}
    very_long = range(2**30)
    x_for_direction = [-1,1,2,1,-1,-2]
    y_for_direction = [-1,-1,0,1,1,0]
    rotations = ["","R","RR","RRR","LL","L"]
    while len(queue) > 0:
        queue = sorted(queue, key=len)
        current, *queue = queue
        route, x, y, direction = current
        if 0 <= y < len(lines) and 0 <= x < len(lines[y]) and lines[y][x] in "+SE" and len(solutions.get(current[1:], very_long)) > len(route):
            solutions[current[1:]] = route
            for change in range(6):
                changed = (direction + change) % 6
                queue += [(route + rotations[change] + "F", x + x_for_direction[changed], y + y_for_direction[changed], changed)]
    end_x, end_y = find_char(maze, lines, "E")
    solution = min([solutions.get((end_x, end_y, direction), very_long) for direction in range(6)], key=len)
    return "Invalid maze!" if solution == very_long else solution

Vay çok güzel. Bu ne kadar zamandır yazdı?
J Atkin

1
@JAtkin Dosya 1.5 saat önce oluşturuldu, ancak kod üzerinde çalışmak için ne kadar zaman harcadığımdan emin değilim. Ayrıca, burada saat 3, bu yüzden verimliliğim açıkça en üst düzeyde.
PurkkaKoodari

Güzel, 2 + saat harcadım ve çoğu zaten standart bir labirent için yazılmış.
J Atkin

Ungolfed versiyonun var mı?
J Atkin

1
@JAtkin Buna ihtiyaç var çünkü başlangıçta dönmeniz gerekebilir. Başlangıç ​​pozisyonu olmadan da işe yarayacaktı L,,R.
PurkkaKoodari

3

Groovy, 624 bayt. Fore!

Zamanın büyük bir topla yuvarlanmasını sağlayın. Çok satırlı dizeyi arg olarak alırQ

Q={a->d=[0]*4
a.eachWithIndex{x,y->f=x.indexOf('S');e=x.indexOf('E');
if(f!=-1){d[0]=f;d[1]=y}
if(e!=-1){d[2]=e;d[3]=y}}
g=[]
s={x,y,h,i,j->if(h.contains([x, y])|y>=a.size()||x>=a[y].size()|x<0|y<0)return;k = a[y][x]
def l=h+[[x, y]]
def m=j
def n=1
if(h){
o=h[-1]
p=[x,y]
q=[p[0]-o[0],p[1]-o[1]]
n=[[-2,0]:0,[-1,-1]:1,[1,-1]:2,[2,0]:3,[1,1]:4,[-1,1]:5][q]
r=n-i
m=j+((r==-5|r==5)?' LR'[(int)r/5]:['','R','RR','LL','L'][r])+'F'}
if(k=='E')g+=m
if(k=='+'|k=='S'){s(x-2,y,l,n,m)
s(x+2,y,l,n,m)
s(x+1,y+1,l,n,m)
s(x+1,y-1,l,n,m)
s(x-1,y+1,l,n,m)
s(x-1,y-1,l,n,m)}}
s(d[0],d[1],[],1,'')
print(g.min{it.size()}?:"Invalid maze!")}

Ungolfed versiyonu:

def map =
        """
  + 0 0 0 0 0 0
 0 0 0 0 0 + + 0
0 0 E 0 + 0 0 + 0
 0 0 0 0 0 0 0 +
  0 + 0 0 + + +
   0 0 + + 0 0
    S + 0 0 0""".split('\n').findAll()
//map =
//        """
// 0 + +
//E + 0 S 0
// 0 0 0 +
//  + + +""".split('\n').findAll()

//map = [""]// TODO remove this, this is type checking only
//map.remove(0)
//reader = System.in.newReader()
//line = reader.readLine()
//while (line != '') {
//    map << line
//    line = reader.readLine()
//}

startAndEnd = [0, 0, 0, 0]
map.eachWithIndex { it, idx ->
    s = it.indexOf('S'); e = it.indexOf('E');
    if (s != -1) {
        startAndEnd[0] = s; startAndEnd[1] = idx
    }
    if (e != -1) {
        startAndEnd[2] = e; startAndEnd[3] = idx
    }
}

def validPaths = []
testMove = { x, y, visited ->// visited is an array of x y pairs that we have already visited in this tree
    if (visited.contains([x, y]) || y >= map.size() || x >= map[y].size() || x < 0 || y < 0)
        return;


    def valueAtPos = map[y][x]
    def newPath = visited + [[x, y]]

    if (valueAtPos == 'E') validPaths += [newPath]
    if (valueAtPos == '+' || valueAtPos == 'S') {
        println "$x, $y passed $valueAtPos"
        testMove(x - 2, y, newPath)
        testMove(x + 2, y, newPath)

        testMove(x + 1, y + 1, newPath)
        testMove(x + 1, y - 1, newPath)

        testMove(x - 1, y + 1, newPath)
        testMove(x - 1, y - 1, newPath)
    }
}

//if (!validPath) invalid()
testMove(startAndEnd[0], startAndEnd[1], [])
println validPaths.join('\n')

//println validPath

def smallest = validPaths.collect {
    def path = ''
    def orintation = 1
    it.inject { old, goal ->
        def chr = map[goal[1]][goal[0]]
        def sub = [goal[0] - old[0], goal[1] - old[1]]
        def newOrin = [[-2, 0]: 0, [-1, -1]: 1, [1, -1]: 2, [2, 0]: 3, [1, 1]:4, [-1, 1]:5][sub]
        def diff = newOrin - orintation// 5L -5R
        def addedPath= ((diff==-5||diff==5)?' LR'[(int)diff/5]:['', 'R', 'RR', 'LL', 'L'][diff]) + 'F'//(diff == 0) ? '' : (diff > 0 ? 'R'*diff : 'L'*(-diff)) + 'F'
//        println "old:$old, goal:$goal chr $chr, orintation $orintation, sub:$sub newOrin $newOrin newPath $addedPath diff $diff"
        path += addedPath
        orintation = newOrin
        goal
    }
    path
}.min{it.size()}
//println "paths:\n${smallest.join('\n')}"
if (smallest)
    println "path $smallest"
else
    println "Invalid maze!"

3

C #, 600 574 bayt

Program tamamlandı, STDIN'den girdi kabul edildi, STDOUT'ya çıktı verdi.

Düzenleme: sarma işleminde bir hata oluştu (verilen test durumlarından herhangi birini bozmadı), 1 bayt daha ekledim, bu yüzden telafi etmek için biraz daha golf oynadım.

using Q=System.Console;struct P{int p,d;static void Main(){string D="",L;int w=0,W=0,o,n=1;for(;(L=Q.ReadLine())!=null;D+=L)w=(o=(L+="X").Length+1)>w?o:w;for(;W<D.Length;)D=D.Insert(W+1,"".PadLeft(D[W++]>87?w-W%w:0));P[]K=new P[W*6];var T=new string[W*6];P c=K[o=0]=new P{p=D.IndexOf('S')};for(System.Action A=()=>{if(c.p>=0&c.p<W&System.Array.IndexOf(K,c)<0&&D[c.p]%8>0){T[n]=T[o]+L;K[n]=c;n=D[c.p]==69?-n:n+1;}};o<n;o++){c=K[o];L="R";c.d=++c.d%6;A();L="L";c.d=(c.d+4)%6;A();L="F";c=K[o];c.p+=new[]{~w,1-w,2,1+w,w-1,-2}[c.d%6];A();}Q.WriteLine(n>0?"Invalid maze!":T[-n]);}}

Harita üzerinde okuyarak başlar, (her bir satıra eklenir, böylece nerede bittiğini bilir ve haritayı dikdörtgen yapmak için geri dönüp bir boşluk ekleyebilir ve sağ tarafta bir sıra boşluk bırakarak (bu tasarruf sağlar) aşağıda açıklanacağı gibi sarma kontrolleri yapıyoruz). Bu konuda bir noktada dikdörtgenin genişliğini hesaplar ve Haritanın toplam uzunluğunu belirler.

Ardından, Bir Genişlik-İlk Arama için her şeyi başlatır. Biri aramamızda keşfetmemiz gereken tüm ülkeleri, diğeri ise her bir duruma ulaşmak için kullandığımız rotayı kaydetmek için iki büyük dizilim yarattı. Baştaki ve kuyruk işaretçiler yukarıda ayarlanmış durumdayken, başlangıçtaki durum sonuç dizisine eklenir. Her şey 1 dizinli.

Daha sonra kuyruk kafaya çarpıncaya kadar yineliyoruz ya da en azından kafaya çarpmış gibi görünüyor . Ziyaret ettiğimiz her eyalet için, aynı konumda sola veya sağa döndürüldüğümüz yeni bir durum eklemeye çalışırız, sonra bir yere ilerleriz. Yönler, başlangıç ​​yönü (varsayılan olarak 0) "yukarı-sol" a karşılık gelecek şekilde indekslenir .

Bir durumu sıraya koymaya çalıştığımızda, sınırlandırılmış kontrol edilir, ancak sağ taraftaki boşluk sütunlarından dolayı "burada bulunmamıza izin verilir" ifadesiyle alınan sarım kontrol edilmez. kontrol edin (boşluklara girmenize izin verilmiyor). Durum sıraya alınmışsa, Ehücrenin üstünde olup olmadığını kontrol ederiz ve eğer öyleyse, sıranın başını eksi olacak şekilde ayarlarız, bu da ana döngünün çıkmasına neden olur ve programın son satırının yazdırılmasını sağlar Arıza mesajından ziyade ilgili rotadan çıkın (bu, genişletmek için devletlerin tükenip bitmediğini gösterir (kuyruk başa çarpıyor)).

using Q=System.Console;

// mod 8 table (the block of zeros is what we are after - it's everywhere we /can't/ go)
//   0 (space)
// O 0
// X 0
// S 3
// + 3
// E 5

struct P
{
    int p,d;
    static void Main()
    {
        // it's probably a bad thing that I have my own standards for naming this stupid read sequence by now
        string D="", // map
        L; // line/path char

        int w=0, // width
        W=0, // full length
        o, // next state to expand
        n=1; // next state to fill

        for(;(L=Q.ReadLine())!=null;D+=L) // read in map
            w=(o=(L+="X").Length+1)>w?o:w; // assertain max length (and mark end, and remove any need for wrap checking)

        // now we need to add those trailing spaces...
        for(;W<D.Length;)
            D=D.Insert(W+1,"".PadLeft(D[W++]>87?w-W%w:0)); // inject a load of spaces if we hit an X

        P[]K=new P[W*6]; // create space for due states (can't be more states than 6*number of cells)
        var T=new string[W*6]; // create space for routes (never done it this way before, kind of exciting :D)
        P c=K[o=0]=new P{p=D.IndexOf('S')}; // set first state (assignment to c is just to make the lambda shut up about unassigned variables)

        // run bfs
        for(

            System.Action A=()=> // this adds c to the list of states to be expanded, if a whole load of checks pass
            {
                if(//n>0& // we havn't already finished - we don't need this, because we can't win on the first turn, so can't win unless we go forward, which we check last
                   c.p>=0&c.p<W& // c is within bounds
                   System.Array.IndexOf(K,c)<0&& // we havn't seen c yet (the && is to prevent the following lookup IOBing)
                   D[c.p]%8>0) // and we can move here (see table at top of code)
                {
                    T[n]=T[o]+L; // store route
                    K[n]=c; // store state
                    n=D[c.p]==69?-n:n+1; // check if we are at the end, if so, set n to be negative of itself so we know, and can look up the route (otherwise, increment n)
                }
            }

            ;o<n;o++) // o<n also catches n<0
        {
            c=K[o]; // take current
            L="R"; // say we are going right
            c.d=++c.d%6; // turn right
            A(); // go!

            L="L"; // say we are going left
            c.d=(c.d+4)%6; // turn left
            A(); // go!

            L="F"; // say we - you get the picture
            c=K[o];
            c.p+=new[]{~w,1-w,2,1+w,w-1,-2}[c.d%6]; // look up direction of travel (~w = -w-1)
            A();
        }

        // check if we visited the end
        Q.WriteLine(n>0?"Invalid maze!":T[-n]); // if n<0, then we found the end, so spit out the corresponding route, otherwise, the maze is invlida
    }
}

Bu sitedeki Grafik Aramalarımın çoğu gibi, değişmez değerle karşılaştırmak için varsayılan olan C # yapılarını iyi kullanıyorum.


2

Python 2,703 bayt

Diğer iki sürüm kadar iyi değil, ama en azından haha ​​çalışıyor. MLabirentine ayarla .

Labirent çözme konusunda hiçbir deneyimim olmadığı için, kaba bir kuvvet yaklaşımı ile gider, burada kendi kendine geri dönmeyi gerektirmeyen tüm çözümleri bulabilir. Dönüşleri en kısa olanlardan hesaplar ve ondan en kısa sonucu seçer.

z=zip;d=z((-1,1,-2,2,-1,1),(-1,-1,0,0,1,1));E=enumerate;D={};t=tuple;o=list;b=o.index
for y,i in E(M.split('\n')):
 for x,j in E(o(i)):
  c=(x,y);D[c]=j
  if j=='S':s=c
  if j=='E':e=c
def P(s,e,D,p):
 p=o(p);p.append(s);D=D.copy();D[s]=''
 for i in d:
  c=t(x+y for x,y in z(s,i))
  if c not in p and c in D:
   if D[c]=='E':L.append(p+[c])
   if D[c]=='+':P(c,e,D,p)
def R(p):
 a=[0,1,3,5,4,2];h=d[0];x=p[0];s=''
 for c in p[1:]:
  r=t(x-y for x,y in z(c,x));n=0
  while h!=r:n+=1;h=d[a[(b(a,b(d,h))+1)%6]]
  s+=['L'*(6-n),'R'*n][n<3]+'F';x=t(x+y for x,y in z(x,h))
 return s
L=[];P(s,e,D,[])
try:l=len(min(L))
except ValueError:print"Invalid maze!"
else:print min([R(i)for i in L if len(i)==l],key=len)

Dağınık ungolfed versiyonu:

maze = """
     0 0 0 0
    0 + 0 + 0
   0 0 0 + + 0
  0 + 0 + 0 + 0
 0 0 + + 0 0 + 0
0 0 + 0 + 0 0 + 0
 E 0 + 0 0 + + 0 
  + + 0 + 0 + 0
   0 0 0 0 0 +
    + 0 + + +
     0 S 0 0
     """
directions = [(-1, -1), (1, -1),
              (-2, 0), (2, 0),
              (-1, 1), (1, 1)]


maze_dict = {}
maze_lines = maze.split('\n')
for y, row in enumerate(maze_lines):
    if row:
        for x, item in enumerate(list(row)):
            coordinates = (x, y)
            maze_dict[coordinates] = item
            if item == 'S':
                start = coordinates
            elif item == 'E':
                end = coordinates

list_of_paths = []


def find_path(start, end, maze_dict, current_path=None):
    if current_path is None:
        current_path = []
    current_path = list(current_path)
    current_path.append(start)
    current_dict = maze_dict.copy()
    current_dict[start] = '0'

    for direction in directions:
        new_coordinate = (start[0] + direction[0], start[1] + direction[1])

        if new_coordinate in current_path:
            pass

        elif new_coordinate in current_dict:
            if current_dict[new_coordinate] == 'E':
                list_of_paths.append(current_path + [new_coordinate])
                break
            elif current_dict[new_coordinate] == '+':
                find_path(new_coordinate, end, current_dict, current_path)


find_path(start, end, maze_dict)


def find_route(path):

    heading_R = [0, 1, 3, 5, 4, 2]
    heading = (-1, -1)
    current_pos = path[0]
    current_heading = directions.index(heading)
    output_string = []
    for coordinate in path[1:]:
        required_heading = (coordinate[0] - current_pos[0], coordinate[1] - current_pos[1])

        count_R = 0
        while heading != required_heading:
            count_R += 1
            heading_index = directions.index(heading)
            heading_order = (heading_R.index(heading_index) + 1) % len(heading_R)
            heading = directions[heading_R[heading_order]]

        if count_R:
            if count_R > 3:
                output_string += ['L'] * (6 - count_R)
            else:
                output_string += ['R'] * count_R

        output_string.append('F')
        current_pos = (current_pos[0] + heading[0], current_pos[1] + heading[1])
    return ''.join(output_string)


routes = []
try:
    min_len = len(min(list_of_paths))
except ValueError:
    print "Invalid maze!"
else:
    for i in list_of_paths:
        if len(i) == min_len:
            routes.append(find_route(i))

    print 'Shortest route to end: {}'.format(min(routes, key=len))

Sen yerine if heading != required_heading: while heading != required_heading: sadece birliktewhile heading != required_heading:
J Atkin

Haha teşekkürler Evet, golfed sürümünü yaparken sadece birkaç fazla karakter kapalı tıraş başardı beri, sadece şimdi bu biraz yapacağız, orijinal kodunu güncellemek olmadığını dahil birkaç şeyin farkına vardı
Peter

Güzel! (15 karakterlik dakikayı doldurma)
J Atkin

<Bu tanınmayan bir HTML etiketi, bu yüzden SE sevmiyorum.>
CalculatorFeline
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.