どうすれば人生でもっと多くのKlotskiを獲得できますか?


15

私はタイルパズルをスライドさせるのが大好きですが、最近は時間がありませんでした。したがって、スライディングタイルパズル、特にKlotskiパズルを修正するプログラムが必要です。

入力は次の形式になります。

#######
#001gg#
##.222#
.######

ここで、#は壁、.オープンエリア、g目標、隣接する数字は異なるブロックを表します。あなたはそれを仮定することができます:

  1. 10ブロックを超えることはありません
  2. 同じ番号のブロックは2つありません
  3. すべてのブロックは壁で囲まれます
  4. グリッドは長方形です
  5. 0ブロックは、目標の正方形のすべてをカバーするために十分な大きさです。
  6. 有効な解決策があります

0すべてのゴールスクエアをカバーするようにブロックを配置する一連の動きを返す必要があります。ブロックは壁や他のブロックを通過できません。上記のパズルの場合、適切なシーケンスは

2L,1R,1R,1D,0R,0R,0R

2ブロックを左に1マス、1ブロックを右に2マス(ゴールの上)、次に1マス下に移動し、0ブロックを右に3マス移動することを表します。

実際には、上記の問題に対して機能するいくつかのシーケンスがあり、それらのいずれかを生成することは許容されます。ソリューションは最適でなければなりません。つまり、できるだけ少ないステップでパズルを解くシーケンスを作成する必要があります。

シーケンスは上記のように出力する必要がありますが、カンマ、改行、またはスペースで区切ることができます。末尾にコンマまたは空白があるかどうかは気にしません。妥当な時間で出力を生成する必要があります(以下のパズルでは最大120秒)。

パズル1:

..####..
..#00#..
###00###
#......#
#.1122.#
##3124##
.#3344#.
.##55##.
..#gg#..
..####..

パズル2:

######
#1002#
#1002#
#3445#
#3675#
#8gg9#
######

パズル3:

.####.
##1g##
#22g3#
#4255#
#4.56#
#.006#
#7008#
######

パズル4:

.####.
##00##
#.00g#
#.0.1#
#..g2#
######

これはコードゴルフなので、最短のソリューション(バイト単位)が勝ちです!


ちょっと考えてみました-これを読んでいると、少し混乱するようなものを見つけました。「隠されている」という目標は時々見にくいものでした。あなたが持っている例では、それらは妥当な精度で「推測」できますが、ブロックが目標を完全にカバーしている場合、目標全体を明確に示す方法が必要です。場合:ブロックの文字、そのスポットがゴールにあるときの大文字?。スペース用、*目標用?他のすべて同じですか?それはより明確ですか?
同上

@Dittoは、ブロックがゴールスクエアで始まるケースはありません。最後の例には、2つの接続されていないゴールスクエアがあります。
ネイサンメリル

すべての入力パズルに解決策があると仮定できますか?
-orlp

@orlpはい、問題ステートメントに追加します。
ネイサンメリル

@NathanMerrill物事が正しく行われていることを確認するために、パズル1-4に最適な量の動きを追加できますか?
orlp

回答:


5

Python、1761

この質問で燃え尽きてしまったので、ゴルフに行くことができませんでした。いずれにせよ、現時点では、制限時間内にすべてを解決する唯一のソリューションです(最長、#3、27秒かかります)。

pieces = {}
taken = set()
goals = set()

y = 0
while True:
    try:
        for x, c in enumerate(input()):
            if c == ".": continue
            if c == "g":
                goals.add((x, y))
            else:
                if c in "0123456789":
                    if c not in pieces: pieces[c] = set()
                    pieces[c].add((x, y))
                taken.add((x, y))

        y += 1

    except: break

def translate_comp(coords):
    o = min(sorted(coords))
    return set((c[0] - o[0], c[1] - o[1]) for c in coords)

similar = {}
for piece in pieces:
    k = tuple(translate_comp(pieces[piece]))
    if k not in similar: similar[k] = []
    similar[k].append(piece)


seen = set()
states = [(pieces, taken, ())]
while states:
    state = states.pop(0)
    if not goals - state[0]["0"]:
        names = {
            (-1, 0): "L",
            (1, 0): "R",
            (0, 1): "D",
            (0, -1): "U",
        }

        print(len(state[2]))
        print(" ".join(piece + names[d] for d, piece in state[2]))
        break

    for piece in pieces:
        for d in ((-1, 0), (1, 0), (0, 1), (0, -1)):
            new_pieces = state[0].copy()
            new_pieces[piece] = {(c[0] + d[0], c[1] + d[1]) for c in state[0][piece]}
            new_taken = state[1] - state[0][piece]

            # Collision
            if new_pieces[piece] & new_taken:
                continue

            gist = tuple(frozenset().union(*(new_pieces[piece] for piece in similar_set))
                         for similar_set in similar.values())

            if gist in seen:
                continue

            seen.add(gist)
            new_taken |= new_pieces[piece]
            states.append((new_pieces, new_taken, state[2] + ((d, piece),)))

すごい!確かに最速の言語ではない
-edc65

それは全く異なるアプローチのようであり、私はPythonをよく理解していません。しかし、私は同じ形の作品を見つけるというアイデアが好きです。これにより、コード内の訪問位置のスペースを大幅に削減できます。ソリューションのために借りてもいいですか?
-edc65

@ edc65もちろん。ただし、これは別のアプローチではありません。幅優先検索も行います。同じボードを2回調べません(同じ形状のブロックは同じボードとカウントされます)。
-orlp

4

JavaScript(ES6)、446 388

幅優先検索なので、最初に見つかったソリューションは最短です。
それでもそれは良い解決策だと思いますが、それでは十分ではありません。数百万の位置(ランタイム数分)をチェックした後でも、例2と3の解決策が見つかりませんでした。

ES6の修正バージョン編集して、javascriptの実行時間制限を克服します。パズル3は7分、145ステップで解決しました。パズル2を10分で解決、116ステップ

同じ形状の2つのブロックが等しい(特別なブロック '0'を除く)と考える@orlpのアイデアを使用して、2つの大きな高速化を編集します。これにより、BSF中に訪問した位置のスペースが削減されます。たとえば、パズル2では、ブロック1、2、3、または5が交換された位置はすべて同じです。

タイミング:最長はパズル3、ラップトップで20秒以内。

Firefoxを使用して、新しいJsFiddleを試してテストします。

F=g=>(o=>{
for(u=[i=s=''],v={},h=[],b={},k={'.':-1},l={},
g=[...g].map((c,p)=>c>'f'?(h.push(p),'.'):c<'0'?c:
l[k[c]?k[c]+=','+(p-b[c]):k[b[c]=p,c]=~(c>0),k[c]]=c),
b=Object.keys(b),b.map(c=>k[c]=l[k[c]]);
h.some(p=>g[p]!='0');[s,g]=u[++i])
b.map(b=>[-1,1,o,-o].map((d,i)=>
g.every((c,p)=>c!=b?1:(c=g[p+d])!=b&c!='.'?0:m[g[p-d]!=b?m[p]='.':1,p+d]=b,m=g.slice(0))
&&!v[q=m.map(c=>k[c]||'')+'']?v[q]=u.push([s+b+'LRUD'[i]+' ',m]):0))
})(o=~g.search(/\n/))||s

時代遅れ

EcmaScript 6(FireFox)JSFiddle

EcmaScript 5(Chrome)JSFiddle

#######
#001gg#
##.222#
.######
T(ms) 10,Len7
1R 0R 1R 0R 2L 1D 0R

パズル1

..####..
..#00#..
###00###
#......#
#.1122.#
##3124##
.#3344#.
.##55##.
..#gg#..
..####..

T(ms) 8030,Len70
1U 2U 3U 4U 5U 5L 4D 2R 1R 3U 5U 4L 4D 5R 5R 3D 1L 3D 1L 5L 5U 5U 2D 5R 
1R 5R 1R 1D 0D 4D 1D 0D 0L 0L 1U 1U 1U 1U 2L 2L 2U 5D 2R 0R 3R 3R 0D 0D
2L 2L 2L 5U 0U 3U 3U 4U 4U 4R 0D 3L 3U 5D 5L 5L 5L 4U 4U 0R 0D 0D

パズル2

######
#1002#
#1002#
#3445#
#3675#
#8gg9#
######

T(ms) 646485, Checked 10566733, Len 116
8R 3D 4L 7U 9L 5D 7R 4R 3U 8L 9L 5L 7D 4R 6U 9U 8R 3D 6L 4L 2D 7D 2D 0R
1R 6U 6U 3U 3U 9L 8L 5L 7L 7U 2D 4R 5U 8R 8R 5D 1D 6R 3U 9U 5L 1D 1D 9R
9U 4L 4L 2U 8R 7D 2L 8U 7R 2D 4R 3D 6L 9U 4R 1U 1U 2L 8L 8D 4D 0D 9R 6R
3U 9R 6R 1U 5U 2U 8L 8L 7L 7L 4D 0D 6D 6R 1R 2U 2U 0L 6D 9D 6D 9D 1R 2R
3R 5U 5U 0L 9L 6U 4U 7R 8R 7R 8R 0D 9L 9L 6L 6L 4U 8U 8R 0R

パズル3

.####.
##1g##
#22g3#
#4255#
#4.56#
#.006#
#7008#
######

T(ms) 433049, Checked 7165203, Len 145
3L 3U 5U 6U 0U 7U 8L 8L 8L 0D 0R 7R 7U 7R 4D 2D 8R 4D 2D 5L 5L 3D 1R 3R
1D 1D 5R 5U 3L 6U 2U 4U 7R 1D 8L 0L 7D 1R 2R 4U 4U 8U 8U 0L 2D 3D 3L 6L  
1U 7D 2R 0R 8D 4D 8D 4D 3L 3U 4U 4R 8U 8U 0L 7L 2D 1D 6R 4R 4U 1L 1L 1U
2U 2L 6D 6D 4R 1R 1U 2U 2L 6L 6U 4D 1R 6U 7U 7U 0R 8D 0R 2D 3D 8D 2D 3D
7L 6D 5D 5L 1L 1U 1L 6U 4U 7R 7R 6D 6L 4L 4U 7U 7U 0U 0U 2R 3D 2R 3R 3D 
6D 5D 1D 1L 4L 7L 7U 0U 2U 3R 6D 5D 4D 7L 3R 6R 8R 5D 4D 7D 4L 7D 7D 0L 
0U

パズル4

.####.
##00##
#.00g#
#.0.1#
#..g2#
######

T(ms) 25,Len6
1L 1D 1L 1L 0D 0R

ソリューション(および他のソリューション)を検証するために、投稿した各問題について取得した移動数を投稿できますか?
ネイサンメリル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.