我如何在生活中获得更多的Klotski?


15

我真的很喜欢滑动拼图,但是最近,我没有时间去做。因此,我需要一个程序来解决滑动砖块难题,特别是Klotski难题。

您的输入将采用以下格式:

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

其中#代表墙壁,.代表开放区域,g代表目标,相邻数字代表不同的方块。您可以假设:

  1. 不会超过10个街区
  2. 不会有两个号码相同的方块
  3. 所有街区将被围墙包围
  4. 网格是矩形
  5. 0块是大到足以覆盖所有的目标方格。
  6. 有一个有效的解决方案

您需要返回一系列移动步骤,以放置0方块,使其覆盖所有目标方格。方块不能穿过墙壁或其他方块。对于上述难题,适当的顺序是

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

while代表将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绝不会在目标方格开始出现障碍。最后一个示例仅具有两个未连接的目标正方形。
内森·美林

我们可以假设每个输入难题都有解决方案吗?
orlp

@orlp是的,我将其添加到问题说明中。
弥敦道·美林

@NathanMerrill为确保我们做的正确,您能为难题1-4添加最佳移动量吗?
2015年

Answers:


5

巨蟒,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当然。但是,这不是不同的方法,我也进行了广度优先搜索-我只是不两次浏览同一块板(并且形状相同的块与同一块板交换了计数)。
orlp 2015年

4

JavaScript的(ES6),446 388

广度优先搜索,因此找到的第一个解决方案是最短的。
虽然我仍然认为这是一个很好的解决方案,但还不够好。即使检查了数百万个位置(运行时间为几分钟),我也找不到示例2和3的解决方案。

编辑 ES6 修改版本以克服javascript执行时间限制。拼图3在145分钟的7分钟内解决。谜题2在10分钟内解决了116个步骤

编辑2大加速,使用@orlp的想法,即考虑将任意两个具有相同形状的块相等(不包括特殊的块“ 0”)。这减少了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

为了验证您的解决方案(以及其他解决方案),您可以针对我发布的每个问题发布您获得的举动数量吗?
内森·美林
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.