森林小径


9

您之后灾难性乘坐独木舟,你结束了在湍急的河流最终掉下瀑布。您的独木舟爆炸了,但您成功度过了爆炸。但是,您的河流之旅完全偏离了地图-您现在发现自己迷失在森林之中。幸运的是,您仍然具有编程技能,因此决定将程序雕刻到树的一边,以帮助您找到穿过森林的道路。但是,树上没有太多的表面积,因此您必须使程序尽可能短。

森林可以用字符nnn > 5)平方来描述,该字符仅由小写字母组成a-z。一个示例森林:

anehcienwlndm
baneiryeivown
bnabncmxlriru
anhahirrnrauc
riwuafuvocvnc
riwnbaueibnxz
hyirorairener
ruwiiwuauawoe
qnnvcizdaiehr
iefyioeorauvi
quoeuroenraib
cuivoaisdfuae
efoiebnxmcsua

您可能已经注意到,在这个森林中,a从左上角到右下角有一条斜线贯穿其中。这是穿过森林的“路径”,如果您跟随它,它将指引您到达某个地方。您的任务是编写一个程序,它将找到单数路径。我现在将更具体地描述在此挑战中什么代表“道路”。

在此挑战中,“路径”被定义为类似于可能用Bresenham算法生成的线,但具有以下附加要求:

  • 该行必须至少6个字符长
  • 行中的每个共线(完全相邻)字符组必须具有相同的长度
  • 它将从森林的一侧开始,到另一侧结束(详细说明请参见我的评论

为了更清楚地解释第二个要求,请考虑以下内容:

aaa
   aaa
      aaa
         aaa
            aaa

该行由字符的共线“段”组成,每个字符正好是三个字符长。它有资格作为一条路径。现在考虑这一行:

a
 aa
   a
    aa
      a
       aa

该行由共线的“段”组成,它们并非完全相同长度的字符(其中一些长度为1个字符,而某些长度为2个)。因此,这条路径不符合条件。

给定森林图,您的程序将识别路径中使用的字符。输入是方便的任何内容(例如,命令行参数,STDIN prompt()等)。不能将其预先初始化为变量。输入的第一部分是一个单个整数,n代表森林的大小(森林总是一个正方形)。在那之后是一个空格,然后将整个森林作为单个字符串。例如,示例林将作为输入呈现,如下所示:

13  anehcienwlndmbaneiryeivownbnabncmxlriruanhahirrnraucriwuafuvocvncriwnbaueibnxzhyirorairenerruwiiwuauawoeqnnvcizdaiehriefyioeorauviquoeuroenraibcuivoaisdfuaeefoiebnxmcsua

输出为:

a

因为路径是使用字母形成的a。森林中只有一条路。这是代码高尔夫,因此获胜的字符数最少。如有疑问,请在评论中提问。


如果有多个路径怎么办?
埃里克·特雷斯勒

@@ EricTressler在任何给定的森林中只有一条路。我将编辑规范以反映这一点。
2014年

路径字母可以在不属于该路径的其他地方使用吗?
马丁·恩德

示例林可能包含该内容。示例森林中此行上的第一个a不属于anhahirrnrauc路径的一部分
Spade

@@MartinBüttner是的。但它们在任何时候都不会是由同一字母组成的两条路径。
2014年

Answers:


3

APL(Dyalog 14)(70)

⎕ML←3⋄Z/⍨1=≢¨Z←∪¨(↓⍉F),(↓F),{(⍳≢⍵)⌷¨↓⍵}¨(⊂F),⊂⌽F←⊃{⍵⍴⍨2/⍎⍺}/I⊂⍨' '≠I←⍞

说明:

  • ⎕ML←3:设置ML3,含义具有其APL2含义。
  • I←⍞:从键盘上读取一行并将其存储在 I
  • I⊂⍨' '≠II在空格上分开
  • {... }/:将此功能应用于两个结果字符串:
    • 2/⍎⍺:求左参数并复制两次,给出矩阵大小
    • ⍵⍴⍨:使用该大小格式化正确的参数
  • F←⊃:取消装箱并将其存储在中F
  • {(⍳≢⍵)⌷¨↓⍵}¨(⊂F),⊂⌽F:得到对角线:从在这两个各行F⌽F(垂直镜像F),在列X,其中X是其行号得到的值
  • (↓⍉F),(↓F),:获取的行和列 F
  • Z←∪¨:在每一行,每一列和对角线上找到唯一的值,并将其存储在中Z

由于“森林”是矩形,因此,如果存在有效路径,则意味着其中一个仅包含一个字符,即路径字符,因此:

  • Z/⍨1=≢¨Z:从Z只有一个元素的那些子数组中获取。

这将显示所有有效路径的字符,但是由于应该只有一个无关紧要的字符。


4

Lua- 506380-字节

对于您的深思熟虑的挑战,您还没有收到任何提交书,我感到非常遗憾,因此我将其汇总。从您提供的信息中推断出路径必须具有的最小可区分属性是一件很有趣的事情。我希望我做对了...并正确实施了它。

a=io.read"*l"n=a:match("%d+")+0 m=a:match"[a-z]+"o=""for i=1,n do for k=1,n^2,n do o=o..m:sub(i+k-1,i+k-1)end end q={m,o}for g=1,n^2 do for u=1,2 do l=q[u]:sub(g,g)for r=1,n do i=1 t=0 e=0 while i do s,e=q[u]:find(l:rep(r),e+1)if s then x=s-(e-s)-i-1 print(s,i,r,n,r)if x==n or x==n-2 or t==0 then t=t+1 i=s end else i=nil end end if t*r==n then print(l)os.exit()end end end end

可以使用以下方法进行测试:

lua divisorPath.lua "input"

如果出现野性挑战者,我将寻找有价值的代码。

更新:打高尔夫球,以纪念将超越我们的人们。在此期间,我不得不将代码固定为从右到左的公认路径。哎呀。


3

MATLAB-270个字符

下面定义了一个函数x,该函数接受林字符串作为参数,并根据给定规则返回代表通过林的有效“路径”的字符。

function F=x(s),A=sscanf(s,'%d%s');n=A(1);A=reshape(A(2:end),n,n);for c=A(:)',B=A==c;for i=1:n,if~mod(n,i),C=[kron(eye(i),ones(n/i,1)),zeros(n,n-i)];for j=0:n-i,f=@(B)sum(sum(B&circshift(C,[0,j]))==n;D=fliplr(B);if f(B)|f(B')|f(D)|f(D'),F=char(c);end;end;end;end;end;end

非缩小版本为

function F = x(s)
    A = sscanf( s, '%d %s' );
    n = A(1);
    A = reshape( A(2:end), n,n );
    for c = A(:)'
        B = A==c;
        for i = 1:n
            if ~mod( n, i )
                C = [kron( eye(i), ones( n/i,1 ) ), zeros( n,n-i )];
                for j = 0:n-i
                    f = @(B) sum(sum( B & circshift( C, [0 j] ))) == n;
                    D = fliplr(B);
                    if f(B) | f(B') | f(D) | f(D')
                        F = char(c);
                    end
                end
            end
        end
    end
end

基本前提是为每个可能的有效路径构造一个布尔掩码,并返回矩阵中索引函数覆盖任何掩码的任何字符。为此,仅创建了垂直或自上而下的反斜杠形蒙版,但是在所有四个方向中对林矩阵进行了比较:同一性,翻转,旋转90°,翻转旋转90°。

该函数可以运行任何n。在命令行上调用它的一个示例是

x('13 anehcienwlndmbaneiryeivownbnabncmxlriruanhahirrnraucriwuafuvocvncriwnbaueibnxzhyirorairenerruwiiwuauawoeqnnvcizdaiehriefyioeorauviquoeuroenraibcuivoaisdfuaeefoiebnxmcsua')

ans =

    a

3

蟒蛇- 384 325 275

此算法基本上检查矩阵的第一行和最后一行是否匹配字符,然后计算每个线段的长度

012345
------
aaVaaa|0
aaVaaa|1
aaaVaa|2
aaaVaa|3
aaaaVa|4
aaaaVa|5

在上面的示例中:
第一行的V在索引2,最后一行的V在索引4。
因此,每个线段的长度为n /(4-2)+1 = 2,其中n = 6 。

然后,它检查该行是否有效。

为了找到从左到右的路径,它将行与列交换,然后再次执行相同的操作。

编辑:不能完全达到270(该死的Python和该死的缩进!!)

n,m=raw_input().split()
n,r=int(n),range
t=r(n)
a=[m[i:i+n]for i in r(0,n*n,n)]
for v in a,["".join([a[i][j]for i in t])for j in t]:
 for i in t:
  for j in t:
   p=1-2*(j-i<0);d,c=p*(j-i)+1,v[0][i]
   if 6<=sum([v[z][i+(z/(n/d))*p*(n%d==0)]==c for z in t])==n:print c;exit()
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.