Waktu labirin heksagonal!

27

Saatnya untuk tantangan labirin lain, tetapi tidak seperti yang Anda tahu.

Aturan untuk tantangan ini sedikit berbeda dari kebanyakan tantangan labirin. Jenis ubin didefinisikan sebagai berikut:

  • S: Lokasi di labirin tempat Anda memulai
  • E: Lokasi yang Anda coba tuju
  • 0: Dinding yang tidak bisa Anda lewati
  • +: Lantai yang bisa Anda lewati

Anda dapat melakukan perjalanan di salah satu dari enam arah: ke kiri, ke kanan, kiri, kanan, kiri bawah, atau kanan bawah.

\ /
-S-
/ \

Labirin tidak terbungkus. Tujuannya adalah untuk menemukan string jalur terpendek untuk didapatkanS ke E.

Memasukkan:

Input adalah spasi yang dipisahkan garis seperti labirin yang ditampilkan. Tidak ada spasi tambahan yang akan mengikuti garis.

Keluaran:

Serangkaian R, Ldan Fdi mana

  • R memutar Anda ke kanan (searah jarum jam) 60 derajat
  • L memutar Anda ke kiri (berlawanan arah jarum jam) 60 derajat
  • F menggerakkan Anda satu ruang ke arah yang Anda tunjuk

Anda mulai menunjuk left-up

Jalur terpendek dihitung oleh panjang string yang dihasilkan, bukan jumlah posisi yang dikunjungi. Program Anda harus mencetak jalur terpendek sebagai solusinya.

Jika labirin tidak dapat dipecahkan, Anda harus menampilkannya Invalid maze! .

( >>>adalah output)

     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

(Perhatikan bahwa beberapa labirin memiliki solusi lain yang panjangnya sama tetapi tidak tercantum di sini)

J Atkin
sumber
27
Berharap untuk solusi Hexagony ...
bkul
3
Saya akan memberikan hadiah 500 poin untuk solusi Hexagony.
lirtosiast
@ lirtosiast2 tahun kemudian, saya pikir hexagony mungkin merupakan peregangan untuk masalah ini;)
J Atkin
Mari kita tunggu beberapa tahun lagi.
user202729
Mungkinkah ada trailing newline?
user202729

Jawaban:

17

Python 2, 291 byte

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!"

Fungsi,, fmengambil labirin sebagai daftar baris, dan mengembalikan solusi, jika ada.

Penjelasan

Lakukan pencarian luas pertama pada grafik pasangan posisi / arah untuk menemukan jalur terpendek dari SkeE .

Yang menarik adalah menemukan cara yang ringkas untuk mewakili posisi dan arah pada kisi heksagonal, yang mengakui "loncatan" sederhana (yaitu, bergerak ke arah tertentu) dan rotasi. Sangat menggoda untuk menggunakan bilangan kompleks di sini, untuk mewakili koordinat pada kisi heksagonal "nyata", tetapi ini bukan ide yang bagus untuk sejumlah alasan, yang paling serius adalah kenyataan bahwa kita perlu memasukkan in3 suatu tempat untuk membuatnya bekerja (sin 60 ° = √3 / 2), yang, ketika menggunakan angka floating-point, adalah jalan keluar jika kita membutuhkan presisi absolut (misalnya, untuk melacak keadaan yang telah kita kunjungi;) Anda dapat mencoba menjalankan konsol JavaScript dan mengetik Math.sqrt(3)*Math.sqrt(3) == 3dan melihat sendiri.

Tapi, kita bisa menggunakan sedikit trik! Alih-alih menggunakan bilangan kompleks, mari kita mendefinisikan bilangan heksagonal dalam nada yang sama, sebagai pasangan bilangan real a + bh , di mana h memainkan peran yang mirip dengan i imajiner ketika berhadapan dengan bilangan kompleks. Sama seperti dengan bilangan kompleks, kita dapat mengaitkan pasangan ( a , b ) dengan titik pada bidang, di mana sumbu nyata menunjuk ke kanan, sumbu imajiner menunjuk 60 ° ke atas, dan keduanya memotong unit segi enam reguler ketika nyata dan bagian imajiner sama dengan 1, masing-masing. Memetakan sistem koordinat ini ke sel-sel labirin sepele.

Gambar 1

Tidak seperti i , konstanta h didefinisikan oleh hubungan h 2 = h - 1 (penyelesaian untuk h mungkin mengungkapkan beberapa wawasan.) Dan hanya itu! Bilangan heksagonal dapat ditambahkan dan dikalikan, menggunakan relasi di atas, seperti bilangan kompleks: ( a + bh ) + ( c + dh ) = ( a + c ) + ( b + d ) h ,
dan ( a + bh ) · ( c + dh ) = ( ac - bd) + ( iklan + bc + bd ) h . Operasi-operasi ini memiliki interpretasi geometris yang sama dengan rekan-rekan mereka yang kompleks: penjumlahan adalah penjumlahan vektor, dan perkalian adalah penskalaan dan rotasi. Secara khusus, untuk memutar bilangan heksgonal 60 ° berlawanan arah jarum jam, kami mengalikannya dengan h :
( a + bh ) · h = - b + ( a + b ) h , dan untuk memutar angka yang sama 60 ° searah jarum jam, kami membagi oleh h :
( a + bh ) / h = ( a +bh ) · (1 - h ) = (a + b) - ah . Misalnya, kita dapat mengambil angka heksagonal satuan yang menunjuk ke kanan, 1 = (1, 0), lingkaran penuh, berlawanan arah jarum jam, dengan mengalikannya dengan h enam kali:
(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 ini menggunakan angka heksagonal dalam mode ini untuk mewakili posisi saat ini di labirin dan arah saat ini, untuk maju dalam arah yang ditentukan, dan untuk memutar arah ke kiri dan ke kanan.

Elo
sumber
31

Hexagony , 2437 byte

Program yang ditunggu-tunggu ada di sini:

(.=$>({{{({}}{\>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'&?={&?#<$

Cobalah online!

Versi "Dapat dibaca":

                             ( . = $ > ( { { { ( { } } { \ > 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 ' & ? = { & ? # < $

Diuji pada Esoteric IDE: TIO mungkin mengalami time out pada beberapa kasus uji yang lebih besar tetapi semua diverifikasi. Terima kasih banyak kepada Timwi, ini tidak akan mungkin terjadi tanpa IDE.

Ada sedikit ruang kosong, jadi saya mungkin bisa memasukkan ini ke segi enam sisi-panjang (bukan sisi-panjang 29) tapi itu akan menjadi tugas besar jadi saya mungkin tidak akan mencobanya.

Penjelasan Dasar

Klik gambar untuk versi yang lebih besar dan lebih detail.

Fungsi

Fungsi
Catatan: Divisi umumnya benar tetapi kadang-kadang bisa menjadi dugaan kasar.

Kode ini cukup "fungsional" - sebanyak yang dimungkinkan oleh Hexagony. Ada delapan fungsi utama dalam kode ini yang berlabel pada diagram di atas, dinamai dengan angka yang dipanggil (jadi nomor penunjuk instruksi mereka adalah nomor mod 6). Dalam urutan panggilan (kasar), mereka adalah (nama yang dikutip adalah lokasi dalam memori yang akan dijelaskan kemudian):

  • S: Fungsi awal - membaca input dan mengatur "array referensi", kemudian memulai "path stack" dengan tiga jalur F, Rdan Lsiap untuk pemrosesan utama. Instruksi penunjuk 0 bergerak ke fungsi 0 sementara eksekusi bergerak ke fungsi 1.
  • 1 (-11): Fungsi utama - menggunakan 2 untuk mendapatkan jalur, 3 untuk memeriksa validitasnya, dan jika valid pergi ke fungsi -110 / -10 dua kali dan kemudian 4 tiga kali untuk menyalin jalur baru di jalur " stack ", selesai dengan kembali ke dirinya sendiri. Dapat memanggil fungsi 5 jika jalurnya ada di lokasi akhir.
  • 2: Mendapat jalur berikutnya dari "jalur tumpukan" yang siap diproses, memanggil fungsi -1 jika tidak ada jalur yang tersisa di tumpukan. Kembali berfungsi 1.
  • 3: Mengambil sepasang nilai serta nomor pemindahan dan memeriksa "array referensi" untuk melihat apakah jalur saat ini telah berakhir di lokasi yang valid. Lokasi yang valid adalah awal dalam 3 gerakan pertama, atau apa saja+ 2 gerakan yang pertama kali dicapai. Kembali berfungsi 1.
  • -10 / -110: Menyalin jalur saat ini. Kembali berfungsi 1.
  • 0: Membantu fungsi 1 untuk mengatur arah gerakan F . Kembali berfungsi 1.
  • 4: Mengambil salinan jalur saat ini dan saling terkait dengan fungsi 1 mengubahnya ke jalur yang sama dengan salah satu F, Ratau Lditambahkan. Kembali berfungsi 1.
  • 5: Mengambil jalur dan mencetak jalur yang benar (mis. FFLF), Lalu menghentikan program.
  • -1: Cetakan Invalid maze!dan berakhir.
  • (Panah ganda): Karena kekurangan ruang, fungsi 1 / -11 harus masuk ke ruang di atas fungsi -1.

Ingatan

Tata letak memori
Catatan: Berkat IDE Esoterik lagi untuk diagram

Memori terdiri dari tiga bagian utama:

  • Array referensi: Kisi disimpan 2 kolom terpisah, dengan nilai pada setiap langkah:
    • 0 mewakili a ,0 atau tempat yang valid yang diakses lebih banyak bergerak dari yang dibutuhkan untuk keluar dari tempat itu ke arah mana pun.
    • 1 mewakili suatu +yang belum tercapai.
    • (angka yang lebih tinggi) mewakili nomor bergerak di mana akan ada cukup banyak gerakan untuk keluar dari tempat ke segala arah.
    • 10 juga mewakili baris baru: ini tidak pernah tercapai dengan asumsi mereka segera mengikuti karakter non-white-space terakhir.
  • Rail: Terdiri dari -1s dengan satu -2di sebelah kiri, memungkinkan penunjuk memori dengan cepat kembali ke area pemrosesan inti.
  • Tumpukan jalur: Menyimpan setiap jalur yang belum diuji dalam urutan dengan ID jalur (yang terkait langsung dengan nomor pemindahan sehingga jalur yang lebih pendek diuji terlebih dahulu). Path disimpan sebagai berikut:
    Tata letak jalur
    • Rot: rotasi di ujung jalan saat ini: 0 untuk kiri dan meningkat searah jarum jam menjadi 5
    • Pindah: nomor pindah saat ini (instruksi - 1)
    • Path: jalan saat ini, disimpan dalam kuaterner dengan F, R, Lsebagai 1, 2, 3masing-masing
    • x / y: koordinat pada akhir jalur saat ini: x +1 -1tepat lalu nilai y naik (meskipun y = 0 diproses sebagai 1 untuk keperluan memisahkan rel dari data referensi)

Lokasi memori penting lainnya:

  1. X / y dari Edisimpan di sini.
  2. Ruang ini digunakan untuk jalur transisi masuk dan keluar dari memori.
  3. Lokasi ini adalah pusat tempat setiap jalur disimpan selama pemrosesan.
boboquack
sumber
Langkah selanjutnya adalah menjalankan program Anda melalui program Anda untuk menemukan rute labirin terpendek.
Veskah
Saya tahu seseorang akan mempostingnya. Akhirnya ... / Saya juga punya rencana berbeda, yang mungkin harus mengambil kode kurang dari milik Anda. Sebenarnya tidak pernah punya waktu untuk mengimplementasikannya.
user202729
@ user202729 akan menarik untuk mendengarnya. Metode ini mungkin bisa golf setidaknya 2 ukuran ke bawah saya akan mengatakan, tetapi hampir pasti ada sesuatu yang lebih baik di luar sana.
boboquack
1
Tinggal menunggu @ lirtosiast.
J Atkin
1
Permintaan maaf atas keterlambatan ini.
lirtosiast
6

Python 3, 466 byte

Mungkin akan berakhir lebih kecil jika saya menggunakan pencarian kedalaman-pertama atau sesuatu. Monstrositas ini menggunakan Dijkstra dan cukup cepat, tetapi sangat panjang.

Kode mendefinisikan fungsi Syang mengambil string multiline dengan labirin dan mengembalikan hasilnya.

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]

Ini adalah tes kode.

Tidak disatukan

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
PurkkaKoodari
sumber
Wow sangat bagus. Berapa lama waktu yang Anda butuhkan untuk menulis?
J Atkin
1
@JAtkin Yah, file itu dibuat 1,5 jam yang lalu, meskipun saya tidak yakin berapa banyak waktu yang saya habiskan untuk mengerjakan kode. Juga, ini jam 3 pagi di sini, jadi produktivitas saya jelas maksimal.
PurkkaKoodari
Bagus, saya menghabiskan 2+ jam, dan sebagian besar milik saya sudah ditulis untuk labirin standar.
J Atkin
Apakah Anda memiliki versi tanpa ungolfed?
J Atkin
1
@JAtkin Ini diperlukan, karena Anda mungkin perlu berbalik di awal. Tanpa posisi awal itu akan berhasil L,,R.
PurkkaKoodari
3

Groovy, 624 byte. Depan!

Waktu waktu bola bergulir dengan yang besar. Mengambil string multi-line sebagai argQ

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!")}

Versi tidak disatukan:

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!"
J Atkin
sumber
3

C #, 600 574 byte

Program lengkap, menerima input dari STDIN, output ke STDOUT.

Sunting: ada bug dalam penanganan bungkus (tidak merusak salah satu kasus uji yang diberikan) yang akan menambahkan 1 byte, jadi saya melakukan sedikit lebih banyak golf untuk mengimbangi.

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

Dimulai dengan membaca di peta, menambahkan (ke setiap baris sehingga tahu di mana itu berakhir, dan dapat kembali dan menambahkan banyak ruang untuk membuat peta persegi panjang, dan dengan deretan ruang di sepanjang sisi kanan (ini menghemat kami melakukan pembungkus cek seperti yang akan dijelaskan di bawah). Ini berfungsi lebar persegi panjang di beberapa titik dalam hal ini, dan memastikan panjang total Peta.

Selanjutnya, ini menginisialisasi segalanya untuk Breadth-First-Search. Dua array biggish dibuat, satu untuk menyimpan semua negara yang perlu kita jelajahi dalam pencarian kita, yang lain untuk mencatat rute yang kita ambil untuk sampai ke masing-masing negara. Keadaan awal ditambahkan ke array karena, dengan pointer kepala dan ekor diatur sebelumnya di atas. Semuanya terindeks 1.

Kami kemudian beralih sampai ekor menabrak kepala, atau setidaknya itu tampaknya telah menabrak kepala. Untuk setiap keadaan yang telah kami kunjungi, kami berupaya menambahkan keadaan baru di posisi yang sama dengan kami diputar ke kiri atau ke kanan, dan kemudian ke tempat di mana kami telah bergerak maju. Arah diindeks, dengan arah awal (default ke 0) sesuai dengan "kiri atas".

Ketika kami mencoba untuk mengantri keadaan, itu terikat diperiksa, tetapi tidak membungkus diperiksa, karena kolom ruang di sisi kanan, yang diambil oleh "apakah kita diizinkan berada di sini?" centang (Anda tidak diizinkan berada di spasi). Jika keadaan antri, kami kemudian memeriksa apakah ada diE sel, dan jika ya, kami mengatur kepala antrian menjadi minus itu sendiri, yang menyebabkan loop utama keluar, dan memberi tahu baris terakhir program untuk mencetak keluar rute yang sesuai, bukan pesan kegagalan (yang menunjukkan jika kita kehabisan negara untuk memperluas (ekor menabrak kepala)).

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

Seperti kebanyakan Pencarian Grafik saya di situs ini, saya memanfaatkan C # struct, yang standarnya dibandingkan dengan nilai literal.

VisualMelon
sumber
2

Python 2, 703 byte

Tidak sebagus dua versi lainnya, tetapi setidaknya ini berfungsi haha. SetM ke labirin.

Karena saya tidak punya pengalaman dalam memecahkan labirin, itu hanya berjalan dengan pendekatan brute force, di mana ia akan menemukan semua solusi yang dapat dilakukan yang tidak melibatkan menyeberang kembali dengan sendirinya. Ini menghitung belokan dari yang terpendek, dan kemudian memilih hasil terpendek dari itu.

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)

Versi ungolfed berantakan:

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))
Peter
sumber
Anda dapat menggantinya if heading != required_heading: while heading != required_heading: denganwhile heading != required_heading:
J Atkin
Ya terima kasih haha, saya telah memperhatikan beberapa hal termasuk ketika melakukan versi golf, hanya saja tidak memperbarui kode asli, saya akan melakukan itu sekarang karena saya baru saja berhasil mencukur beberapa karakter lagi
Peter
Bagus! (mengisi 15 karakter min)
J Atkin
<Ini adalah tag HTML yang tidak dikenal, jadi SE tidak suka.>
CalculatorFeline