Hayat bir labirent: yürümeyi öğrenmeden önce yanlış yolu kullanıyoruz


30

Giriş:

Karakterleri içeren bir labirent:

  • -- (yatay duvar);
  • | (dikey duvar);
  • + (bağ);
  • (yürüme alanı);
  • I (Giriş);
  • U (çıkış).

Yani bir girdi şöyle görünebilir:

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

Çıktı:

En verimli yürümeniz gerektiği yolu sağa, yukarı ve aşağı, sol belirten karakterleri ile gösterilir (labirent) labirentin çıkış, girişinden almak için (yani >; <; ^; v).

Meydan okuma kuralları:

  • Girişi herhangi bir makul formatta alabilirsiniz. String-array, single with new-lines, 2D karakter dizisi, vb. Olası giriş biçimleridir.
  • Çıktı, dört farklı karakterden oluşabilir. Yani ><^v; →←↑↓; ⇒⇐⇑⇓; RLUD; 0123; ABCD; vb.).
  • İsterseniz çıktıya boşluk ekleyebilir veya çıktınızı izleyebilir; bu isteğe bağlıdır.
  • Adımlar kare başına sayılır ( +kareler için dört simgeye bakın ) ve karakter başına değil.
  • Labirent 5x5 ile 15x15 arasında olabilir ve her zaman bir kare olacaktır (bu nedenle 5x10 labirentinde herhangi bir test durumu olmayacaktır).
  • Her labirentin, baştan sona kadar bir ya da daha fazla geçerli yolu olduğunu varsayabilir ve her zaman en kısa süreyi yazdırabilirsiniz (bkz. Test durumları 4 ve 5).
  • Aynı uzunlukta birden çok yol varsa, hangisinin çıkarılacağını seçebilirsiniz (bkz. Test durumu 6).
  • Labirentin sınırları dışında 'yürüyemezsiniz' (bkz. Test durumları 7 ve 8).

Genel kurallar:

  • Bu , bayt cinsinden en kısa cevap kazanır.
    Code-golf dillerinin, codegolfing olmayan dillerle cevap göndermekten vazgeçmesine izin vermeyin. Herhangi bir programlama dili için mümkün olduğunca kısa bir cevap bulmaya çalışın.
  • Cevabınız için standart kurallar geçerlidir , bu nedenle STDIN / STDOUT, fonksiyonlar / yöntem ile uygun parametreler, tam programlar kullanabilirsiniz. Senin çağrı.
  • Varsayılan Loopholes yasaktır.
  • Mümkünse, lütfen kodunuz için test içeren bir bağlantı ekleyin.
  • Ayrıca, lütfen gerekirse bir açıklama ekleyin.

Test durumları:

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<

Bu araç kullanılarak oluşturulan labirentler (ve bazı durumlarda hafifçe değiştirilmiş).


10
Üçüncü test olayı için daha kısa bir çözüm buldum! v<<<<<<^^^^^(her zaman kutunun dışında düşünün)
Leo

2
Bir kişi kendi kodunun en kısa süreyi vereceğini ispatlayabilirse, yeterli zaman ve hafızaya sahipse rekabet eder mi? Çok uzun bir çalışma süresi olsa bile (evren modasının sonu)?
Yytsi

1
@JackBates Bu bir şaka. Kelimenin tam anlamıyla çıkış için kutunun etrafında yürür: D
Yytsi

1
Bence ilk test davası yanlış, öyle olmalı >v>>>vv<v>>v>v>>vvv>>>.
sml

1
@KevinCruijssen Örneğin, "v ^ <>" nin her bir kombinasyonunu labirentin içindeki boş kutuların miktarına kadar test eden bir çözüm. Doğru çözüm orada olacak, ancak hesaplanması astronomik zaman alıyor.
Yytsi

Yanıtlar:


7

Retina , 338 281 275 273 261 bayt

¶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|&

Çevrimiçi deneyin!


notlar

  • Önemli boşluklar nedeniyle, tüm boşluklar 0x20( ·) hem bu yanıtta hem de TIO bağlantısında yorumlayıcı ( ) ile değiştirilir . Alanlar geri yüklenirse, program iyi çalışır.
  • AvKrSırasıyla, yukarı, aşağı, sola ve sağa kullanır . Bunlar dışında herhangi bir harfle değiştirilebilir I.
  • 15 × 15 test durumu için TIO'da yaklaşık 40 saniye sürüyor. Sabırlı ol. Yol çıkışa ulaştığında en kısa yolu bulmak için parçayı elden geçirdi. Çok zaman alıyordu.
  • 66 ya da daha fazla hücre genişliğindeki labirentten tamamen kopabilir ancak rastgele yükseklikte labirentlerle başa çıkabilir. Keyfi genişlik için bir düzeltme +1 bayt alır.

açıklama

Program 3 aşamadan oluşmaktadır:

  • Labirenti, üzerinde çalışması kolay olan kompakt bir formata dönüştüren bir yapım aşaması (aşağıda detaylandırılmıştır).
  • Bir sel doldurma algoritması kullanarak labirent aslında çözmek için bir doldurma aşaması .
  • Çıkıştaki en kısa yolu döndürmek için bir dönüş aşaması .

Biçim

Orijinal labirent formatı oldukça hantal olduğundan, programın ilk kısmı onu farklı bir formata dönüştürür.

Hücreler

Orijinal formatta, her bir hücre 2 x 3 bölge olarak temsil edilir:

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

Sağ sütun hiçbir bilgi içermediğinden, program hücreleri +üst solda bir a ile 2 × 2 bölge olarak tanımlar .

Bu bizi 3 çeşit hücreyle bırakır:

  • Ben Hücreler : Labirentin içinde uygun şekilde bulunan hücreler.
  • R Hücreler : Labirentin sağında bulunan hücreler. Bunlar giriş veya çıkışı barındırmak için kullanılan dolgu malzemesi ile oluşturulur. Örneğin, Utest durumu 1'deki çıkış bir R Hücresinde.
  • B Hücreler : Labirentin altındaki hücreler. R-Hücreleri gibi bunlar da doldurma ile oluşturulur.

Yeni formatta, hücreler değişken uzunluklu bir dize olarak temsil edilir:

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

Sol ve üst duvar orijinal formattan kopyalanır. Sütun numarası hücrenin yatay pozisyonuna dayanır ve hizalama için kullanılır (hücreleri doğrudan birbirlerinin üstünde / altında tanımlayarak). Yol, doldurma aşamasında bu hücreye ulaşacak en kısa yolu kaydetmek için kullanılan alfabetik bir dizedir. Yol ve çıkış işaretçisi ayrıca açıklanacaktır.

Yarı-hücre

Labirentin çoğu hücre olmasına rağmen, labirentin hücreleri olmayan bölgeleri vardır:

  • R Yarım hücreler : Sağ dolgu +olmazsa, sağ duvar boyunca bulunan s, son sütunda oldukları için hücreler oluşturmaz.
  • L Yarım hücreler : Sol dolgu varsa, solunda hiç olmadığından hücreler orada oluşamaz +. Örneğin, Itest durumu 1'deki giriş bir L Yarım hücrededir.

Teknik olarak, labirentin üstünde T üst hücreleri ( üst doldurma varken) ve B yarım hücreleri (alt duvar boyunca yokken alt duvar boyunca) vardır, ancak bunlar yeni formatta gösterilmezler.

Yarım hücrenin üst sırası, aynı satırdaki tam hücrelerin oluşturulmasının bir parçası olarak kaldırılır, bu nedenle yarım hücreler yeni biçimde temsil edilir.

<wall/exit marker>? <path>

Bir R Half-hücreleri sadece |. L Yarım hücrelerinde tam Iyol, sadece çıkış işareti ve boş bir yol veya sadece boş bir duvar bulunur.

Girişler ve çıkışlar

Giriş, labirentin sola, sağına veya altına ise, giriş işareti Idoğal olarak (yarım) hücreye, son yolu döndürürken çıkarılabilecek olan yol olarak dahil edilir.

Giriş labirentin üzerindeyse, inşaat aşaması sırasında ilk (aşağı) adım atılır, çünkü T yarı hücreleri inşaat sırasında çıkarılır. Bu, uygulanabilir bir yolu dolu bir hücrede tutar. Üst duvar daha sonra kapanır.

Çıkış, labirentin sola, sağına veya altına ise, Udoğal olarak (yarım) hücreye dahil edilir. Bir yol olarak hatalı olmaktan kaçınmak için, &yerine alfanum olmayan çıkış işaretçisi kullanılır U. Çıkış işareti bir hücreye veya yarım hücreye gömülür (yukarıda belirtildiği gibi).

Eğer çıkış labirentin üzerindeyse, hücre üst sırasının üstünden geçebilecek tek delik olacaktır (eğer varsa giriş için zaten kapalı olacaktır). Bu deliğe ulaşan herhangi bir yol yukarı doğru bir adım atarak labirentten çıkabilir.

Son olarak, giriş veya çıkışı içeren herhangi bir B Hücresi, B Hücreleri boyunca yürüyerek labirentin "çözülmesini" önlemek için sol duvarını kapatmalıdır. R Hücrelerinde veya L'de girişler ve çıkışlar Yarım hücrelerin başka işlemlere ihtiyacı yoktur, çünkü taşma dolgusu algoritması bunlara dikey hareketlerin girmesine izin vermez.

Örnek

Örnek olarak, ilk test davası

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

olduğu

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&

yeni biçimde. Burada diğer labirentlere dönüştürebilirsiniz .


Yapı aşaması

İnşaat aşaması programın ilk 13 satırını oluşturur.

¶U
¶&

İşaretleyiciden çıkmak için L Half-cell içindeki çıkışı dönüştürür

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

B Hücrelerinde giriş ve çıkış soluna duvar ekler

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

Giriş labirentin üzerindeyse ilk adımı atar

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

Gerçek dönüşüm gerçekleştirir

·v
-v

Üst giriş deliğini kapatır

G`1

Sadece a ile satırları tutar 1. Labirentler en az 5 hücre genişliğinde olduğundan ve sütun sayıları 3'lük artışlarla gerçekleştiğinden, yeni biçimli hücrelere sahip bir satır 10 ile 19 arasında bir sütun numarasına sahip olmalıdır.

·U
&

İşaretleyiciden çıkmak için R Hücresi veya B Hücresindeki çıkışı dönüştürür


Doldurma aşaması

Doldurma aşaması programın bir sonraki 8 satırını oluşturur. Tüm hücreleri girişten erişebilecek en kısa yolla doldurmak için bir sel doldurma algoritması kullanır.

{`

Bütün labirenti doldurmak için tüm doldurma aşamasını bir döngüye yerleştirir.

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

Sola hareket edebilen her hücre bunu yapar. Bir hücre eğer sola hareket edebilir

  1. boş olmayan bir yolu var
  2. boş bir sol duvarı vardır; ve
  3. hücre veya soldaki L yarı hücresinin boş bir yolu var
(\w+)·\d+.\B
$&$1r

Sonra, her hücre sağa hareket edebiliyor. Bir hücre sağa hareket edebiliyorsa

  1. boş olmayan bir yolu var
  2. sağındaki hücrenin boş bir sol duvarı vardır; ve
  3. sağındaki hücrenin boş bir yolu var
(?<=\D\2.(\w+).+?¶.*\D(\d+)[·&])\B
$1v

Sonra aşağı hareket edebilen her hücre bunu yapar. Bir hücre varsa aşağı hareket edebilir

  1. boş olmayan bir yolu var
  2. sağında en az bir hücre veya yarım hücre var (yani bir R hücresi değil)
  3. altındaki hücre (yani aynı sütun numarasına sahip bir sonraki satırdaki hücre) boş bir üst duvara veya çıkış işaretçisine sahiptir; ve
  4. altındaki hücrenin boş bir yolu var

L Yarım hücrelerin sütun numaralarına sahip olmadıkları için aşağıya hareket edemeyeceğini unutmayın.

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

Sonra, hareket edebilen her hücre bunu yapar. Bir hücre varsa yukarı hareket edebilir

  1. boş olmayan bir yolu var
  2. boş bir üst duvarı var
  3. üstündeki hücre sağında en az bir hücre veya yarım hücreye sahiptir; ve
  4. üstündeki hücre boş bir yola sahip

Dönüş aşaması

Dönüş aşaması programın son 5 satırını oluşturur. Bu aşama çıkış hücresine doldurulmuş yolu arar ve döndürür.

Çıkıştaki yolun deseni çıkışın bulunduğu yere göre değişir:

  1. Çıkış bir L Yarım hücresindeyse, bu yarım hücre & <path>
  2. Çıkış bir R Hücresi veya B Hücresindeyse, bu hücre <left wall> <column number> & <path>
  3. Çıkış bir T Yarım hücresindeyse, yukarıda belirtildiği gibi, çıkışa giden I Hücresi <left wall> <column number> · <path>üst satırda ve olacaktır .
^.+\d·(\w+)
&$1A

Boş bir üst duvarı ve boş olmayan bir yolu olan üst satırdaki bir hücreyi bulur. Bu, son adımı ve çıkış işaretçisini ekleyerek son durumu önemser.

M!`&\w+

Bir çıkış işaretçisini izleyerek boş olmayan bir yolu eşleştirir ve döndürür.

I|&

Çıkış işaretçisini ve Iyolun önekini kaldırır .


Neden AvKr? Ana dillerinde yukarı, aşağı, sola ve sağa kısaltmaları var mı, yoksa bu karakterleri seçmenizin başka bir nedeni var mı?
Kevin Cruijssen

@KevinCruijssen Basitçe alfanümerik karakterleri kullanmam gerektiği ve alfanumdaki AvKroklara en yakın şey olduğum için.
TwiNight

12

Perl 6 , 259 295 bayt

{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...*]}

Nasıl çalışır

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

Bu labirenti sıkar, böylece her hücrenin içi 2x1 boşluk karakterleri yerine 1x1 olur:

 + - + - + - + - + - + + - + - + - + - + - + 
Ben | | | Ben | | |
 + + - + - + + + + + - + - + + + 
 | | | | | | | |
 + + - + + + + + + - + + + + 
 | | | | | -> | | | | |
 + + + - + + + + + + - + + + 
 | | | | | |
 + - + + + - + - + + - + + + - + - + 
 | | 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/
        }
    }

Bu özyinelemeli yol bulma işlevidir. Üç parametre alır: Geçerli koordinat c=(y,x), önceden ziyaret edilmiş koordinatların listesi vve pşimdiye kadarki yol (ok karakterleri listesi olarak).

Eğer mevcut koordinattaki karakter boşluksa, dört komşusuna tekrar başlar.
Eğer mevcut koordinattaki karakter a ise I, etrafındakilere değil labirentten geçmeye zorlamak için "kenarı" olmayan iki komşuya yeniden başlar.
Geçerli koordinattaki karakter a ise, toplam yol dizgisini Uçağırır take.

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

Özyinelemeli işlevi başlangıçta I, bir regex kullanarak bulunan mektubun koordinatı ile adlandırılır .

gatherAnahtar kelime hangi tüm değerleri toplayan takeişlevi içinde çağrıldı, labirent yani tüm geçerli olmayan döngüsel yolları.

En kısa yol seçilir, her ikinci ok bir hücreden diğerine almak için iki özdeş hareketin gerekli olduğu gerçeğini hesaba katar ve kalan oklar lambdadan döndürülen dizgiyi oluşturmak için birleştirilir.


Öncelikle, meydan okumamı tamamlayan ilk kişi olmak büyük iş! :) Gerçek hareketi / sayımı kolaylaştırmak için iki boşluğu bir ile nasıl değiştirdiğin akıllıca. Benden +1. Neyse, bazı yorumlardan sonra iki yeni test durumu eklendi. Bu çalışmayı çözümünüzle de doğrulayabilir misiniz? (Ayrıca, Perl 6'da link ekleyebileceğiniz bir TIO ya da başka bir çevrimiçi derleyici var mı?)
Kevin Cruijssen

@KevinCruijssen: Yeni test durumlarında labirentte dolaştı. :( Ben şimdi kod sabit tio.run Perl 6 destekler, ancak bazı nedenlerden dolayı, bu belki bir çok eski Perl 6 sürümü vardır ... Orada çalışmıyor.?
SML'ler

Kodu düzeltmek harika bir iş. Cevabınızı gönderdikten sonra labirentten geçmek zorunda olma kuralını belirttiğim için üzgünüm, ama çok hızlı bir şekilde düzeltmek için chapeau. Ve TIO sürümüyle ilgili hiçbir fikrim yok. Gerçekten benim uzmanlık alanım değil ...
Kevin Cruijssen

Dört ay önce mücadeleme ilk cevap veren sen olduğun için, sana ödül verdim. :) Ve Kabul Et biraz daha kısa Retina cevabı için.
Kevin Cruijssen

5

Python 2: 302 bayt

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)

Aynı uzunlukta bir dizi dizisi olarak girdiyi alır. 0Sağa, 1aşağıya, 2sola ve 3yukarıya doğru yazdırır .

açıklama

Diğer cevaplardan farklı bir yaklaşım benimsedim. Genel fikir: dümdüz ileri gitmek ve tahtayı 90 derece döndürmek arasındaki en kısa yolu bularak tekrar tekrar arayın.

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)

Çevrimiçi deneyin!


3
PPCG'ye Hoşgeldiniz! Bu harika bir ilk cevap ve ilk olarak oldukça zorlu bir mücadeleye girmeye karar vermenize çok etkilendim. Ayrıca I, yolun labirentin dışına çıkmasını önlemek için etrafına duvarları nasıl yerleştirdiğiniz de akıllı . Kaldınız ve benden +1. :)
Kevin Cruijssen

2

JavaScript (ES6), 356 bayt

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

Girdiyi 2B karakter dizisi olarak alır. Her satırın bir boşluk bırakması ve başlangıç ​​/ bitiş noktaları nerede olursa olsun hiçbir boşluk bırakmaması gerekir.

Her hücreyi 1x1 yapmak ve tekrarlanan okları çıktıdan çıkarmak için smls'in labirenti ezmesi fikrini kullanır .

Ungolfed ve Açıklaması

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
)

Test Parçacığı


1

Retina , 416 bayt

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

Çevrimiçi deneyin! Bu soruyu ilk başta yayınlandığında görseydim, muhtemelen vereceğim cevap buydu, bu yüzden yine de gönderiyorum, Retina'da çok daha iyi bir cevap olsa bile. Açıklama:

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

Sınırı doldurun. Bu labirentin dışından dolaşmaktan kaçınır (örneğin, test durumu 7 için).

I
#

Girişte alfabetik olmayan bir işaretleyici yerleştirin.

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

Çıkıştan girişten sel dolgusu. Her adımda, gidilecek en iyi yönü belirtmek için bir mektup kullanın (wasd - bu oyuncular için tanıdık gelebilir; hjkl'yi de düşünmüştüm ama çok kafa karıştırıcı buldum). Ek olarak, aynı yönü tekrarlamayı tercih edin; bu, dikey olarak bitişik iki hücre arasında sola / sağa gitmeyi önler.

^
w¶

İlk adımın azaldığını varsayın.

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

Ancak girişin solunda veya sağında bir harf varsa, ilk adımı değiştirin.

{`^(.*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 

İşaretçiyi, işaretleyicinin hareket ettiği kareden bir sonraki hareketin yönünü okuyarak, son hareket yönünde hareket ettirin ve bunu yön listesine ekleyin. Bu U, ulaşılana kadar tekrar eder .

s`U.*

Artık gerekmediğinden, yönergelerden sonraki her şeyi silin.

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

Orijinal ızgara 3 × 2 düzendedir. Yatay olarak zig-zag yaparsak dikey hareket ederken taşma dolgusu hareketi optimize eder ve yalnızca 3n-1 karakterleri yatay olarak hareket ettirir; Dikey olarak sadece 2'ye bölüyoruz.

Ayrıca, gerçek bir kare ızgara çözümünü de araştırdım; yani karakter matrisinin isteğe bağlı kenarlıklı 3 × 2 bir düzen olmaktan ziyade kare olduğu. Muhtemelen soruya uymamakla birlikte, aktarma yeteneği bayt sayısını 350'ye düşürdü: Çevrimiçi deneyin!


Güzel cevap, +1! TIO bağlantınızda -hem giriş hem de çıkış karakterlerinin ikisine iki eklediğinizi görüyorum . Zorluk labirentten geçmekle ilgili olduğu için sanırım sorun değil, ama merak ediyorum: Bu duvarları Ive altına yerleştirmedeki sorunlar nelerdi U? Ayrıca, test durumda 7 için bu işleri doğrulamak olabilir Ive Uüst yerine yanlarında? TIO, 60 saniyelik sınırı aşıyor, bu yüzden kendim test edemiyorum. Her ne kadar ilk önce varsayılan olarak aşağıya inmeye çalıştığınızın açıklamasını okumanıza rağmen, bunun iyi çalışması gerektiğini düşünüyorum.
Kevin Cruijssen,

@KevinCruijssen "İkincil" cevabı, test senaryosu 7 için işe yarıyor ancak fazladan karakter gerektiriyor: Çevrimiçi deneyin! devam etti ...
Neil

@KevinCruijssen "Ana" cevabında, en üst satırdaki çıkışla baş edemediği bir hata vardı. Aynı zamanda, "ikincil" cevabına benzer bir hatayı vardır, böylece mümkünse labirentin dışından dolaşmayı tercih eder. (Ayrıca, 60 saniyelik sınırın yakınına da
Neil

Aslında her iki cevabı da sınırda doldurarak düzeltebilirim. Bunu daha sonra zamanım olduğunda yapacağım.
Neil
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.