私の障害物コースはどの程度変化しますか?


21

バックグラウンド

長方形の部屋に箱を置いて、簡単な障害物コースを構築しました。今、私はそれが解決できる本質的に異なる方法の数を数えたいです。そのためのプログラムを書いてほしい。

入力

入力は、文字の空でない長方形の配列です.#。ドット.は空きスペースであり、#障害物です。

パス障害物までは、もちろん右下隅にある左上隅と端で始まり、そして唯一の右またはダウンしました。また、有効なパスは障害物を通過できません。以下に、- +文字を使用したいくつかの例を示します。

Valid path  Invalid path  Invalid path  Invalid path
++........   ++........    +++++.....    ..+.......
.++++++#..   .+.....#..    ....+++#++    ..++...#..
......+#..   .+.++++#..    .......#.+    ...+++.#..
....#.++++   .+++#.++++    ....#....+    ....#+....

2つのパスは、一度に1つずつ移動することで一方を他方に変換できる場合、基本的に1 +中間のパスも有効でなければならないため、障害物の上でパスを曲げることはできません。たとえば、ここの最初の2つのパスは基本的に似ていますが、3番目のパスは2つの障害物の上をくねることができないため、基本的にそれらとは異なります。

++........   +.........   +++++++++.
.+++++.#..   ++.....#..   .......#+.
.....+.#..   .++++++#..   .......#++
....#+++++   ....#.++++   ....#....+

出力

出力は、障害物コースを通る本質的に異なるパスの数です。つまり、すべての有効なパスが本質的に同様のパスのクラスに分割される場合、出力はクラスの数になります。有効なパスがない場合、この番号は0になる場合があります。

ルールとスコアリング

完全なプログラムまたは関数を作成できます。最小のバイトカウントが優先され、標準の抜け穴は許可されません。時間制限はありませんが、提出する前にすべてのテストケースでプログラムを評価する必要があります。

テストケース

....
....
.... => 1

...#
....
...# => 0

#..#
..#.
.... => 0

......
......
..##..
......
...... => 2

......
...#..
......
..#...
#..... => 3

......
..#...
......
....#.
#..... => 4

.......
##.....
....###
...#...
..##.#.
#....#.
..#.... => 0

......#.
..##....
...#....
.......#
....#...
.##...#.
....#...
##...... => 7

.........
.#.#.#.#.
.........
#.#...#.#
.........
.#.#.#.#.
......... => 17

..........
.#........
..........
.....#....
#.........
........#.
......#...
.......... => 10

.........
.#.......
.........
...#.....
.........
.....#...
.........
.......#.
......... => 16

1正しい技術用語は「ホモトピック」です。


1
あなたは「とはどういう意味ですか1を移動する+時に」?これは、本質的に同様のパスは同じ長さでなければならないことを意味しますか?
ピーターテイラー

3
@PeterTaylorすべてのパスは同じ長さです。なぜなら、それらは右下にしか行けないからです。「1つ移動する+」とは、基本的に、パスの1つのコーナーが反対方向のコーナーに反転することを意味します。
ズガーブ

1
@Peter:右または下にしか行けないため、すべてのパスは同じ長さです。
デウソビ

回答:


8

カタツムリ53 49バイト

A^
\.+d!{.l\.+a3(.|~c!~}\.+r!(.u\.+e(.|~},\.,=~d~

一度はt、恐ろしいテレポート命令を使用する必要はありませんでした。その結果、テストケースはイオンを取得する代わりに即座に終了します。

ゴルフをしていない:

A^
r\.+
{
    d\.+
    !{ r\.u \.+ a3 (.|~)}
    r\.+
    !{ d\.l \.+ a3 (.|~)}
},
d\.,
!(dr .)

オプションA^は、左上隅から開始し、一致するすべてのパスをカウントすることを意味します。主なアイデアは、パスの標準条件をチェックすることです。私は正直にそれが機能することを期待していませんでしたが、テストケースを釘付けにしたので....チェックするのは、現在のパス内で最も貪欲なルートが選択されている、つまり可能な限り何度も進むことです、可能な限り何度もダウンなど、障害物を越えることなく。これは、右に1回以上移動した後、1回以上下に移動した後、前の右方向セグメントでもう1回右に移動しても次の正方形(右にある必要があります)に到達できなかったことを確認することによって行われます。同様の条件は、右に移動してから下に移動した後にもチェックされます。


仕事にふさわしい言語について話してください!
チャールズではない

10

Python 2、 170 131 112バイト

def f(C,t=1):i="#".join(C).find("#")+1;return([]<C)*(i<1or(i<t
and f([r[i:]for r in C],t-i))+(i>1)*f(C[1:],i-1))

関数、f障害物コースを行のリストとして取得し、本質的に異なるパスの数を返します。

説明

基本的な概念は次のとおりです。特定の障害物oを選択します。これにより、oと左上隅を囲むボックスに他の障害物がないようにします。

+--+....
|..|....  
+--#<==== o
.....#..
.#......
........

次に、oの東と南の2つのサブコースを検討します。これらのサブコースのいずれかを検討するのは、oが実際にそれらに通じる方向から横断できる場合、つまり、北から東に到達し、西から南に到達する場合です。選択した各サブコースの問題を解決し、結果の合計を返します。これらの数字は、それぞれ左と右からoを横切るときの本質的に異なるパスの数に対応するため、結果として生じる2つのパスのセットは本質的に異なります。開始点とoの間に障害物がないため、開始点とこれらの各領域への入口点の間にパスがあり、同じポイントに至るすべてのこのようなパスは本質的に類似しているため、上記の合計はコース全体の本質的に異なるパスの完全な数です。

                               A
_
........       ...|////      |....
........       ...|////      |....
...#....  -->  ...#////  -->  ....
.#....#.       .#..//#/       ..#.
........       ....////       ....

   |                           |
   v                           v
                  B
........       ___
........       .#....#.
___#....  -->  ........  -->   +
/#////#/       
////////       

障害物コースだけでは必要なすべての情報が伝えられないという事実により、事態はやや複雑になります。たとえば、上の図のコースBを検討してください。単独で考えると、各障害物が北から渡れるかどうかを判断することはできません。場合Bは、入力されたコースだったすべてのパスが左上隅に起動するので、その後、障害物が北から交差されていない可能性があり、しかし、我々は到達することができますので、どちらもBを横断するとき、左障害物のいずれかの側からOを東から、コースを解くときに、この障害を北から横切ることができるかのように扱う必要があります。ただし、適切な障害物については同じことが当てはまりません。障害物はこの方向からは通過できません。

この追加情報は、障害物コースとともに、パスが開始できる最初の行に沿った左からの文字数を指定することで確認します。上の図では、これは各コースの隣の実線として示されています。技術的には、サブコースAの場合のように、パスが開始できる最初の列に沿って対応する文字数も指定する必要がありますが、実際には常に最も高い障害物を選択したため、この情報は不要です。

oの実際の選択は次のとおりです。最後以外の各行の後に障害物が続いている(つまり、#それに付加されている)ふりをして、結果のコースの最初の障害物を読み取り順に選択します。元々障害がなかった行(最後の行以外)の場合、これは事実上それらをスキップすることを意味します(下のパスは上の行に沿った任意の文字で始まることに注意してください)。最終的に、障害物のない単一の行を持つコースになります。このコースには、可能なパスが1つしかありません。


これは私が考えていた解決策です。私はチャンスを得る前に誰かがそれを投稿することを知っていました。
キントピア

6

CJam、85 84 82 81 80 79バイト

qN/:Q,(Qz,(:R_T]2/e~e!{'#Qs@{\(\@>}%s-},{_}{(a\L{@+_@\-_{2$\f.=0fe=2&},}h;}w;],

オンラインでお試しください。または、テストスイート全体を実行します。

このソリューションの効率はおそらく恐ろしいものですが、数秒以内に各テストケースを解決します。

説明

後でコードの完全な内訳を追加する必要がありますが、アルゴリズムの考え方は次のとおりです。

  • グリッドの幅と高さをそれぞれWHとします。
  • W-1コピー0とのH-1コピーの異なる順列としてすべての可能なパスを生成しますW-1(ここで0、水平方向のステップとW-1垂直方向のステップを表します)。グリッドの最初の要素を繰り返し取得し、step読み取り順序でセルをスキップすることで(where stepis 0またはW-1)、これらすべてのパスを調べます。を含むすべてのパスを破棄します#
  • 次に、同様のパスのグループを繰り返し削除します(これは、残りのパスの最初のパスに類似したすべてのパスになります)。同様のパスのチェックは、それらの条件をわずかに緩和することで少し簡単になります。パスがx移動したかどうかをチェックする代わりに、パスが正確に2か所異なるかどうかをチェックします。その場合、これらの2つの場所では、垂直方向と水平方向の移動が入れ替わります。これにより、これらの動きの間のセグメント全体が1セル分だけ斜めにシフトします。ただし、両方のパスが有効な場合、パスの一部を1セルだけ斜めにシフトしても障害物を越えることはできないため、それらは類似しています。推移的閉包を見つける必要があるので、次のグループに進む前に、同様のパスがなくなるまでそれを続けます。
  • 最後に、見つけたグループをカウントします。グループはスタックの一番下に残しました。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.