Life is a Maze:歩くことを学ぶ前に間違った道をたどる


30

入力:

キャラクターを含む迷路:

  • -- (水平壁);
  • | (垂直壁);
  • + (接続);
  • (歩行スペース);
  • I (エントランス);
  • U (出口)。

つまり、入力は次のようになります。

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

出力:

最も効率的なあなたが(迷路)迷路の入口から出口まで取得するために歩いすべきパスは、左、右、上下(すなわちを示す文字で示され>; <; ^; v)。

チャレンジルール:

  • 任意の妥当な形式で入力を取得できます。文字列配列、改行を含む単一の文字列、2D文字配列などはすべて、可能な入力形式です。
  • 出力は、任意の4つの異なる文字で構成できます。すなわち><^v; →←↑↓; ⇒⇐⇑⇓; RLUD; 0123; ABCD; 等。)。
  • 必要に応じて、出力にスペースまたは末尾の改行を追加できます。これはオプションです。
  • ステップは+、文字ごとではなく、正方形ごとにカウントされます(正方形については4つの記号を参照)。
  • 迷路のサイズは5x5〜15x15で、常に正方形です(したがって、5x10迷路のテストケースはありません)。
  • すべての迷路には、開始から終了までの1つ以上の有効なパスがあり、常に最短を出力すると想定できます(テストケース4および5を参照)。
  • 同じ長さのパスが複数ある場合は、出力するパスを選択できます(テストケース6を参照)。
  • 迷路の境界の外を「歩く」ことはできません(テストケース7および8を参照)。

一般的なルール:

  • これはであるため、バイト単位の最短回答が優先されます。
    コードゴルフ言語では、コードゴルフ以外の言語で回答を投稿しないようにしないでください。「任意の」プログラミング言語の可能な限り短い答えを考えてみてください。
  • 回答には標準の規則が適用されるため、STDIN / STDOUT、適切なパラメーターを持つ関数/メソッド、完全なプログラムを使用できます。あなたの電話。
  • デフォルトの抜け穴は禁止されています。
  • 可能であれば、コードのテストへのリンクを追加してください。
  • また、必要に応じて説明を追加してください。

テストケース:

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<

このツールを使用し生成された迷路(および場合によってはわずかに変更)。


10
3番目のテストケースの短いソリューションを見つけました!v<<<<<<^^^^^(常にボックスの外側を考える)
レオ

2
十分な時間とメモリがあれば、コードが最短のソリューションをもたらすことを証明できる場合、競合しますか?本当に長い実行時間(宇宙のファッションの終わり)の場合でも?
Yytsi

1
@JackBatesそれは冗談です。彼は文字通り箱の周りを出口まで歩きます:D
Yytsi

1
最初のテストケースは間違っていると思います>v>>>vv<v>>v>v>>vvv>>>
smls

1
@KevinCruijssenたとえば、迷路内の空のボックスの量までの「v ^ <>」の各組み合わせをテストするソリューション。正しいソリューションはそこにありますが、計算には天文学的な時間がかかります。
Yytsi

回答:


7

網膜338の 281 275 273 261バイト

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

オンラインでお試しください!


ノート

  • 重要な空白のため、この回答とTIOリンクの両方で、すべてのスペース(0x20)がinterpunct(·)に置き換えられます。スペースが復元されると、プログラムは正常に動作します。
  • 用途AvKrアップのためには、下、右、それぞれ左、と。これらはを除く任意の文字に置き換えることができますI
  • 15×15テストケースのTIOで約40秒かかります。我慢して。パスが出口に到達したら、最短パスを見つけるために部品を作り直しました。時間がかかりました。
  • 66セル以上の幅の迷路で完全に壊れる可能性がありますが、任意の高さの迷路を処理できます。任意の幅の修正には+1バイトが必要です。

説明

プログラムは3つのフェーズで構成されます。

  • 建設段階(以下に詳述)での作業が容易であり、コンパクトな形式に迷路に変換します。
  • フィル相実際に塗りつぶしアルゴリズムを使用して迷路を解決します。
  • 戻り相出口で最短パスを返します。

フォーマット

元の迷路形式は非常に扱いにくいため、プログラムの最初の部分は別の形式に変換します。

細胞

元の形式では、各セルは2×3領域として表されます。

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

右側の列には情報が含まれていないため、プログラムはセルを2x2領域として識別+し、左上にa を付けます。

これにより、3種類のセルが残ります。

  • I細胞:迷路の内側に適切にある細胞。
  • R細胞:迷路の右側にある細胞。これらは、入口または出口を収容するために使用されるパディングによって作成されます。たとえばU、テストケース1の出口はRセルにあります。
  • B細胞:迷路の下にある細胞。Rセルと同様に、これらはパディングによって作成されます。

新しい形式では、セルは可変長文字列として表されます。

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

左と上の壁が元の形式からコピーされます。列番号はセルの水平位置に基づいており、位置合わせに使用されます(セルを互いの上または下に直接識別する)。パスは、そのセルに到達するための最短パスを保存するために、充填フェーズで使用されるアルファベット文字列です。パスと出口マーカーについてさらに説明します。

ハーフセル

迷路のほとんどはセルですが、セルではない迷路の領域があります。

  • Rハーフセル:右のパディングがない場合+、右の壁に沿ったsは最後の列にあるためセルを形成しません。
  • Lハーフセル:左側にパディングがある場合、左側にセルがないため、そこにセルを形成できません+。たとえばI、テストケース1の入り口はLハーフセルにあります。

技術的には、迷路の上にTハーフセル(上部パディングがある場合)とBハーフセル(下部パディングがない場合は下部壁に沿って)がありますが、新しい形式では表されません。

ハーフセルの一番上の行は、同じ行にフルセルを構築する一環として削除されるため、ハーフセルは次のような新しい形式で表されます。

<wall/exit marker>? <path>

R Half-cellsはちょうど|です。LハーフセルにはI、パスと同じように、出口マーカーと空のパス、または空の壁があります。

入り口と出口

入り口が迷路の左、右、または下にある場合、入り口マーカーIは自然に(ハーフ)セルにパスとして含まれます。これは最終パスを返すときに削除できます。

入口が迷路の上にある場合、建設中にTハーフセルが削除されるため、建設段階で最初の(下向きの)ステップが実行されます。これにより、フルセルに実行可能なパスが保持されます。上部の壁はその後閉じられます。

出口が迷路の左、右、または下にある場合、U当然(半)セルに含​​まれます。パスと間違われることを避けるため、の&代わりに非英数字の出口マーカーが使用されますU。出口マーカーは、セルまたはハーフセルに埋め込まれます(上記で指定)。

出口が迷路の上にある場合、セルの一番上の行の上に行くことができる唯一の穴になります(入口の穴は存在する場合は既に閉じられているため)。その穴に到達するすべての経路は、上向きのステップを踏むことで迷路を出ることができます。

最後に、入口または出口を含むBセルは、Bセルに沿って歩いて迷路を「解決」するのを防ぐために、左壁を閉じる必要があります。RセルまたはLハーフセルの入り口と出口は、フラッドフィルアルゴリズムがそれらへの/からの垂直方向の移動を許可しないため、さらに処理する必要はありません。

例として、最初のテストケース

·+--+--+--+--+--+--+--+--+--+--+·
I···············|·····|········|·
·+··+--+--+--+··+··+··+··+--+··+·
·|···········|·····|··|··|·····|·
·+--+--+--+··+--+--+··+··+··+--+·
·|···········|·····|·····|·····|·
·+··+--+--+··+··+--+--+··+--+··+·
·|·····|·····|·····|·····|·····|·
·+--+··+··+--+--+··+--+--+··+··+·
·|·····|········|········|··|··|·
·+··+--+--+--+··+--+--+··+··+··+·
·|·····|·····|·····|········|··|·
·+--+··+··+--+--+··+--+--+--+--+·
·|··|··|·················|·····|·
·+··+··+--+--+--+··+--+··+··+··+·
·|·····|········|··|··|··|··|··|·
·+--+--+··+··+--+··+··+··+--+··+·
·|········|·····|·····|··|·····|·
·+··+--+--+--+··+··+··+··+··+--+·
·|···········|·····|··|·········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&

新しい形式で。ここで他の迷路を変換できます


建設段階

構築フェーズは、プログラムの最初の13行を構成します。

¶U
¶&

Lハーフセルの出口を出口マーカーに変換します

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

Bセルの入口と出口の左側に壁を追加します

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

入り口が迷路の上にある場合、最初の一歩を踏み出します

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

実際の変換を実行します

·v
-v

上部入口の穴を閉じます

G`1

の行のみを保持し1ます。迷路の幅は少なくとも5セルで、列番号は3ずつ増加するため、新しい形式のセルを含む行には10〜19の列番号が含まれている必要があります。

·U
&

RセルまたはBセルの出口を出口マーカーに変換します


充填段階

充填フェーズは、プログラムの次の8行を構成します。フラッドフィルアルゴリズムを使用して、入り口からそこに到達する最短パスですべてのセルを埋めます。

{`

迷路全体を埋めるために、塗りフェーズ全体をループに入れます。

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

左に移動できる各セルはそうします。次の場合、セルは左に移動できます

  1. 空ではないパスがあります
  2. 空の左壁があります。そして
  3. 左のセルまたはLハーフセルに空のパスがある
(\w+)·\d+.\B
$&$1r

次に、右に移動できる各セルがそうします。セルは次の場合に正しく移動できます

  1. 空ではないパスがあります
  2. その右側のセルには空の左壁があります。そして
  3. 右側のセルには空のパスがあります
(?<=\D\2.(\w+).+?¶.*\D(\d+)[·&])\B
$1v

次に、下に移動できる各セルがそうします。次の場合、セルは下に移動できます。

  1. 空ではないパスがあります
  2. 右側に少なくとも1つのセルまたは半セルがあります(つまり、Rセルではありません)
  3. その下のセル(つまり、同じ列番号を持つ次の行のセル)には、空の上部壁があるか、出口マーカーがあります。そして
  4. その下のセルには空のパスがあります

Lハーフセルは列番号がないため下に移動できないことに注意してください。

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

次に、上に移動できる各セルがそうします。セルは次の場合に上に移動できます

  1. 空ではないパスがあります
  2. 空の上部壁があります
  3. その上のセルには、その右側に少なくとも1つのセルまたはハーフセルがあります。そして
  4. 上のセルには空のパスがあります

返品フェーズ

リターンフェーズは、プログラムの最後の5行を構成します。このフェーズでは、出口セルに入力されたパスを検索して返します。

出口でのパスのパターンは、出口の場所によって異なります。

  1. 出口がLハーフセルにある場合、そのハーフセルは & <path>
  2. 出口がRセルまたはBセルにある場合、そのセルは <left wall> <column number> & <path>
  3. 出口がTハーフセルにある場合、上記のように、出口につながるIセル<left wall> <column number> · <path>は最上行にあります。
^.+\d·(\w+)
&$1A

空の上部壁と空ではないパスを持つ一番上の行のセルを検索します。これは、最後のステップと終了マーカーを追加することにより、最後のケースを処理します。

M!`&\w+

出口マーカーに続く空でないパスに一致して返します。

I|&

出口マーカーとIパスのプレフィックスを削除します。


なぜAvKr?彼らは意味を持っていますか/彼らはあなたの母国語で上、下、左、右の略語ですか、またはあなたがそれらの特定の文字を選んだ別の理由がありますか?
ケビンCruijssen

@KevinCruijssen単に英数字を使用する必要がありAvKr、alphanumの矢印に最も近いからです。
トワイナイト

12

Perl 6の259の 295バイト

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

使い方

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

これにより、各セルの内側が2x1のスペース文字ではなく1x1になるように迷路が絞られます。

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

これは、再帰的なパス検索機能です。現在の座標c=(y,x)、既に訪れた座標のリストv、およびpこれまでに取られたパス(矢印文字のリストとして)の3つのパラメーターを取ります。

現在の座標の文字がスペースの場合、4つの隣の文字に再帰します。
現在の座標のキャラクターがaの場合、I「エッジに沿って」いない2つの隣人に再帰して、ソリューションを迷路を通過させ、迷路を通過させません。
現在の座標の文字がの場合、累積されたパス文字列をU呼び出しtakeます。

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

再帰関数は、最初にI、正規表現を使用して見つかったletterの座標で呼び出されます。

gatherキーワードを収集しているすべての値をtake関数の内部で呼ばれていた、つまり迷路を介してすべての有効な非周期的なパス。

最短パスが選択され、1つのセルから次のセルに移動するために2つの同一の移動が必要であるという事実を考慮して、1つおきの矢印がドロップされ、残りの矢印が連結されてラムダから返される文字列が形成されます。


最初に私のチャレンジを完了する最初の素晴らしい仕事です!:)実際の移動/カウントを容易にするために、2つのスペースを1つに変更した方法。私から+1。とにかく、いくつかのコメントの後、2つの新しいテストケースが追加されました。これらの動作をソリューションでも検証できますか?(また、Perl 6にはリンクを追加できるTIOまたはその他のオンラインコンパイラがありますか?)
ケビンクルーイッセン

@KevinCruijssen:新しいテストケースの迷路を回りました。:(私は今、コードを固定tio.runはPerl 6のサポートしていますが、何らかの理由で、これは多分それはあまりにも古いPerl 6のバージョンがいる...そこには動作しません。?
SMLS

コードを修正する素晴らしい仕事。すでに答えを投稿した後、迷路を通過する必要があるというルールを指定して申し訳ありませんが、それを非常に迅速に修正するためにシャポー。そして、TIOバージョンに関しては、私にはわかりません。そうでもない私の専門知識...
ケビンCruijssen

4か月前にあなたが私の挑戦に最初に答えたので、私はあなたに報奨金を与えました。:)そしてAcceptは、少し短いRetina回答用です。
ケビンCruijssen

5

Python 2:302バイト

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)

入力をすべて同じ長さの文字列の配列として受け取ります。0右、1下、2左、上に印刷3します。

説明

私は他の答えとは異なるアプローチを取りました。一般的なアイデア:まっすぐ進むこととボードを90度回転することの間の最短経路を見つけることによって再帰的に検索します。

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)

オンラインでお試しください!


3
PPCGへようこそ!これは素晴らしい最初の答えであり、あなたが最初としてかなり厳しい挑戦をすることに決めたことに感銘を受けました。また、壁Iが迷路の外に出るのを防ぐために壁をどのように配置するかをスマートにします。滞在を楽しんで、私から+1してください。:)
ケビンクルイッセン

2

JavaScript(ES6)、356バイト

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

入力を文字の2D配列として受け取ります。各行は、開始点/終了点がどこであっても、1つのスペースで左詰めされ、末尾のスペースがないようにする必要があります。

迷路をつぶして各セルを1x1にし、出力から繰り返し矢印を削除するというsmlsのアイデアを使用します。

非ゴルフと説明

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
)

テストスニペット


1

網膜、416バイト

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

オンラインでお試しください!この質問が最初に投稿されたときに見た場合、これはおそらく私が与えた回答であるため、Retinaにははるかに良い回答がありますが、とにかくそれを投稿しています。説明:

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

境界線を埋めます。これにより、迷路の外側を歩き回る必要がなくなります(テストケース7など)。

I
#

入り口にアルファベット以外のマーカーを配置します。

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

出口から入口までの洪水。各ステップで、行くべき最適な方向を示すために文字を使用します(これはゲーマーにはおなじみかもしれません。hjklも検討していましたが、あまりにも混乱を招きました)。さらに、同じ方向を繰り返すことを好みます。これにより、垂直方向に隣接する2つのセル間で左右に移動することを回避できます。

^
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 

マーカーを最後の移動の方向に移動し、マーカーの移動先の正方形から次の移動の方向を読み取り、それを方向のリストに追加します。にU達するまでこれを繰り返します。

s`U.*

不要になったため、指示の後にすべてを削除します。

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

元のグリッドは3×2レイアウトです。水平方向にジグザグすると垂直方向に移動しますが、塗りつぶしは移動を最適化し、3n-1文字だけ水平方向に移動するため、3で割る場合は切り上げる必要があります。垂直に2で割るだけです。

また、真の正方形グリッドソリューション、つまり、オプションの境界線を使用した3×2レイアウトではなく、文字マトリックス自体が正方形であるソリューションについても調査しました。おそらく質問には適合していませんが、転置する機能によりバイト数が350に削減されました。オンラインで試してみてください。


いい答え、+ 1!-入り口と出口の両方の文字の周りに2つ追加したTIOリンクが表示されます。課題は、迷路を行くことについて主にあるので、私はそれの罰金を推測するが、私は好奇心:何を上/下、これらの壁を置いていなかったときの問題はなかったIU?また、テストケース7で、側面ではなく上部Iとを使用Uして、これが機能することを確認できますか?TIOが60秒の制限を超えているため、自分でテストすることはできません。デフォルトで最初にダウンしようとすることの説明を読んでいますが、私はそれがうまくいくはずだと思います。
ケビンCruijssen

@KevinCruijssen「セカンダリ」回答はテストケース7で機能しますが、追加の文字が必要です。オンラインで試してみてください。続き
ニール

@KevinCruijssen「メイン」の回答にはバグがあり、それによりトップラインの出口にまったく対処できませんでした。また、「二次」回答と同様のバグがあり、迷路の外側を歩き回ることができます。(また、60秒の制限
ニール

実際、境界線を埋めることで両方の答えを修正できました。後で時間があればそれを行います。
ニール
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.