无限迷宫


35

背景

您是一个功能强大的向导的徒弟,您的大师当前正在开发一种咒语,以创建一个多维迷宫来诱捕敌人。他希望您对自己的蒸汽动力计算机进行编程,以分析可能的布局。对这台恶魔般的机器进行编程非常危险,因此您需要使代码尽可能短。

输入值

您的输入是一个由句点.和哈希组成的二维网格#,表示空白空间和墙壁,以换行符分隔的字符串形式给出。总是至少有一个.和一个#,并且您可以决定是否有尾随换行符。

此网格是无限迷宫的蓝图,它是通过将网格的许多副本彼此相邻对齐而制成的。迷宫分为空腔,它们是空空间的连接组件(对角相邻的空间不连接)。例如网格

##.####
...##..
#..#..#
####..#
##...##

导致以下迷宫(在各个方向无限连续):

##.######.######.####
...##.....##.....##..
#..#..##..#..##..#..#
####..#####..#####..#
##...####...####...##
##.######.######.####
...##.....##.....##..
#..#..##..#..##..#..#
####..#####..#####..#
##...####...####...##
##.######.######.####
...##.....##.....##..
#..#..##..#..##..#..#
####..#####..#####..#
##...####...####...##

这个特殊的迷宫包含一个无限区域的空腔。另一方面,此蓝图导致迷宫只有有限的空腔:

##.####
##..###
####...
..####.
#..####

输出量

如果迷宫包含无限的空腔,则您的输出应为真实值,否则为虚假的值。注意迷宫可能同时包含有限和无限的腔;在这种情况下,输出应为真实的。

规则

您可以编写完整的程序或函数。最低字节数获胜,并且不允许出现标准漏洞。

其他测试用例

无限腔:

.#

#.#
...
#.#

#.###.#.###.#
#.#...#...#.#
#.#.#####.#.#
..#.#...#.#..
###.#.#.#.###
#...#.#.#...#
#.###.#.###.#

##.###
#..###
..##..
###..#
##..##

..#..#..#..#..#..#
.#..#..#..#..#..#.
#..#..#..#..#..#..

#.####.###.###.####
#...#..#...###..###
###.#..#.######..##
....####.#######...
###..###...########
##########.##....##
..###......##.##...
#.........##..#####
###########..###..#
#...........####..#
#.###########.##..#
#.##....##.....####
#.####.###.###.####

有限型腔:

###
#.#
###

.#
#.

####
.#..
####

#.#.#
..#..
#####
..#..
#.#.#

#.#.#.#.#.#
..#...#.#..
###.###.###
..#.#......
#.#.#######
#.#.......#
#.#######.#
#.#.....#.#
#.#.#.#.#.#

##....#####
.#..#...##.
.##.#..#...
..###.###..
#..##.#####
#...##....#
#.#.#####.#
###..####.#
....####...
###...#####

###....##.#########
####...##....#...##
..####.#######.###.
....##..........##.
###..#####.#..##...
####..#..#....#..##
..###.####.#.#..##.
..###...#....#.#...
..####..##.###...##
#.####.##..#####.##
####...##.#####..##


###########
........#..
#########.#
..........#
.##########
.#.........
##.########
...#.......

是否有换行符?
FUZxxl 2015年

@FUZxxl由您决定。
Zgarb 2015年

无限迷宫是否可以是一直延伸到无限的直线。

1
@尼尔,我不确定你的意思。第一个和第二个无限示例具有无限行,但是输入中至少有一个.和一个#
Zgarb 2015年

1
不错的挑战,比看起来要困难的多
edc65

Answers:


2

的JavaScript(ES6),235 253

@mac使用的方法相同。对于每个空闲单元格,我尝试进行递归填充,并用我正在使用的坐标(可以在原始模板之外)标记使用过的单元格。如果在填充过程中我到达一个已经标记为具有不同坐标的像元,则我处于无限路径中。

在JS中处理模数的古怪方式很烦人。

L=g=>(
  g=g.split('\n').map(r=>[...r]),
  w=g[0].length,h=g.length,
  F=(x,y,t=((x%w)+w)%w,u=((y%h)+h)%h,v=g[u][t],k=0+[x,y])=>
    v<'.'?0:v>'.'?v!=k
    :[0,2,-3,5].some(n=>F(x+(n&3)-1,y+(n>>2)),g[u][t]=k),
  g.some((r,y)=>r.some((c,x)=>c=='.'&&F(x,y)))
)

在Firefox / FireBug控制台中测试

无穷

['##.###\n#..###\n..##..\n###..#\n##..##'
,'#.#\n...\n#.#'
,'#.###.#.###.#\n#.#...#...#.#\n#.#.#####.#.#\n..#.#...#.#..\n###.#.#.#.###\n#...#.#.#...#\n#.###.#.###.#'
,'##.###\n#..###\n..##..\n###..#\n##..##'
,'#.####.###.###.####\n#...#..#...###..###\n###.#..#.######..##\n....####.#######...\n###..###...########\n##########.##....##\n..###......##.##...\n#.........##..#####\n###########..###..#\n#...........####..#\n#.###########.##..#\n#.##....##.....####\n#.####.###.###.####'
].forEach(g=>console.log(g,L(g)))

输出量

"##.###
#..###
..##..
###..#
##..##" true

"#.#
...
#.#" true

"#.###.#.###.#
#.#...#...#.#
#.#.#####.#.#
..#.#...#.#..
###.#.#.#.###
#...#.#.#...#
#.###.#.###.#" true

"##.###
#..###
..##..
###..#
##..##" true

"#.####.###.###.####
#...#..#...###..###
###.#..#.######..##
....####.#######...
###..###...########
##########.##....##
..###......##.##...
#.........##..#####
###########..###..#
#...........####..#
#.###########.##..#
#.##....##.....####
#.####.###.###.####" true

有限

['###\n#.#\n###', '.#\n#.', '####\n.#..\n####'
,'#.#.#\n..#..\n#####\n..#..\n#.#.#'
,'#.#.#.#.#.#\n..#...#.#..\n###.###.###\n..#.#......\n#.#.#######\n#.#.......#\n#.#######.#\n#.#.....#.#\n#.#.#.#.#.#'
,'##....#####\n.#..#...##.\n.##.#..#...\n..###.###..\n#..##.#####\n#...##....#\n#.#.#####.#\n###..####.#\n....####...\n###...#####'
,'###....##.#########\n####...##....#...##\n..####.#######.###.\n....##..........##.\n###..#####.#..##...\n####..#..#....#..##\n..###.####.#.#..##.\n..###...#....#.#...\n..####..##.###...##\n#.####.##..#####.##\n####...##.#####..##'
].forEach(g=>console.log(g,L(g)))

输出量

"###
#.#
###" false

".#
#." false

"####
.#..
####" false

"#.#.#
..#..
#####
..#..
#.#.#" false

"#.#.#.#.#.#
..#...#.#..
###.###.###
..#.#......
#.#.#######
#.#.......#
#.#######.#
#.#.....#.#
#.#.#.#.#.#" false

"##....#####
.#..#...##.
.##.#..#...
..###.###..
#..##.#####
#...##....#
#.#.#####.#
###..####.#
....####...
###...#####" false

"###....##.#########
####...##....#...##
..####.#######.###.
....##..........##.
###..#####.#..##...
####..#..#....#..##
..###.####.#.#..##.
..###...#....#.#...
..####..##.###...##
#.####.##..#####.##
####...##.#####..##" false

是的,愚蠢的模数在C#中也是一种痛苦,但是我想我已经找到了一种方法,可以在我的带有方向代码的工作副本中充分利用它(我只会在能获得10%的费用的情况下重新发布)减少或更好):(j%4-1)%2给出一个不错的重复模式。
VisualMelon 2015年

我相信未命名的函数是允许的,因此,除非该函数包括对自身的调用(看来不如此),否则不计入L=字节数是允许的。
SuperJedi224 2015年

@ SuperJedi224您可能是对的,但毕竟足够简短
edc65

21

C#-423375字节

完整的C#程序,接受通过STDIN的输入,并根据需要向STDOUT输出“ True”或“ False”。

我不能光秃秃地把那把Linq留在那里...谢天谢地,它的清除还清了!现在,它可以跟踪阵列中可见和已访问的单元格(只要它始终只看有限数量的单元格)。我还重新编写了定向代码,消除了对Lambda的需要,通常使该代码更难以理解(但节省了大量字节)。

using C=System.Console;struct P{int x,y;static void Main(){int w=0,W,k=0,o,i,j;P t;string D="",L;for(;(L=C.ReadLine())!=null;D+=L)w=L.Length;for(i=W=D.Length;i-->0&k<W;){k=1;P[]F=new P[W];for(F[j=0].x=i%w+W*W,F[0].y=i/w+W*W;D[i]>35&j<k;)for(t=F[j++],o=1;o<5&k<W;t.y+=(o++&2)-1){t.x+=o&2;if(D[--t.x%w+t.y%(W/w)*w]>35&System.Array.IndexOf(F,t)<0)F[k++]=t;}}C.WriteLine(k>=W);}}

这是广度优先(并非重要)的搜索,一直进行直到它卡在有限的洞穴中,或者确定洞穴足够大以至于它必须无限大(当它具有与原始矩形,这意味着必须存在从一个单元格到其自身其他位置的路径,我们可以一直沿此路径走下去)。

未整理的代码:

using C=System.Console;

struct P
{
    int x,y;

    static void Main()
    {
        int w=0, // w is the width
        W, // W is the length of the whole thing
        k=0, // k is visited count
        o, // o is offset, or something (gives -1,0 0,-1 +1,0 0,+1 t offset pattern)
        i, // i is the start cell we are checking currently
        j; // j is the F index of the cell we are looking at

        P t; // t is the cell at offset from the cell we are looking at

        string D="", // D is the map
        L;

        for(;(L=C.ReadLine())!=null; // read a line, while we can
            D+=L) // add the line to the map
            w=L.Length; // record the width

        for(i=W=D.Length;i-->0&k<W;) // for each cell
        {
            k=1;

            P[]F=new P[W]; // F is the list of visited cells,

            for(F[j=0].x=i%w+W*W,F[0].y=i/w+W*W; // there are reasons (broken modulo)
                D[i]>35&j<k;) // for each cell we've visited, until we've run out
                for(t=F[j++], // get the current cell
                    o=1; // o is just a counter which we use to kick t about
                    o<5& // 4 counts
                    k<W; // make sure we havn't filled F
                    t.y+=(o++&2)-1) // kick and nudge y, inc o
                {
                    t.x+=o&2; // kick x
                    if(D[--t.x%w+t.y%(W/w)*w]>35 // nudge x, it's a dot
                       &System.Array.IndexOf(F,t)<0) // and we've not seen it before
                        F[k++]=t; // then add it
                }
        }

        C.WriteLine(k>=W); // result is whether we visited lots of cells
    }
}

1
大概是我第一次看到C#答案是这里的最高投票者。
Michael McGriff

1
Main()在结构中,现在多数民众赞成在可爱。
PTwr 2015年

10

蟒2 - 258个 210 244字节

递归检查路径,如果堆栈溢出返回1(真),否则返回None(假)。

import sys
def k(s):
 a=len(s);m=[[c=='.'for c in b]*999for b in s.split('\n')]*999;sys.setrecursionlimit(a)
 for x in range(a*a):
  try:p(m,x/a,x%a)
  except:return 1
def p(m,x,y):
 if m[x][y]:m[x][y]=0;map(p,[m]*4,[x,x,x+1,x-1],[y+1,y-1,y,y])

1
您可以使用;中的行来保存一些字节p,因为它们将与放在同一行if
PurkkaKoodari 2015年

11
“如果堆栈溢出返回true”-我喜欢该递归结束条件:)
schnaader

3
我不认为这是有效的方法。使用堆栈溢出检测“无限”区域将产生误报。问题规格没有说明对输入范围的任何限制,但是类似300x300的迷宫似乎并不合理,并且可能包含很长的有限路径。
强尼

4
几乎所有有限的迷宫都会导致堆栈溢出。这不是有效的程序。
PyRulez

@johne已更新,因此递归限制约为迷宫大小。不幸的是增加了34个字节,但现在应该正确了(至少像这样的hack一样正确)。
凯尔·金利恩

5

Python的2 - 297个 286 275字节

选择一个任意的“开放”单元格以开始填充。如果在填充过程中我们重新访问了一个已经访问过的单元,则迷宫是无限的,但是它与上一次访问具有不同的坐标。如果泛洪填充未找到这样的像元,则填充了整个区域,请尝试其他区域。如果找不到这样的区域,则迷宫是有限的。

在命令行上获取文件进行处理,返回1无限和0有限的退出代码。

返回所有测试用例的正确结果。

import sys
e=enumerate
C=dict([((i,j),1)for i,l in e(open(sys.argv[1]))for j,k in e(l)if'.'==k])
while C:
 d={}
 def f(r,c):
  n=(r%(i+1),c%j)
  if n in d:return(r,c)!=d[n]
  if C.pop(n,0):d[n]=(r,c);return any(map(f,[r-1,r,r+1,r],[c,c+1,c,c-1]))
 if f(*C.keys()[0]):exit(1)

1
您不能假设某些单元将成为无限洞穴的成员,您可以轻松拥有无限洞穴和有限洞穴。
VisualMelon

2
@VisualMelon:对不起,描述并不完全正确。该代码实际上检查互连的单元的每个可能区域,而不仅仅是检查一个(当前暗示)。这就是最后的while循环的目的-选择区域进行检查,同时还剩下任何未检查的单元格。
2015年
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.