为我解决这个城堡


39

最近,我一直在玩一个叫做Alcazar的游戏。这是一款棋盘益智游戏,您的目标是从一扇门进入,穿过所有正方形,然后从另一扇门退出。唯一的规则是:

  • 进入一次,离开一次;
  • 穿过所有正方形;
  • 不要多次穿过广场

下图显示了一个Alcazar板的示例,其右侧显示了已解决的难题(当然这是一个简单的难题):

样品拼图

您可以在http://www.theincrediblecompany.com/try-alcazar上找到更多拼图,并在PlayStore下载该游戏(PS:不是广告)。

我的问题是除了一个关卡之外,我几乎完成了游戏。我根本找不到解决方法。因此,我提出的挑战是:创建一个可以解决任何正常的1可解决的2城堡等级的算法。

当然,我不是要任何人来构建图像解释器来读取图像并解决难题(或者是吗?)。因此,我使用方框图字符重新绘制了上述难题。这个难题及其解决方案将是这样的:

╔═══════╗         ╔═══════╗
║▒ ▒ ▒ ▒║         ║┌─┐ ┌─┐║
║     ║ ║         ║│ │ │║│║
╣▒ ▒ ▒║▒╠         ╣│ └─┘║└╠
║ ══╦═╩═╣         ║│══╦═╩═╣
║▒ ▒║▒ ▒║         ║└─┐║┌─┐║
║   ║   ║   ==>   ║  │║│ │║
╣▒ ▒║▒ ▒║         ╣┐ │║│ │║
║ ║ ║   ║         ║│║│║│ │║
╣▒║▒ ▒ ▒║         ╣│║└─┘ │║
║ ║     ║         ║│║    │║
║▒ ▒ ▒ ▒║         ║└─────┘║
╚═══════╝         ╚═══════╝

在上面的面板中,是要填充的单元格。

可以观察到细胞之间存在垂直和水平间隙。这是因为我必须在单元之间插入一个空格以添加墙。这意味着唯一重要的单元格是每个单元格的上方,下方,左侧和右侧。可以删除对角线而不会丢失信息。例如,在下面的面板中,两者都代表着相同的难题:

╔════╩╗         ═ ═ ╩ 
║▒ ▒ ▒║        ║▒ ▒ ▒║
║ ═══ ║           ═   
║▒ ▒ ▒║   ==   ║▒ ▒ ▒║
║     ║               
║▒ ▒ ▒║        ║▒ ▒ ▒║
╚╦════╝         ╦═ ══ 

这对于解决方案也是有效的。也就是说,不需要连接单元:

╔════╩╗        ╔════╩╗        ╔════╩╗
║▒ ▒ ▒║        ║┌───┘║        ║┌ ─ ┘║
║ ═══ ║        ║│═══ ║        ║ ═══ ║
║▒ ▒ ▒║   ==   ║└───┐║   =>   ║└ ─ ┐║
║     ║        ║    │║        ║     ║
║▒ ▒ ▒║        ║┌───┘║        ║┌ ─ ┘║
╚╦════╝        ╚╦════╝        ╚╦════╝

在上面的示例中,两种解决方案的含义相同。

是的,测试用例。他们来了:

难题1

╔════╩╗        ╔════╩╗
║▒ ▒ ▒║        ║┌ ─ ┘║
║ ═══ ║        ║ ═══ ║
║▒ ▒ ▒║   =>   ║└ ─ ┐║
║     ║        ║     ║
║▒ ▒ ▒║        ║┌ ─ ┘║
╚╦════╝        ╚╦════╝

拼图2

╔═════╗        ╔═════╗
║▒ ▒ ▒║        ║┌ ─ ┐║
║   ║ ║        ║   ║ ║
╣▒ ▒║▒║        ╣└ ┐║│║
║ ║ ║ ║   =>   ║ ║ ║ ║
╣▒║▒ ▒╠        ╣┐║│ │╠
║ ║   ║        ║ ║   ║
║▒ ▒ ▒║        ║└ ┘ │║
╚════╦╝        ╚════╦╝

拼图3

╔════╩══╗        ╔════╩══╗
║▒ ▒ ▒ ▒║        ║┌ ┐ └ ┐║
║ ║   ║ ║        ║ ║   ║ ║
╣▒║▒ ▒║▒╠        ╣┘║└ ┐║│╠
║ ╚══ ║ ║        ║ ╚══ ║ ║
║▒ ▒ ▒ ▒╠   =>   ║┌ ─ ┘ │╠
║   ═══ ║        ║   ═══ ║
║▒ ▒ ▒ ▒║        ║│ ┌ ┐ │║
║   ║   ║        ║   ║   ║
║▒ ▒║▒ ▒║        ║└ ┘║└ ┘║
╚═══╩═══╝        ╚═══╩═══╝

难题4

╔═══════╗        ╔═══════╗
║▒ ▒ ▒ ▒║        ║┌ ┐ ┌ ┐║
║     ║ ║        ║     ║ ║
╣▒ ▒ ▒║▒╠        ╣│ └ ┘║└╠
║ ══╦═╩═╣        ║ ══╦═╩═╣
║▒ ▒║▒ ▒║        ║└ ┐║┌ ┐║
║   ║   ║   =>   ║   ║   ║
╣▒ ▒║▒ ▒║        ╣┐ │║│ │║
║ ║ ║   ║        ║ ║ ║   ║
╣▒║▒ ▒ ▒║        ╣│║└ ┘ │║
║ ║     ║        ║ ║     ║
║▒ ▒ ▒ ▒║        ║└ ─ ─ ┘║
╚═══════╝        ╚═══════╝

拼图5

╔══╩══════╗        ╔══╩══════╗
║▒ ▒ ▒ ▒ ▒║        ║┌ ─ ┐ ┌ ┐║
║   ║     ║        ║   ║     ║
║▒ ▒║▒ ▒ ▒╠        ║└ ┐║└ ┘ │╠
║   ╠════ ║        ║   ╠════ ║
║▒ ▒║▒ ▒ ▒║   =>   ║┌ ┘║┌ ─ ┘║
║   ║     ║        ║   ║     ║
║▒ ▒║▒ ▒ ▒╠        ║└ ┐║└ ─ ─╠
║   ╠═════╣        ║   ╠═════╣
║▒ ▒║▒ ▒ ▒║        ║┌ ┘║┌ ─ ┐║
║   ║     ║        ║   ║     ║
║▒ ▒ ▒ ▒ ▒║        ║└ ─ ┘ ┌ ┘║
╚══╦═══╦══╝        ╚══╦═══╦══╝

拼图6

╔═══════════╗        ╔═══════════╗
║▒ ▒ ▒ ▒ ▒ ▒║        ║┌ ┐ ┌ ┐ ┌ ┐║
║           ║        ║           ║
║▒ ▒ ▒ ▒ ▒ ▒║        ║│ └ ┘ └ ┘ │║
║       ═══ ║        ║       ═══ ║
║▒ ▒ ▒ ▒ ▒ ▒║        ║└ ┐ ┌ ─ ─ ┘║
║     ═══   ║        ║     ═══   ║
╣▒ ▒ ▒ ▒ ▒ ▒╠   =>   ╣┐ │ │ ┌ ┐ ┌╠
║           ║        ║           ║
║▒ ▒ ▒ ▒ ▒ ▒║        ║│ │ │ │ │ │║
║   ║   ║   ║        ║   ║   ║   ║
║▒ ▒║▒ ▒║▒ ▒║        ║│ │║│ │║│ │║
║   ║   ║   ║        ║   ║   ║   ║
║▒ ▒ ▒ ▒ ▒ ▒║        ║└ ┘ └ ┘ └ ┘║
╚═══════════╝        ╚═══════════╝

拼图7

╔════╩════════╦╩╗        ╔════╩════════╦╩╗
║▒ ▒ ▒ ▒ ▒ ▒ ▒║▒║        ║┌ ─ ─ ─ ─ ─ ┐║│║
║ ║       ║   ║ ║        ║ ║       ║   ║ ║
║▒║▒ ▒ ▒ ▒║▒ ▒ ▒║        ║│║┌ ─ ─ ┐║┌ ┘ │║
║ ║ ║ ═══ ║     ║        ║ ║ ║ ═══ ║     ║
║▒ ▒║▒ ▒ ▒ ▒ ▒ ▒╠        ║│ │║┌ ─ ┘ └ ┐ │╠
║   ║           ║        ║   ║           ║
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║        ║│ │ └ ┐ ┌ ┐ └ ┘║
║     ║ ║     ══╣        ║     ║ ║     ══╣
║▒ ▒ ▒║▒║▒ ▒ ▒ ▒║        ║│ └ ┐║│║│ └ ─ ┐║
║     ║ ║       ║        ║     ║ ║       ║
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║        ║│ ┌ ┘ │ └ ┐ ┌ ┘║
║           ║ ══╣   =>   ║           ║ ══╣
║▒ ▒ ▒ ▒ ▒ ▒║▒ ▒║        ║└ ┘ ┌ ┘ ┌ ┘║└ ┐║
╠══       ║ ╚══ ║        ╠══       ║ ╚══ ║
║▒ ▒ ▒ ▒ ▒║▒ ▒ ▒║        ║┌ ┐ └ ┐ │║┌ ─ ┘║
║     ║ ║ ║     ║        ║     ║ ║ ║     ║
║▒ ▒ ▒║▒║▒ ▒ ▒ ▒║        ║│ └ ┐║│║│ └ ─ ┐║
║ ║   ║ ║ ╔══   ║        ║ ║   ║ ║ ╔══   ║
║▒║▒ ▒ ▒ ▒║▒ ▒ ▒║        ║│║┌ ┘ │ │║┌ ┐ │║
║ ║     ║ ║     ║        ║ ║     ║ ║     ║
║▒ ▒ ▒ ▒║▒ ▒ ▒ ▒║        ║│ └ ─ ┘║└ ┘ │ │║
║       ╚══     ║        ║       ╚══     ║
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║        ║└ ─ ─ ─ ─ ─ ┘ │║
╚════╦═╦═╦═════╦╝        ╚════╦═╦═╦═════╦╝

难题8(对不起,我真的没有解决办法)

╔══╩╦══╩═══╩═╩═╩═══╩╗
║▒ ▒║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║
║   ║               ║
╣▒ ▒║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║
║   ╚══ ╔══     ╔═══╣
╣▒ ▒ ▒ ▒║▒ ▒ ▒ ▒║▒ ▒╠
║       ║   ╔══ ║   ║
╣▒ ▒ ▒ ▒ ▒ ▒║▒ ▒ ▒ ▒╠
║           ║       ║
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒╠
║           ║       ║
╣▒ ▒ ▒ ▒ ▒ ▒║▒ ▒ ▒ ▒╠
║   ╔═══╗   ╚══     ║
╣▒ ▒║▒ ▒║▒ ▒ ▒ ▒ ▒ ▒║
║   ║   ║           ║
╣▒ ▒║▒ ▒║▒ ▒ ▒ ▒ ▒ ▒╠
║ ══╝   ║       ╔══ ║
║▒ ▒ ▒ ▒║▒ ▒ ▒ ▒║▒ ▒║
║   ══╗ ╚══ ╔══ ║   ║
╣▒ ▒ ▒║▒ ▒ ▒║▒ ▒ ▒ ▒╠
║     ║     ║   ║   ║
╣▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║▒ ▒║
║   ═══   ══╗   ║   ║
╣▒ ▒ ▒ ▒ ▒ ▒║▒ ▒ ▒ ▒╠
╠══ ║       ║   ╔══ ║
║▒ ▒║▒ ▒ ▒ ▒ ▒ ▒║▒ ▒╠
║   ╚══ ║   ║   ║   ║
╣▒ ▒ ▒ ▒║▒ ▒║▒ ▒ ▒ ▒╠
║       ║   ║       ║
║▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒ ▒║
╚══╦═══╦═══╦═╦═╦═╦═╦╝

输入值

只要遵循以下规则,您的代码输入就可以具有任何表示形式:

  1. 它必须是图形输入。因此,例如,无法读取坐标列表。

  2. 水平墙,垂直墙和门必须是不同的,并且必须由可见字符组成(不能有空白字符)。

  3. 可以用空格代替。我只是用一个不同的角色来突出显示它们。

输出量

只要遵循以下规则,输出也可以具有任何表示形式:

  1. 它必须是图形输出。也就是说,可以通过查看路径来查看路径。

  2. 第一条规则意味着路径字符不同。也就是说,至少要有6个路径字符;水平,垂直和转角。

  3. 为了使答案有效,输出必须与输入(显然)在同一块板上,并且所有单元格(在我的表示中为)都已填充。填充单元之间的间隙是可选的。

计分

这是,因此以字节为单位的最短代码获胜。

1有些Alcazar级别具有可选的单元格和隧道。这些将不被考虑。

2有些Alcazar板是不可能的。


2
我的程序找不到谜题8的解决方案。您确定它可以解决吗?也许有错字?
edc65

1
@ edc65同样在这里-为#8无解
NGN

Answers:


5

Python 3中809 728 723 714 693 688 684 663 657 641 639 627 610 571 569字节

编辑:由于@Felipe Nardi Batista而节省了55个字节

不会在60秒内在TIO上运行最后一个测试用例,但是仍然可以正常工作。返回路径的坐标列表。大约400个字节用于从I / O获取数据列表。

A=enumerate
I,J="═║"
B=range
L=len
K=-1
Z=1,0
X=0,1
C=K,0
V=0,K
E=lambda a,b,p:(((a,b)in d)*L(p)==H*h)*p or max([E(q+a,w+b,p+[(q+a,w+b)])for q,w in y[a][b]if~-((q+a,w+b)in p)*-h>w+b>K<q+a<H]+[[]])
x=input().split("\n")
h=L(x[0])//2
H=L(x)//2
y=[[{C,Z,V,X}for i in B(h)]for j in B(H)]
d=[]
exec('d+=[(%s,i)for i,a in A(x[%s][1::2])if I<a]\nfor i,u in A(x[%s:%s:2]):\n d+=[(i,0)]*(J<u[0])+[(i,h-1)]*(J<u[K])\n for j,w in A(u[%s:%s:2]):\n  if"%s"==w:y[i][j]-={%s};y[i+%s][j+%s]-={%s}\n'*2%(0,*X,"",2,K,J,X,*X,V,H-1,K,2,K,1,"",I,Z,*Z,C))
print(max(E(*D,[D])for D in d))

在线尝试!


@HalvardHummel好,很抱歉挑战的公式不好。因此,我提出以下建议。分数应通过将字节数乘以运行时间来计算,因此应奖励运行时间和字节数。你怎么看?
Phelype Oleinik

1
@PhelypeOleinik我认为这不是一个很好的评分系统。将其保留在男女混合高尔夫中是一个更好的解决方案,但是如果您确实在寻找解决方案,我相信可以对其进行修改以提高效率。
caird coinheringaahing

@cairdcoinheringaahing我知道最优雅的解决方案是保持原样。但是,要花费8天甚至12个月才能解决8x12拼图板的算法效率低下,您不觉得吗?从我的角度来看,应该花更少的时间解决问题的算法,即使它更长一些。
Phelype Oleinik

3
@PhelypeOleinik代码的“效率”无关紧要。您已要求我们编写短代码,这是您面临挑战的基础。将程序运行的速度增加到混合中只会使不必要的事情复杂化,并且也可被用于获得可笑的分数。自定义计分系统往往难以奏效。如果您需要短代码,请提出一个代码高尔夫问题。如果您想要快速编码,请提出一个最快的编码问题。尝试将它们混合在一起不是一个好主意。
LyricLy

您的exec(...)字符串中有5行,表示为\n,5 * 2 = 10字节。使用三引号引起来的字符串将添加4个字节(...''...''...),但随后删除5个字节,因为可以使用实际的换行符。总共可以节省一个字节。
乔纳森·弗雷希

5

APL(Dyalog Classic),319字节

iNj←⍳1+n←×/N←⌊2÷⍨⍴a←⎕⋄e←↑⊃,/{(,~'#='∊⍨a[(⍵⌽⍳2)∘+¨2×⍳N+⍵=⍳2])/,2,/[⍵]⊃,[⍵]/n i n}¨⍳2
r←{e g c←⍵⋄d←+/j∘.=∊g⋄e⌿⍨←(≠/c[e])∧2>⌈/d[e]⋄n≡≢g:gj/⍨d=10≡≢e:02>⌊/d+D←+/j∘.=,e:0⋄u←,¯1↑e←e[⍒⌊/D[e];]⋄e↓⍨←¯1⋄0≢r←∇e(g⍪u)(c-(-/c[u])×c=c[⊃u]):r⋄∇e g c}e(0e)j
a[1+2×⍳N]←' ??┌?─┐┬?└│├┘┴┤┼'[2⊥(↑(⊂i),¨¨{⊖∘⍉⍣⍵⊢n⍪¯1↓⌽∘⍉⍣⍵⊢i}¨⍳4)∊↓r⍪⌽r]
a

在线尝试!

Input使用=#F7LJ<>^v.而不是═║╔╗╚╝╣╠╩╦▒为了适合经典字符集

除最后一个通过以外,所有测试用例都在几秒钟内通过。

最后一次测试在我的计算机上花费了47分钟,并且没有解决方案。

当生成的路径在拐角附近使用一扇门时,可能会渲染不正确(就像是小路岔开并穿过了一个额外的假想门),但仍然清晰可辨。


很好!如果我要问的话,您的代码使用什么方法解决?穷举搜索或更优雅的东西?而且,正如我所说,我没有手动解决最后一个难题。它没有明确的分步解决方案,即使是手工解决,也需要猜测才能找到一些答案。这个难题包含在原始游戏中,但可能没有解决方案,因此可能不应该考虑在内。
Phelype Oleinik

1
@PhelypeOleinik是的,这是一个相当简单的详尽搜索。它迅速找到现有解决方案的原因是,它首先尝试了更可能的情况(有vs在图中没有确定的边缘-我的试探法是两个顶点的度数中的最小值,较低者是可能的)。在最后一种情况下,它可怕地执行的原因是无论如何它都会测试所有可能性,并且仅在明显矛盾时才修剪递归。即使对于有界度(≤4邻域)图的特殊情况,似乎也没有好的汉密尔顿路径算法。
ngn

3

JavaScript(ES6),274个字节

输入为多行字符串,每行以换行符终止。门上标有字符“ 2”

输出为多行字符串,其路径以字符“ 1”标记,非常容易辨别。

这是深度优先搜索,尝试所有路径并在遇到问题时回溯。它根本没有效率,但是可以在不到1分钟的时间内解决难题1 .. 6。

z=>(w=z.search`
`+1,t=(w-2)*(z.length/w-1)/4,z=[...z],R=(p,l,q)=>[1,-1,w,-w].some(d=>l<t?z[q=p+d]<1&z[q+d]<1&&(R(q+d,++z[q]+l)||--z[q]):z[p+d]>1&&--z[p+d],++z[p])||--z[p],z.some((c,i)=>-c&&(x=i%w,R(i<w?i+w:x?x>w-3?i-1:i-w:i+1,--z[i])||++z[i]*0))&&z.join``.replace(/0/g,' '))

少打高尔夫球

z => (
  w = z.search`\n`+1, // board width and offset to next row
  t = (w-2)*(z.length/w-1)/4, // total size of board, number of cells that must be filled
  z = [...z], // convert string to array
  d = [1, -1, w, -w], // delta to next position in all directions
  // recursive search
  // given a current position, try to move in all directions
  // if the board is not full, look for an emoty cell
  // if the board is full, look for a door
  R = (p, // current position
       l, // fill level
       q  // parameter used as a local variable
      ) => (
        ++z[p], // mark current position
        // .some will terminate early if the called function returns true
        // in case of return true the recursive function returns all way up leaving the path marked
        // in case of return false we need to unmark path and backtrack
        d.some( d => // for each direction, offset in d
          l < t // check if board is full
          ? z[q=p+d] < 1 & z[q+d] < 1 // not full, try to advance 
            && (++z[q], // mark intermediate cell
                R(q+d, 1+l) // recursive call incrementing fill level
                || --z[q] // if R return false, backtrack: unmark intermediate cell
               )
          : z[p+d] > 1 && --z[p+d]
        ) // full, ok only if I find a door nearby
        || --z[p], // if some returns false, unmark and backtrak
  // look for doors and for each door call R 
  // when R returns true, stop and return the marked board
  // if R returns false for each door, no solution, return false
  z.some((c,i) => 
   -c && // if numeric and != 0
    (x = i%w,
     z[i]=1, // marking starting position (door)
     R(i<w ? i+w : x ? x > w-3 ? i-1 : i-w : i+1, 1)
     || (z[i] = 2, false) // if R returned false, unmark a return false
    ) 
  ) && z.join``.replace(/0/g,' ') 
)

在测试代​​码片段中,有一个使用DFS的解决方案,该解决方案具有一些约束,可以在不到一分钟的时间内(在我的PC上)解决难题7。拼图8没有解决方案。限制条件:

  • 所有空单元格都必须可从当前单元格到达-不得将空白空间分成两部分
  • 必须有一个可到达的门
  • 一个单元的配置不能被多次探索
  • 无法跳过只有一个空相邻单元格的单元格

测试

请注意,Puzzle 7远远超出了在任何浏览器中执行JavaScript的超时范围(使用Short and Slow解算器)

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.