Hidup adalah Labirin: Kita mengambil jalan yang salah sebelum kita belajar berjalan


30

Memasukkan:

Labirin berisi karakter:

  • -- (dinding horizontal);
  • | (dinding vertikal);
  • + (koneksi);
  • (ruang berjalan);
  • I (jalan masuk);
  • U (keluar).

Ie input bisa terlihat seperti ini:

 +--+--+--+--+--+--+--+--+--+--+ 
I               |     |        | 
 +  +--+--+--+  +  +  +  +--+  + 
 |           |     |  |  |     | 
 +--+--+--+  +--+--+  +  +  +--+ 
 |           |     |     |     | 
 +  +--+--+  +  +--+--+  +--+  + 
 |     |     |     |     |     | 
 +--+  +  +--+--+  +--+--+  +  + 
 |     |        |        |  |  | 
 +  +--+--+--+  +--+--+  +  +  + 
 |     |     |     |        |  | 
 +--+  +  +--+--+  +--+--+--+--+ 
 |  |  |                 |     | 
 +  +  +--+--+--+  +--+  +  +  + 
 |     |        |  |  |  |  |  | 
 +--+--+  +  +--+  +  +  +--+  + 
 |        |     |     |  |     | 
 +  +--+--+--+  +  +  +  +  +--+ 
 |           |     |  |         U
 +--+--+--+--+--+--+--+--+--+--+ 

Keluaran:

Yang paling efisien jalan Anda harus berjalan untuk mendapatkan dari pintu masuk ke pintu keluar dari labirin (melalui labirin), ditunjukkan oleh karakter menunjukkan kiri, kanan, atas dan bawah (yaitu >; <; ^; v).

Aturan tantangan:

  • Anda dapat mengambil input dalam format apa pun yang masuk akal. String-array, String tunggal dengan baris baru, 2D char-array, dll. Semuanya merupakan format input yang memungkinkan.
  • Output dapat terdiri dari empat karakter berbeda. Yaitu ><^v; →←↑↓; ⇒⇐⇑⇓; RLUD; 0123; ABCD; dll.)
  • Anda diizinkan untuk menambahkan spasi atau mengikuti baris baru ke output jika diinginkan; ini opsional.
  • Langkah-langkah dihitung per kotak (lihat empat- +simbol untuk kotak), dan bukan per karakter.
  • Labirin dapat berukuran 5x5 hingga 15x15, dan akan selalu berbentuk kotak (sehingga tidak akan ada uji kasus untuk labirin 5x10).
  • Anda dapat mengasumsikan bahwa setiap labirin memiliki satu atau lebih jalur yang valid dari awal hingga akhir, dan Anda selalu menampilkan jalur terpendek (lihat kotak uji 4 dan 5).
  • Jika ada beberapa jalur dengan panjang yang sama, Anda dapat memilih jalur mana yang akan di-output (lihat test case 6).
  • Anda tidak dapat 'berjalan' di luar batas labirin (lihat kotak uji 7 dan 8).

Aturan umum:

  • Ini adalah , jadi jawaban tersingkat dalam byte menang.
    Jangan biarkan bahasa kode-golf mencegah Anda memposting jawaban dengan bahasa non-codegolf. Cobalah untuk memberikan jawaban sesingkat mungkin untuk bahasa pemrograman 'apa saja'.
  • Aturan standar berlaku untuk jawaban Anda, jadi Anda diperbolehkan menggunakan STDIN / STDOUT, fungsi / metode dengan parameter yang tepat, program lengkap. Panggilanmu.
  • Celah default tidak diperbolehkan.
  • Jika memungkinkan, silakan tambahkan tautan dengan tes untuk kode Anda.
  • Juga, silakan tambahkan penjelasan jika perlu.

Kasus uji:

1. Input:
 +--+--+--+--+--+--+--+--+--+--+ 
I               |     |        | 
 +  +--+--+--+  +  +  +  +--+  + 
 |           |     |  |  |     | 
 +--+--+--+  +--+--+  +  +  +--+ 
 |           |     |     |     | 
 +  +--+--+  +  +--+--+  +--+  + 
 |     |     |     |     |     | 
 +--+  +  +--+--+  +--+--+  +  + 
 |     |        |        |  |  | 
 +  +--+--+--+  +--+--+  +  +  + 
 |     |     |     |        |  | 
 +--+  +  +--+--+  +--+--+--+--+ 
 |  |  |                 |     | 
 +  +  +--+--+--+  +--+  +  +  + 
 |     |        |  |  |  |  |  | 
 +--+--+  +  +--+  +  +  +--+  + 
 |        |     |     |  |     | 
 +  +--+--+--+  +  +  +  +  +--+ 
 |           |     |  |         U
 +--+--+--+--+--+--+--+--+--+--+ 

1. Output:
>v>>>vv<v>>v>v>>vvv>>>

2. Input:
 +--+--+--+--+--+ 
I   |        |  | 
 +  +--+--+  +  + 
 |        |  |  | 
 +  +--+  +  +  + 
 |  |  |     |  | 
 +  +  +--+  +  + 
 |        |     | 
 +--+  +  +--+--+ 
 |     |         U
 +--+--+--+--+--+ 

2. Output:
>vvv>>v>>>

3. Input:
 +--+--+--+--+--+ 
U      |        | 
 +  +  +--+--+  + 
 |  |     |     | 
 +--+--+  +  +--+ 
 |        |     | 
 +  +--+--+--+  + 
 |  |     |     | 
 +  +  +  +  +--+ 
 |     |         I
 +--+--+--+--+--+ 

3. Output:
<<<^<v<^^>>^<^<<

4. Input (test case with two valid paths):
 +--+--+--+--+--+ 
U      |        | 
 +  +  +--+--+  + 
 |  |           | 
 +--+--+  +  +--+ 
 |        |     | 
 +  +--+--+--+  + 
 |  |     |     | 
 +  +  +  +  +--+ 
 |     |         I
 +--+--+--+--+--+ 

4. Output:
<<^>^<^<<^<<     (<<<^<v<^^>>^<^<< is less efficient, and therefore not a valid output)

5. Input (test case with two valid paths):
                               I
+--+--+--+--+--+--+--+--+--+--+  +--+--+--+--+
|     |              |                    |  |
+  +  +  +--+--+--+  +  +--+--+  +--+--+  +  +
|  |     |        |     |        |     |     |
+--+--+--+  +--+  +  +--+--+--+--+  +--+--+--+
|     |  |  |  |     |     |           |     |
+  +  +  +  +  +--+  +  +  +  +--+--+  +--+  +
|  |        |        |  |     |        |     |
+  +--+--+--+  +--+--+  +  +--+  +--+--+  +--+
|  |     |     |        |  |     |     |     |
+  +--+  +  +--+  +--+--+  +--+--+  +  +--+  +
|  |     |        |     |           |        |
+  +  +--+--+--+--+  +  +--+--+--+  +--+  +--+
|     |     |        |        |  |     |     |
+--+--+--+  +  +--+--+  +--+  +  +--+  +--+  +
|              |     |     |        |  |  |  |
+  +--+--+--+--+  +  +  +--+--+--+  +  +  +  +
|     |  |     |  |  |        |        |  |  |
+--+  +  +  +  +  +  +--+--+  +  +  +--+  +  +
|     |     |  |  |  |           |  |     |  |
+--+  +--+--+  +  +  +  +--+--+--+  +  +  +  +
|     |        |  |  |     |        |  |  |  |
+  +--+  +--+--+  +  +--+--+  +  +--+  +  +  +
|        |     |  |     |     |  |     |  |  |
+--+--+--+  +  +  +--+  +  +--+--+  +--+  +  +
|  |        |        |     |        |     |  |
+  +  +--+--+--+--+  +--+--+  +--+--+  +--+  +
|  |              |              |     |     |
+  +  +  +--+--+--+--+--+--+--+--+  +--+  +--+
|     |                                |     |
+--+--+--+--+--+--+--+--+--+  +--+--+--+--+--+
                            U

5. Output:
v<<<v<vv<<v<v>>^>>^^>vvv>>>v>vv<vv<<v<v<^<^^^^<vvvvv<^<v<<v>v>>>>>>>v     (v<<<v<vv<<v<v>>^>>^^>vvv>>>v>vv<vv<<v<v<^<^^^^<vvvvv>v>>>^>>^>^^>vvv<v<v<<v is less efficient, and therefore not a valid output)

6. Input:
 +--+--+--+--+--+
I               |
 +  +  +  +  +  +
 |              |
 +  +  +  +  +  +
 |              |
 +  +  +  +  +  +
 |              |
 +  +  +  +  +  +
 |               U
 +--+--+--+--+--+

6. Output:
>>v>v>v>v> or >v>v>v>v>> or >>>>>vvvv> or etc. (all are equally efficient, so all 10-length outputs are valid)

7. Input:
 I  U
+  +  +--+--+--+
|  |        |  |
+  +--+--+  +  +
|     |     |  |
+--+  +  +--+  +
|        |  |  |
+  +--+  +  +  +
|     |        |
+--+  +--+--+  +
|     |        |
+--+--+--+--+--+

7. Output:
vv>v>^>^<<^

8. Input:
 +--+--+--+--+--+
 |     |        |
 +  +--+  +--+  +
I   |     |  |  |
 +  +  +--+  +  +
U   |     |  |  |
 +--+--+  +  +  +
 |     |     |  |
 +  +--+--+--+  +
 |               
 +--+--+--+--+--+

8. Output:
>v<

Labirin dihasilkan menggunakan alat ini (dan dalam beberapa kasus sedikit dimodifikasi).


10
Saya telah menemukan solusi yang lebih pendek untuk test case ketiga! v<<<<<<^^^^^(selalu berpikir di luar kotak)
Leo

2
Jika seseorang dapat membuktikan bahwa kode mereka akan menghasilkan solusi terpendek, mengingat waktu dan memori yang cukup, apakah itu bersaing? Bahkan dalam kasus waktu berjalan yang sangat lama (akhir mode semesta)?
Yytsi

1
@JackBates Ini lelucon. Dia benar-benar berjalan di sekitar kotak ke pintu keluar: D
Yytsi

1
Saya pikir test case pertama salah, seharusnya >v>>>vv<v>>v>v>>vvv>>>.
smls

1
@KevinCruijssen Misalnya, solusi yang menguji setiap kombinasi "v ^ <>" untuk panjang hingga jumlah kotak kosong di dalam labirin. Solusi yang tepat akan ada di sana, tetapi membutuhkan waktu astronomi untuk menghitung.
Yytsi

Jawaban:


7

Retina , 338 281 275 273 261 byte

¶U
¶&
+`·(\w.+)$
|$1
((.)+I.+¶.+¶(?<-2>.)+)·
$1v
+`((.)*)\+(.).*(¶(?<-2>.)*.)((\w)|·)·?
$1$4$.4$3$6
·v
-v
G`1
·U
&
{`\B·\d+.(\w+)
$1K$&
(\w+)·\d+.\B
$&$1r
(?<=\D\2.(\w+).+?¶.*\D(\d+)[·&])\B
$1v
)`\D(\d+).\B(?=.+¶.*\D\1·(\w+))
$&$2A
^.+\d·(\w+)
&$1A
M!`&\w+
I|&

Cobalah online!


Catatan

  • Karena spasi putih yang signifikan, semua spasi ( 0x20) diganti dengan interpunct ( ·) baik dalam jawaban ini dan tautan TIO. Program ini berfungsi dengan baik jika ruang dipulihkan.
  • Penggunaan AvKruntuk naik, turun, kiri, dan kanan, masing-masing. Itu bisa diganti dengan huruf apa pun kecuali I.
  • Memakan waktu sekitar 40 detik pada TIO untuk test case 15 × 15. Sabar. Mengolah bagian untuk menemukan jalur terpendek setelah jalan mencapai pintu keluar. Ternyata itu menyita banyak waktu.
  • Dapat benar-benar pecah pada labirin yang selnya 66 atau lebih sel tetapi dapat menangani labirin dengan tinggi sewenang-wenang. Perbaikan untuk lebar sewenang-wenang membutuhkan +1 byte.

Penjelasan

Program ini terdiri dari 3 fase:

  • Sebuah tahap konstruksi untuk mengkonversi labirin untuk format kompak yang lebih mudah untuk bekerja dengan (rinci di bawah).
  • Sebuah fase mengisi untuk benar-benar memecahkan labirin menggunakan algoritma mengisi banjir.
  • Sebuah fase kembali untuk mengembalikan jalur terpendek di pintu keluar.

Format

Karena format labirin asli cukup sulit, bagian pertama dari program mengubahnya menjadi format lain.

Sel

Dalam format asli, setiap sel direpresentasikan sebagai wilayah 2 × 3:

+               <top wall>      <top wall>
<left wall>     <data/space>    <space>

Karena kolom kanan tidak berisi informasi, program mengidentifikasi sel-sel sebagai wilayah 2 × 2 dengan bagian +di kiri atas.

Ini memberi kita 3 jenis sel:

  • Sel I : Sel yang ada di dalam labirin.
  • Sel R : Sel yang ada di sebelah kanan labirin. Ini dibuat oleh bantalan yang digunakan untuk rumah pintu masuk atau keluar. Misalnya, jalan keluar Udalam uji kasus 1 adalah dalam R-Cell.
  • Sel B : Sel yang berada di bawah labirin. Seperti R-Cell, sel ini dibuat dengan cara di-padding.

Dalam format baru, sel direpresentasikan sebagai string panjang variabel:

<left wall> <column number> <top wall/exit marker> <path>

Dinding kiri dan atas disalin dari format aslinya. Nomor kolom didasarkan pada posisi horizontal sel dan digunakan untuk penyelarasan (mengidentifikasi sel langsung di atas / di bawah satu sama lain). Path adalah string alfabet yang digunakan selama fase isian untuk menyimpan jalur terpendek untuk mencapai sel itu. Penanda jalur dan keluar akan dijelaskan lebih lanjut.

Setengah sel

Meskipun sebagian besar labirin adalah sel, ada wilayah labirin yang bukan sel:

  • R Setengah sel : Jika tidak ada bantalan kanan, +s di sepanjang dinding kanan tidak membentuk sel karena berada di kolom terakhir.
  • L Setengah sel : Jika ada padding kiri, sel tidak dapat terbentuk di sana karena tidak ada +di sebelah kiri mereka. Misalnya, pintu masuk Idalam uji kasus 1 adalah dalam setengah-sel L.

Secara teknis, ada sel-T setengah di atas labirin (ketika ada lapisan atas) dan sel setengah B (sepanjang dinding bawah ketika tidak ada lapisan bawah) tetapi mereka tidak terwakili dalam format baru.

Baris atas setengah sel akan dihapus sebagai bagian dari membangun sel penuh di baris yang sama, sehingga setengah sel diwakili dalam format baru sebagai

<wall/exit marker>? <path>

Setengah R R hanya |. Setengah-L memiliki hanya Isebagai jalur, hanya penanda keluar dan jalur kosong, atau hanya dinding kosong.

Pintu masuk dan keluar

Jika pintu masuk berada di sebelah kiri, kanan atau bawah labirin, maka penanda pintu masuk Isecara alami akan dimasukkan dalam sel (setengah) sebagai jalur, yang dapat dihilangkan ketika mengembalikan jalur terakhir.

Jika pintu masuk berada di atas labirin, langkah pertama (ke bawah) diambil selama fase konstruksi karena sel-T setengah dikeluarkan selama konstruksi. Ini membuat jalur yang bisa diterapkan dalam sel penuh. Dinding atas ditutup setelah itu.

Jika jalan keluar ke kiri, kanan atau bawah labirin, maka Usecara alami akan dimasukkan dalam sel (setengah). Untuk menghindari keliru sebagai jalur, penanda keluar non-alfanumer &digunakan sebagai ganti U. Marker keluar tertanam ke dalam sel atau setengah sel (seperti yang ditentukan di atas).

Jika pintu keluar berada di atas labirin, maka itu akan menjadi satu-satunya lubang yang bisa pergi di atas barisan sel teratas (karena pintu masuk, jika ada, sudah akan ditutup). Setiap jalan yang mencapai lubang itu dapat keluar dari labirin dengan mengambil langkah ke atas.

Terakhir, setiap Sel B yang mengandung pintu masuk atau keluar harus menutup dinding kirinya untuk mencegah "penyelesaian" labirin dengan berjalan di sepanjang Sel B. Pintu masuk dan keluar di Sel R atau Sel setengah L tidak perlu diproses lebih lanjut karena algoritma pengisian banjir tidak memungkinkan pergerakan vertikal ke / dari mereka.

Contoh

Sebagai contoh, test case pertama

·+--+--+--+--+--+--+--+--+--+--+·
I···············|·····|········|·
·+··+--+--+--+··+··+··+··+--+··+·
·|···········|·····|··|··|·····|·
·+--+--+--+··+--+--+··+··+··+--+·
·|···········|·····|·····|·····|·
·+··+--+--+··+··+--+--+··+--+··+·
·|·····|·····|·····|·····|·····|·
·+--+··+··+--+--+··+--+--+··+··+·
·|·····|········|········|··|··|·
·+··+--+--+--+··+--+--+··+··+··+·
·|·····|·····|·····|········|··|·
·+--+··+··+--+--+··+--+--+--+--+·
·|··|··|·················|·····|·
·+··+··+--+--+--+··+--+··+··+··+·
·|·····|········|··|··|··|··|··|·
·+--+--+··+··+--+··+··+··+--+··+·
·|········|·····|·····|··|·····|·
·+··+--+--+--+··+··+··+··+··+--+·
·|···········|·····|··|·········U
·+--+--+--+--+--+--+--+--+--+--+·

aku s

I·3-·6-·9-·12-·15-|18-·21-|24-·27-·30-|33·
·|3··6-·9-·12-|15··18·|21·|24·|27-·30·|33·
·|3-·6-·9-·12·|15-·18-|21··24·|27··30-|33·
·|3··6-|9-·12·|15··18-|21-·24·|27-·30·|33·
·|3-·6·|9··12-·15-|18··21-·24-|27·|30·|33·
·|3··6-|9-·12-|15··18-|21-·24··27·|30·|33·
·|3-|6·|9··12-·15-·18··21-·24-|27-·30-|33·
·|3··6·|9-·12-·15-|18·|21-|24·|27·|30·|33·
·|3-·6-·9·|12··15-|18··21·|24·|27-·30·|33·
·|3··6-·9-·12-|15··18·|21·|24··27··30-·33&

dalam format baru. Anda dapat mengonversi labirin lain di sini .


Tahap konstruksi

Fase konstruksi membentuk 13 baris pertama program.

¶U
¶&

Mengonversi keluar di L Sel setengah untuk keluar dari penanda

+`·(\w.+)$
|$1

Menambahkan dinding di sebelah kiri pintu masuk dan keluar di Sel B

((.)+I.+¶.+¶(?<-2>.)+)·
$1v

Mengambil langkah pertama jika pintu masuk berada di atas labirin

+`((.)*)\+(.).*(¶(?<-2>.)*.)((\w)|·)·?
$1$4$.4$3$6

Melakukan konversi yang sebenarnya

·v
-v

Menutup lubang masuk atas

G`1

Hanya menyimpan garis dengan a 1. Karena labirin memiliki lebar paling sedikit 5 sel dan jumlah kolom terjadi dengan penambahan 3, garis dengan sel format baru harus berisi nomor kolom antara 10 dan 19.

·U
&

Mengonversi keluar di Sel R atau Sel B untuk keluar dari penanda


Isi fase

Fase pengisian membentuk 8 baris berikutnya dari program. Ini menggunakan algoritma pengisian banjir untuk mengisi semua sel dengan jalur terpendek untuk mencapai sana dari pintu masuk.

{`

Letakkan seluruh fase pengisian pada satu lingkaran untuk mengisi seluruh labirin.

\B·\d+.(\w+)
$1K$&

Setiap sel dapat bergerak ke kiri melakukannya. Sebuah sel dapat bergerak ke kiri jika

  1. ini memiliki jalur yang tidak kosong
  2. memiliki dinding kiri yang kosong; dan
  3. sel atau setengah-sel L di sebelah kirinya memiliki jalur kosong
(\w+)·\d+.\B
$&$1r

Kemudian, setiap sel dapat bergerak ke kanan melakukannya. Sebuah sel dapat bergerak ke kanan jika

  1. ini memiliki jalur yang tidak kosong
  2. sel di sebelah kanannya memiliki dinding kiri yang kosong; dan
  3. sel di sebelah kanannya memiliki jalur kosong
(?<=\D\2.(\w+).+?¶.*\D(\d+)[·&])\B
$1v

Kemudian, setiap sel dapat bergerak ke bawah melakukannya. Sebuah sel dapat bergerak ke bawah jika

  1. ini memiliki jalur yang tidak kosong
  2. ia memiliki setidaknya satu sel atau setengah sel di sebelah kanannya (yaitu bukan sel R)
  3. sel di bawahnya (yaitu sel pada baris berikutnya dengan nomor kolom yang sama) memiliki dinding atas yang kosong atau memiliki penanda keluar; dan
  4. sel di bawahnya memiliki jalur kosong

Perhatikan bahwa setengah-sel L tidak dapat bergerak ke bawah karena tidak memiliki nomor kolom.

\D(\d+).\B(?=.+¶.*\D\1·(\w+))
$&$2A

Kemudian, setiap sel dapat bergerak ke atas melakukannya. Sebuah sel dapat bergerak ke atas jika

  1. ini memiliki jalur yang tidak kosong
  2. ini memiliki dinding atas yang kosong
  3. sel di atasnya memiliki setidaknya satu sel atau setengah sel di sebelah kanannya; dan
  4. sel di atasnya memiliki jalur kosong

Fase kembali

Fase pengembalian membentuk 5 baris terakhir dari program. Fase ini mencari dan mengembalikan jalur yang diisi ke sel keluar.

Pola jalur di pintu keluar tergantung di mana jalan keluarnya:

  1. Jika keluarnya dalam sel setengah-L, maka setengah sel itu akan menjadi & <path>
  2. Jika keluar adalah dalam Sel R atau Sel B, maka sel itu akan <left wall> <column number> & <path>
  3. Jika keluar dalam sel-T setengah, maka seperti yang disebutkan di atas, sel I yang mengarah ke keluar akan berada <left wall> <column number> · <path>dan di baris atas.
^.+\d·(\w+)
&$1A

Menemukan sel di baris atas dengan dinding atas yang kosong dan jalur yang tidak kosong. Ini menangani kasus terakhir dengan menambahkan langkah terakhir dan penanda keluar.

M!`&\w+

Mencocokkan dan mengembalikan jalur yang tidak kosong setelah penanda keluar.

I|&

Menghapus penanda keluar dan Iawalan jalur.


Mengapa AvKr? Apakah mereka memiliki arti / apakah mereka singkatan dari atas, bawah, kiri, dan kanan dalam bahasa asli Anda, atau adakah alasan lain mengapa Anda memilih karakter khusus itu?
Kevin Cruijssen

@KevinCruijssen Hanya karena saya harus menggunakan karakter alfanumerik dan AvKrmerupakan hal yang paling dekat dengan tanda panah dalam alfanumerik.
TwiNight

12

Perl 6 , 259 295 byte

{my \a=S:g/(.)$0+/{$0 x($/.comb+.5)*2/3}/;sub f (\c,\v,*@p) {with (c ne any v)&&a.lines».comb[+c[0];+c[1]] ->$_ {for (/\s/??10011221!!/I/??a~~/^\N*I|I\N*$/??2101!!1012!!'').comb X-1 {f [c Z+$^a,$^b],(|v,c),@p,chr 8592+$++}
take @p if /U/}}
[~] (gather f a~~/(\N+\n)*(.)*I/,[]).min(+*)[1,3...*]}

Bagaimana itu bekerja

  1. my \a = S:g/ (.) $0+ /{ $0 x ($/.chars + .5) * 2/3 }/;

Ini meremas labirin sehingga bagian dalam setiap sel adalah 1x1 bukannya karakter ruang 2x1:

 + - + - + - + - + - + + - + - + - + - + - + 
Saya | | | Saya | | |
 + + - + - + + + + + - + - + + + 
 | | | | | | | |
 + + - + + + + + + - + + + + 
 | | | | | -> | | | | |
 + + + - + + + + + + - + + + 
 | | | | | |
 + - + + + - + - + + - + + + - + - + 
 | | U | | U
 + - + - + - + - + - + + - + - + - + - + - +

  1. sub f (\c,\v,*@p) {
        with (c ne any v) &&                   # If the coordinate wasn't visited yet
             lines».comb[+c[0];+c[1]] -> $_ {  # and a character exists there...
            for (                          # For each vector...
                 /\s/ ?? 10011221 !!       #  from a cell: (0,-1), (-1,0), (0,1), (1,0)
                 /I/  ?? a~~/^\N*I|I\N*$/
                          ?? 2101          #  from a top/bottom entrance: (1,0), (-1,0)
                          !! 1012          #  from a left/right entrance: (0,-1), (0,1)
                      !! ''                #  otherwise: none
                ).comb X-1 {
                f                       #   Recurse with arguments:
                    [c Z+ $^a, $^b],    #     c plus the vector
                    (|v, c),            #     v with c appended
                    @p, chr 8592 + $++  #     p with the correct Unicode arrow appended
            }
            take @p if /U/
        }
    }

Ini adalah fungsi pencarian jalur rekursif. Dibutuhkan tiga parameter: Koordinat saat ini c=(y,x), daftar koordinat yang sudah dikunjungi v, dan jalur yang pdiambil sejauh ini (sebagai daftar karakter panah).

Jika karakter pada koordinat saat ini adalah spasi, maka akan muncul kembali ke empat tetangganya.
Jika karakter pada koordinat saat ini adalah a I, karakter akan muncul kembali ke dua tetangga yang tidak "di sepanjang tepi", untuk memaksa solusi melewati labirin dan tidak di sekitarnya.
Jika karakter pada koordinat saat ini adalah a U, ia memanggil takestring path terakumulasi.

  1. [~] (gather f a ~~ /(\N+\n)*(.)*I/, []).min(+*)[1,3...*]

Fungsi rekursif pada awalnya disebut dengan koordinat surat itu I, yang ditemukan menggunakan regex.

Kata gatherkunci mengumpulkan semua nilai yang takedisebut di dalam fungsi, yaitu semua jalur non-siklus yang valid melalui labirin.

Jalur terpendek dipilih, setiap panah kedua dijatuhkan untuk menjelaskan fakta bahwa dua gerakan identik diperlukan untuk berpindah dari satu sel ke sel berikutnya, dan panah yang tersisa digabungkan untuk membentuk string yang dikembalikan dari lambda.


Pertama-tama, pekerjaan hebat untuk menjadi yang pertama menyelesaikan tantangan saya! :) Cerdas bagaimana Anda mengubah dua spasi menjadi satu untuk memudahkan gerakan / penghitungan yang sebenarnya. +1 dari saya. Bagaimanapun, setelah beberapa komentar dua kasus uji baru ditambahkan. Bisakah Anda memverifikasi pekerjaan ini dengan solusi Anda juga? (Juga, apakah Perl 6 memiliki TIO atau kompiler online lain yang dapat Anda tambahkan tautannya?)
Kevin Cruijssen

@KevinCruijssen: Ini berputar-putar di labirin dalam kasus uji baru. :( Saya tetap kode sekarang tio.run mendukung Perl 6, tapi untuk beberapa alasan, ini tidak bekerja di sana ... mungkin telah terlalu tua versi Perl 6.?
SMLS

Kerja bagus memperbaiki kode. Maaf untuk menentukan aturan harus melalui labirin setelah Anda sudah mengirim jawaban Anda, tetapi chapeau untuk memperbaikinya begitu cepat. Dan mengenai versi TIO saya tidak tahu. Tidak benar-benar keahlian saya ..
Kevin Cruijssen

Karena Anda adalah orang pertama yang menjawab tantangan saya empat bulan lalu, saya memberikan hadiah kepada Anda. :) Dan Terima adalah untuk jawaban Retina yang sedikit lebih pendek.
Kevin Cruijssen

5

Python 2: 302 byte

from re import*
r=lambda x:[''.join(_)for _ in zip(*x)][::-1]
z=',l)for l in s]'
def f(s,b=1,o=0,n=0):
 exec("s=[sub('(..).(?!$)',r'\\1'%s;"%z+"s=r([sub(' I ','+I+'%s);"%z*4)*b+"t=[sub('I  ','@@I'"+z
 if'I U'in`s`or n>3:return`o%4`+n/4*`s`
 return min(`o%4`+f(t,0,o,4*(t==s)),f(r(s),0,o+1,n+1),key=len)

Mengambil input sebagai array dari string semua dengan panjang yang sama. Mencetak 0ke kanan, 1ke bawah, 2ke kiri, dan 3ke atas.

Penjelasan

Saya mengambil pendekatan yang berbeda dari jawaban lainnya. Gagasan umum: pencarian secara rekursif dengan menemukan jalur terpendek antara berjalan lurus ke depan dan memutar papan 90 derajat.

from re import*
r=lambda x:[''.join(_)for _ in zip(*x)][::-1] #Rotates the board counterclockwise
z=',l)for l in s]'    #Suffix for hacky exec golfing
def f(s,b=1,o=0,n=0): #b is 1 on initial call, 0 on every recursion
                      #o is orientation
                      #n is number of rotations
 exec("s=[sub('(..).(?!$)',r'\\1'%s;"%z  #Squeeze the maze
      +"s=r([sub(' I ','+I+'%s);"%z*4)   #Add walls around the I to keep it in the maze
      *b                                 #Only if b is 1
      +"t=[sub('I  ','@@I'"+z            #Attempt to move right

 if'I U'in`s`or n>3:return`o%4`+n/4*`s`  #If the I is next to the U, return the orientation
                                         #If there were 4 rotations, return a long string
 return min(                             #Return the path with the shortest length:
            `o%4`+f(t,0,o,4*(t==s)),       #Moving forward if possible
            f(r(s),0,o+1,n+1),             #Rotating the board
        key=len)

Cobalah online!


3
Selamat datang di PPCG! Ini adalah jawaban pertama yang bagus, dan saya terkesan Anda memutuskan untuk melakukan tantangan yang cukup sulit sebagai yang pertama. Juga cerdas bagaimana Anda menempatkan dinding di sekelilingnya Iuntuk mencegah jalan keluar dari labirin. Nikmati masa tinggal Anda, dan +1 dari saya. :)
Kevin Cruijssen

2

JavaScript (ES6), 356 byte

a=>(a=a.map(s=>s.filter((_,i)=>!i|i%3)),g=([x,y])=>a[y]&&a[y][x],o=[],c=([x,y],m="",v=[])=>[[0,1],[1,0],[0,-1],[-1,0]].map(([j,k],i)=>(p=[x+j,y+k],!m&(!y|y>a[l="length"]-2)==i%2|v.includes(""+p)||(g(p)<"!"?c(p,m+"v>^<"[i],[...v,""+p]):g(p)=="U"?o.push(m.replace(/(.)\1/g,"$1")):0))),a.map((h,i)=>h.map((k,j)=>k=="I"&&c([j,i]))),o.sort((a,b)=>a[l]-b[l])[0])

Mengambil input sebagai array karakter 2D. Setiap baris harus diisi dengan satu spasi dan tidak memiliki spasi, di mana pun titik awal / akhir berada.

Menggunakan ide smls tentang memeras labirin untuk membuat setiap sel 1x1 dan menghapus panah berulang dari output.

Tidak Diikat dan Dijelaskan

a=>(
    a=a.map(s=>s.filter((_,i)=>!i|i%3)),    // squish the maze to 1x1 cells
    g=([x,y])=>a[y]&&a[y][x],               // helper func to get maze value
    o=[],                                   // resulting movesets
    c=([x,y], m="", v=[]) =>                // recursive func to search
                                            // takes current point, moves, and visited spots
        [[0,1],[1,0],[0,-1],[-1,0]].map(([j,k],i)=>(// for each direction
            p=[x+j,y+k],
            !m & (!y | y>a[l="length"]-2) == i%2 |  // if first move, prevent moving out of maze
                v.includes(""+p) || (               // also prevent if already visited
                    g(p)<"!" ?                      // is this a space?
                        c(p, m+"v>^<"[i], [...v,""+p]) // check this spot recursively
                    : g(p)=="U" ?                   // if this the end?
                        o.push(                     // add moves to moveset
                            m.replace(/(.)\1/g,"$1")) // with double arrows removed
                    : 0
                )
        )),

    a.map((h,i)=>h.map((k,j)=>      // find the starting "I" and
        k=="I" && c([j,i])          // begin recursion at that point
    )),

    o.sort((a,b)=>a[l]-b[l])[0]     // get shortest path
)

Cuplikan Tes


1

Retina , 416 byte

T` `+`^.*| ?¶.|.*$
I
#
{+` (\w)
d$1
+`(\w) 
$1a
+`(¶(.)*) (.*¶(?<-2>.)*(?(2)(?!))\w)
$1s$3
}+m`(^(.)*\w.*¶(?<-2>.)*(?(2)(?!))) 
$1w
^
w¶
w((.|¶)*(¶(.)*#.*¶(?<-4>.)*(?(4)(?!))(s)|#(d)|(a)#))
$4$5$6¶$1
{`^(.*d)(¶(.|¶)*)#(\w)
$1$4$2 #
^(.*a)(¶(.|¶)*)(\w)#
$1$4$2# 
^(.*s)(¶(.|¶)*¶(.)*)#(.*¶(?<-4>.)*(?(4)(?!)))(\w)
$1$6$2 $5#
}`^(.*w)(¶(.|¶)*¶(.)*)(\w)(.*¶(?<-4>.)*(?(4)(?!)))#
$1$5$2#$6 
s`U.*

(a|d)\1\1?
$1
ss
s
ww
w

Cobalah online!Seandainya saya melihat pertanyaan ini ketika awalnya dikirim, ini mungkin jawaban yang akan saya berikan, jadi saya tetap mempostingnya, meskipun ada jawaban yang jauh lebih baik di Retina. Penjelasan:

T` `+`^.*| ?¶.|.*$

Isi perbatasan. Ini menghindari berjalan di luar labirin (mis. Untuk test case 7).

I
#

Tempatkan penanda non-alfabet di pintu masuk.

{+` (\w)
d$1
+`(\w) 
$1a
+`(¶(.)*) (.*¶(?<-2>.)*(?(2)(?!))\w)
$1s$3
}+m`(^(.)*\w.*¶(?<-2>.)*(?(2)(?!))) 
$1w

Banjir mengisi dari pintu keluar ke pintu masuk. Pada setiap langkah, gunakan huruf untuk menunjukkan arah terbaik untuk pergi (WAS - ini mungkin akrab bagi gamer; Saya juga menganggap hjkl tapi saya merasa terlalu membingungkan). Selain itu, lebih suka mengulangi arah yang sama; ini menghindari ke kiri / kanan di antara dua sel yang berdekatan secara vertikal.

^
w¶

Anggaplah langkah pertama turun.

w((.|¶)*(¶(.)*#.*¶(?<-4>.)*(?(4)(?!))(s)|#(d)|(a)#))
$4$5$6¶$1

Tetapi jika ada huruf di atas, kiri atau kanan pintu masuk, ubah itu ke langkah pertama.

{`^(.*d)(¶(.|¶)*)#(\w)
$1$4$2 #
^(.*a)(¶(.|¶)*)(\w)#
$1$4$2# 
^(.*s)(¶(.|¶)*¶(.)*)#(.*¶(?<-4>.)*(?(4)(?!)))(\w)
$1$6$2 $5#
}`^(.*w)(¶(.|¶)*¶(.)*)(\w)(.*¶(?<-4>.)*(?(4)(?!)))#
$1$5$2#$6 

Pindahkan penanda ke arah langkah terakhir, bacalah arah langkah selanjutnya dari kotak tempat penanda itu bergerak, dan tambahkan itu ke daftar arah. Ini berulang sampaiU tercapai.

s`U.*

Hapus semuanya setelah petunjuk karena tidak diperlukan lagi.

(a|d)\1\1?
$1
ss
s
ww
w

Kotak asli berada pada tata letak 3 × 2. Saat bergerak secara vertikal jika kita zig-zag secara horizontal pengisian banjir akan mengoptimalkan gerakan dan hanya memindahkan karakter 3n-1 secara horizontal, jadi ketika membaginya dengan tiga, kita perlu mengumpulkan. Secara vertikal kami hanya membagi 2.

Saya juga menyelidiki solusi kotak persegi yang benar yaitu di mana matriks karakter itu sendiri persegi daripada menjadi tata letak 3 × 2 dengan batas opsional. Meskipun mungkin tidak sesuai dengan pertanyaan, kemampuan transpos mengurangi jumlah byte menjadi 350: Coba online!


Jawaban yang bagus, +1! Saya melihat di tautan TIO Anda, Anda telah menambahkan dua di -sekitar karakter masuk dan keluar. Karena tantangannya terutama tentang melewati labirin, saya rasa tidak apa-apa, tapi saya ingin tahu: apa masalahnya ketika Anda tidak menempatkan dinding-dinding itu di atas / di bawah Idan U? Juga, dapatkah Anda memverifikasi ini berfungsi untuk test case 7 dengan Idan Udi bagian atas, bukan sisi? TIO melebihi batas 60 detik, jadi saya tidak dapat mengujinya sendiri. Meskipun membaca penjelasan Anda tentang mencoba mencoba turun secara default, saya menganggap itu akan berfungsi dengan baik.
Kevin Cruijssen

@KevinCruijssen Jawaban "sekunder" berfungsi untuk test case 7 tetapi memerlukan karakter tambahan: Cobalah online! melanjutkan ...
Neil

@KevinCruijssen Jawaban "utama" memiliki bug di mana ia tidak bisa mengatasi jalan keluar di baris atas sama sekali. Ini juga memiliki bug yang mirip dengan jawaban "sekunder" di mana ia lebih suka berjalan di luar labirin jika bisa. (Juga, saya tidak mencapai batas 60 detik.)
Neil

Sebenarnya, saya bisa memperbaiki kedua jawaban dengan mengisi perbatasan. Saya akan melakukannya nanti ketika saya punya waktu.
Neil
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.