寻找保利尼莫!


11

不好了!Nemo,我们的小小丑鱼在这个ASCII海洋中迷路了,他的父亲Marlin试图找到他。

您的任务是让Marlin安全地到达Nemo。但是要当心,我们在宽松的状态下有疯狂的布鲁斯,所以最好不惜一切代价避免他!

细节

您将获得一个仅包含小写字母的矩形ASCII海洋网格a-z。该海洋将具有nemomarlinbruce以连续多米诺的形式存在于其内部,始终从多米诺第一列的最顶部单元开始。因此,例如,在所有可能的Tetromino中,有效片段在下面的代码段中列出

但是这样的形式是无效的,并且不会出现在输入中:

omen

ne
mo

nem
o

o
m
en

nem
 o

n
eo
m

最后,您的任务是找到从marlin多米诺瓷砖到nemo多米诺瓷砖的路径,确保路径中的任何单元格都不与bruce多米诺瓷砖相邻。您的输出应使用小写字母以外的可打印ASCII范围(包括空格)中的字符替换所有不属于marlintile,nemotile和连接它们的路径的字母a-z

如果输入海洋如下:

oxknvvolacycxg
xmliuzsxpdzkpw
warukpyhcldlgu
tucpzymenmoyhk
qnvtbsalyfrlyn
cicjrucejhiaeb
bzqfnfwqtrzqbp
ywvjanjdtzcoyh
xsjeyemojwtyhi
mcefvugvqabqtt
oihfadeihvzakk
pjuicqduvnwscv

(其中3个多米诺骨牌为:

...n..........
.mli..........
.ar...........
..............
....b.........
....ruce......
..............
.....n........
.....emo......
..............
..............
..............

那么有效的解决方案可能看起来像:

...n..........
.mli..........
.ar...........
.u............
.n............
.i............
.z............
.wvjan........
.....emo......
..............
..............
..............

以下代码段包含更多示例:

笔记

  • 该网格将永远是一个完美的矩形,将只包含一个的四角瓷砖nemomarlinbruce
  • 您的路径不应穿过图块bruce中任何单元的4个相邻(上,下,左和右)单元中的任何一个bruce
  • 始终保证从marlin到至少会有一条有效路径nemo
  • 这里没有最短路径的要求,所以疯了!
  • 即使您不必找到最短路径,路径中的任何单元格(不包括马林鱼或尼莫蛋白的路径)也不能与该路径中的两个以上其他单元格相邻。
  • 路径不应穿过marlinnemo,否则会迷惑小鱼选择方向。
  • 与往常一样,您可以编写程序或函数,通过STDIN(或最接近的等效项),命令行参数或函数参数获取输入,并通过STDOUT(或最接近的等效项),返回值或函数(out)参数生成输出。
  • 如果无法进行多行输入,则可以假定网格由|字符而不是由字符连接\n。您也可以将输入作为网格行的数组。

这是代码高尔夫球,因此以字节为单位的最短条目将获胜。


路径可以穿过马林鱼(或nemo)吗?如果k上面的l马林鱼可见,上述解决方案仍然有效吗?(从马林岛的n到
尼莫

@KSab我会说“不”,否则会混淆马林鱼:)
优化器

Answers:


4

Matlab 560

删除所有不必要的空格,所有分号和所有注释时为560字节。可以打更多的高尔夫球,但是我现在很累(也许明天……)大家晚安。

PS:我假设路径必须具有4个邻域('+')连通性。

function c(A)
Z = [0,1,0;1,1,1;0,1,0];
Br = q('bruce');
Bn = conv2(Br,ones(3),'s')>0;
Ne = q('nemo');
Ma = q('marlin');
%construct path marlin to nemo
U=Ma>0;M=A*Inf;
M(U)=0;
for k=1:2*sum(size(A))%upper bound for path length
    %expand
    V=imdilate(U,Z);
    V(Bn)=0;
    M(V-U==1)=k;
    U=V;
    %disp(M)
end
%go back from nemo to marlin
Pr=reshape(1:numel(A),size(A));
[i,j]=find(Ne);
m=M(i(1),j(1));%value
P=A*0;%path image
P(i(1),j(1))=1;
for k=m:-1:1
    %find neighbour of (i(1),j(1)) with value m-1
    U=imdilate(P,Z);
    F = M==k;
    G = F&U;
    mask = Pr == min(Pr(F & U));
    P(mask)=1; 
end
A(~P & ~Ma & ~Ne)='.';
disp(A)



    function M = q(s)%find string in matrix, A ascii, M mask
        M = A*0;
        m=numel(s);
        N = M+1;%all neighbours
        for k=1:m;
            M(A==s(k) & N)=k;%only set the ones that were in the neighbourhood of last
            L=M==k;
            N=imdilate(L,Z);
        end
        for k=m:-1:2
            %set all that are not neighbour to next higher highest to zero
            L=M==k;
            N=imdilate(L,Z);
            M(M==k-1 & ~N)=0;
        end
    end


end

调用函数:(不需要换行)

c(['oxknvvolacycxg',
'xmliuzsxpdzkpw',
'warukpyhcldlgu',
'tucpzymenmoyhk',
'qnvtbsalyfrlyn',
'cicjrucejhiaeb',
'bzqfnfwqtrzqbp',
'ywvjanjdtzcoyh',
'xsjeyemojwtyhi',
'mcefvugvqabqtt',
'oihfadeihvzakk',
'pjuicqduvnwscv']);

输出:

...n..........
.mli..........
.ar...........
..c...........
..v...........
..c...........
..q...........
..vjan........
.....emo......
..............
..............
..............

这个怎么运作

提取名字

第一部分是提取名称,例如nemo,由功能完成q()。该函数首先将所有内容标记为0,然后将名称的第一个字母标记为1,然后将第二个字母标记为,2如果1在邻域中有a ,则出现第三个字母,依此类推。在那之后应该nemo只有一个4。从那开始,我们往回走,直到1再次找到,然后删除所有大于该数字的所有其他数字,因此我们得到了一个很好的掩码,其中字母nemo被掩码。我们为所有三个名称执行此操作,然后可以继续查找路径。

寻找道路

我们从马林鱼的位置开始,并逐步通过孔“图像”发送冲击波。在每一步中,我们增加距离计数器,并以当前距离标记波前下方的“像素”。(因为通常使用最短路径算法来完成。)该波阵面显然被Bruce区域阻挡,因此它将在他周围流动。重复此步骤,直到达到上限。现在(很松散)的上限是“图像”的周长(无论如何,最短的路径会更短)。在测试用例中,它看起来像这样:

 2 1 1  0  1  2  3  4  5  6  7  8  9 10
 1 0 0  0  1  2  3  4  5  6  7  8  9 10
 1 0 0  1  2  3  4  5  6  7  8  9 10 11
 2 1 1  _  _  _  5  6  7  8  9 10 11 12
 3 2 2  _  _  _  _  _  _  9 10 11 12 13
 4 3 3  _  _  _  _  _  _ 10 11 12 13 14
 5 4 4  _  _  _  _  _  _ 11 12 13 14 15
 6 5 5  6  7  8  9 10 11 12 13 14 15 16
 7 6 6  7  8  9 10 11 12 13 14 15 16 17
 8 7 7  8  9 10 11 12 13 14 15 16 17 18
 9 8 8  9 10 11 12 13 14 15 16 17 18 19
10 9 9 10 11 12 13 14 15 16 17 18 19 20

现在从nemo像素开始,并在每一步中减少距离计数器,并向其路径添加下一个较低距离的邻居(根据我们之前计算的距离图)。


3

Python 2-658

时间和内存都非常低效。识别模式的功能是递归函数S,而找到路径的功能是C,这基本上是效率极低的A *实现。

G=input().split('\n')
R=range
S=lambda g,x,y,s,B:[[(x,y)]+r for a,b in[(-1,0),(0,-1),(0,1),(1,0)]for r in S(g,x+a,y+b,s[1:],B)if B(x,y)and s[0]==g[y][x]]if s else[[]]
C=lambda l,N,B:[i for i in l if i[-1]in N]or C([i+[(i[-1][0]+c,i[-1][1]+d)]for i in l for c,d in [(-1,0),(0,-1),(0,1),(1,0)]if all(1<abs(i[-1][0]+c-a)or 1<abs(i[-1][1]+d-b)for a,b in B)],N,B)
X,Y=len(G[0]),len(G)
N,M,B=[filter(list,[S(G,s,t,e,lambda a,b:0<=a<X and 0<=b<Y and Y*(a-s)+b-t>=0)for s in R(X)for t in R(Y)])[0][0]for e in["nemo","marlin","bruce"]]
print'\n'.join(''.join(G[y][x]if(x,y)in N+M+min([C([[k]],N,B)[0]for k in M],key=lambda i:len(i))else'.'for x in R(X))for y in R(Y))

为了进行测试,请使用(很少)打高尔夫球的工具(该工具计算一次路径,而不是为每个瓷砖计算)

G=input().split('\n')
R=range
S=lambda g,x,y,s,B:[[(x,y)]+r for a,b in[(-1,0),(0,-1),(0,1),(1,0)]for r in S(g,x+a,y+b,s[1:],B)if B(x,y)and s[0]==g[y][x]]if s else[[]]
C=lambda l,N,B:[i for i in l if i[-1]in N]or C([i+[(i[-1][0]+c,i[-1][1]+d)]for i in l for c,d in [(-1,0),(0,-1),(0,1),(1,0)]if all(1<abs(i[-1][0]+c-a)or 1<abs(i[-1][1]+d-b)for a,b in B)],N,B)
X,Y=len(G[0]),len(G)
N,M,B=[filter(list,[S(G,s,t,e,lambda a,b:0<=a<X and 0<=b<Y and Y*(a-s)+b-t>=0)for s in R(X)for t in R(Y)])[0][0]for e in["nemo","marlin","bruce"]]
s=N+M+min([C([[k]],N,B)[0]for k in M],key=lambda i:len(i))
print'\n'.join(''.join(G[y][x]if(x,y)in s else'.'for x in R(X))for y in R(Y))
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.