Python 2 208 205 200字节
A=lambda n:n and A(~-n/3)+[-n%3]or[]
f=lambda x,y:f(A(x),A(y))if x<[]else["SSNEW"[m::3]for m in
y[len(x):]]if x==y[:len(x)]else min([["NNSWE"[m::3]]+f(x[:~x[::-1].index(m)],y)for
m in set(x)],key=len)
函数f带有一对节点号,并返回最短路径作为字符串列表。
说明
我们从对三角形采用不同的寻址方案开始;每个三角形的地址是一个字符串,定义如下:
本质上,每个三角形的地址编码从中心三角形到它的(最短)路径。我们的程序要做的第一件事是将输入的三角形数字转换为相应的地址。

单击图像查看大图。
可以根据地址轻松确定每个三角形处的可能移动:
要移动到北部,西南部和东南部的孩子,我们简单地追加0,1和2分别的地址。
要移动到南部,东北部和西北部的祖先,我们找到的最后一个(最右边)的发生0,1和2分别,和微调地址到左边的吧。如果地址中没有0,1或2,则相应的祖先不存在。例如,要移至112(即其父级)的西北祖先,我们发现2in 的最后一次出现(即112最后一个字符),并在其左侧修剪地址,从而得到11; 要移至东北祖先,我们找到1in 的最后一个出现112,它是第二个字符,并在其左侧修整地址,从而给我们1;但是,112由于没有祖先,所以没有南祖先0 在其地址中。
需要注意的几件事情讲述了一对地址,x并且y:
如果x是的初始子串y,则y是的后代x,因此从x到的最短路径y简单地遵循x和之间的每个三角形的对应子代y。换句话说,我们可以相互替换0,1以及2在y[len(x):]用N,SW和SE分别。
否则,i设为x和之间的第一个不匹配项的索引y。有没有从路径x到y不通过x[:i](其是相同的y[:i]),即,所述第一共同祖先x和y。因此,从x到的任何路径都y必须到达x[:i],或其祖先之一,我们称这个三角形z,然后继续y。若要从到货x到z,我们遵循祖先如上所述。从z到的最短路径y由上一个项目符号点给出。
如果x是的初始子串y,则上面的第一个项目符号点很容易给出从x到的最短路径y。否则,我们让j是最小的最后出现的指标0,1以及2在x。如果j大于或等于,之间的第一失配的索引x和y,i我们简单地添加相应的移动(S,NE,或NW,分别地)的路径,修剪x到左的j,并继续。如果j小于i,事情会变得更加棘手,因为从那时起,我们可能会直接y上升到共同祖先x[:j]并一直下降到y或者我们也许能够去一个不同的共同祖先x,并y认为更接近于y由上升到一个不同的祖先x到右侧i,并从那里得到y更快。例如,要从1222到达1,最短的路径是首先上升到中心三角形(其地址是空字符串),然后下降到1,即,第一步将我们带到不匹配点的左侧。但是,要从1222到达12,最短的路径是先上升到122,然后再上升到12,即,第一个举动将我们带到错配点的右边。
那么,我们如何找到最短的路径?“官方”程序使用暴力破解方法,只要x不是的初始子串,就尝试所有可能的移动到任何祖先y。听起来还不错!它在一两秒钟之内就解决了所有测试用例。
但是话又说回来,我们可以做得更好:如果不匹配点的左边有多个直接可联系的祖先,我们只需要测试最右边的一个,而如果不匹配的祖先不止一个,在不匹配点的右边,我们只需要测试最左边的那个。这将产生一个线性时间算法,该算法的长度x(即源三角形的深度,或与源三角形数量的对数成正比的时间)可以放大更大的测试用例。以下程序至少在本质上实现了该算法-由于打高尔夫球,其复杂性实际上比线性复杂,但仍然非常快。
Python 2 271 266 261字节
def f(x,y):
exec"g=f;f=[]\nwhile y:f=[-y%3]+f;y=~-y/3\ny=x;"*2;G=["SSNEW"[n::3]for
n in g];P=G+f;p=[];s=0
while f[s:]:
i=len(f)+~max(map(f[::-1].index,f[s:]));m=["NNSWE"[f[i]::3]]
if f[:i]==g[:i]:P=min(p+m+G[i:],P,key=len);s=i+1
else:p+=m;f=f[:i]
return P
请注意,与较短的版本不同,此版本专门编写为在输入值到其对应地址的转换中不使用递归,以便它可以处理非常大的值而不会导致堆栈溢出。
结果
以下代码段可用于运行任一版本的测试并生成结果:
def test(x, y, length):
path = f(x, y)
print "%10d %10d => %2d: %s" % (x, y, len(path), " ".join(path))
assert len(path) == length
# x y Length
test( 0, 40, 4 )
test( 66, 67, 5 )
test( 30, 2, 2 )
test( 93, 2, 2 )
test( 120, 61, 8 )
test( 1493682877, 0, 4 )
test( 0, 368460408, 18 )
test( 1371432130, 1242824, 17 )
test( 520174, 1675046339, 23 )
test( 312602548, 940907702, 19 )
test( 1238153746, 1371016873, 22 )
test( 547211529, 1386725128, 23 )
test( 1162261466, 1743392199, 38 )
高尔夫版
0 40 => 4: N N N N
66 67 => 5: S SW N N N
30 2 => 2: NE SW
93 2 => 2: NE SW
120 61 => 8: NW NW NW NW N SE SW N
1493682877 0 => 4: S S NW NW
0 368460408 => 18: SW SW N N SW SW SE SW SW N SE N N SW SW N SE SE
1371432130 1242824 => 17: NW NW NE NW N SE SW SW SW SE SE SW N N N N SW
520174 1675046339 => 23: NE NE NE NE SE SE SW SW N SE N SW N SW SE N N N N SE SE SW SW
312602548 940907702 => 19: NE NW S SW N N SW SE SE SE SW SE N N SW SE SE SE SW
1238153746 1371016873 => 22: NE NE NE SE N N SW N N SW N SE SE SW N SW N N SE N SE N
547211529 1386725128 => 23: S S S S NW N N SE N SW N SE SW SE SW N SE SE N SE SW SW N
1162261466 1743392199 => 38: NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE
高效版
0 40 => 4: N N N N
66 67 => 5: S SW N N N
30 2 => 2: NW NW
93 2 => 2: NE SW
120 61 => 8: NW NW NW NW N SE SW N
1493682877 0 => 4: NE S NW NW
0 368460408 => 18: SW SW N N SW SW SE SW SW N SE N N SW SW N SE SE
1371432130 1242824 => 17: NW NW NE NW N SE SW SW SW SE SE SW N N N N SW
520174 1675046339 => 23: NE NW NE NE SE SE SW SW N SE N SW N SW SE N N N N SE SE SW SW
312602548 940907702 => 19: NE NW S SW N N SW SE SE SE SW SE N N SW SE SE SE SW
1238153746 1371016873 => 22: NE NE NE SE N N SW N N SW N SE SE SW N SW N N SE N SE N
547211529 1386725128 => 23: S S S S NW N N SE N SW N SE SW SE SW N SE SE N SE SW SW N
1162261466 1743392199 => 38: NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE