那条蛇去哪儿了?


35

编写一个函数(使用尽可能少的字节),该函数采用任意数量的列和行的二维数组,其中:

  • 0 代表空块,
  • 1 代表蛇块。

该函数必须返回蛇可能经过的路径数。

范例1:

输入:

[
  [1,1,1,1,1],
  [0,0,0,0,1],
  [0,0,0,0,1],
]

输出: 2

在上面的示例中,该函数将返回,2因为答案是以下之一:

在此处输入图片说明

范例2:

输入:

[
  [1,1,1,1],
  [0,0,1,1],
  [0,0,1,1],
]

输出: 6

在此示例中,该函数将返回,6因为答案是以下之一:

在此处输入图片说明

注意:

评估输入时,可以假定:

  • 表示列的数组将始终具有相同的大小(因此,数组为矩形);
  • 至少存在1条有效路径;
  • 蛇不能穿过边缘(某些蛇可能会发生这种情况)。
  • 蛇将始终至少有2个方块;
  • 蛇不能斜移动。
  • 路径是定向的。(因此,两条路径在不同位置处结束,但看起来完全一样的路径不是同一条路径,它们将总计)

13
欢迎来到PPCG!不错的第一个挑战。
莱科尼

5
小注释:鉴于蛇将始终至少具有2个块,因此“总是将至少有一行和一列”是多余的。
Stewie Griffin

2
建议的测试用例:@StewieGriffin和给出的测试用例[[0,0,1,1],[0,0,1,1],[0,0,1,1]]。大多数的答案给16,但一个给15
凯文Cruijssen

2
到目前为止,似乎每个人(包括我在内)都假设两条路径在不同位置处终止,但看起来完全相同的路径并不相同。我认为这需要明确指定。
阿诺尔德

2
@Arnauld-是的。两条路径以不同的位置结尾但看起来完全相同的两条路径不是同一条路径,它们将总计。在您的示例中,如果我没记错的话,总数应该为16-我现在无法准确计算,但您明白了
阿德琳

Answers:


11

Wolfram语言(Mathematica),16 + 83 = 99字节

库导入语句(16个字节):

<<Combinatorica`

实际功能主体(83个字节):

Length@HamiltonianCycle[MakeGraph[#~Position~1~Join~{1>0},##||Norm[#-#2]==1&],All]&

在线尝试!


请注意,该问题只是询问图中的哈密顿路径数。

但是,(由于某种原因)该HamiltonianPath功能实际上不适用于有向图(例如)。因此,我使用了此Mathematica.SE问题中描述的解决方法:

  • 添加True连接到所有其他顶点的顶点(称为)。
  • 计算结果图上的哈密顿循环数。

该图是使用MakeGraphboolean函数构造的(令人讨厌的是,它没有直接等效的内置函数),该布尔函数仅当参数之一为或两个顶点之间的距离为时才##||Norm[#-#2]==1&返回。TrueTrue1


Tr[1^x]不能代替Length@x<2也不能代替==1


HamiltonianPath如果图形是无向的,则可以使用该函数,函数主体占用84个字节(比当前提交多1个字节):

Length@HamiltonianPath[MakeGraph[#~Position~1,Norm[#-#2]==1&,Type->Undirected],All]&

在线尝试!


10

的JavaScript(ES6),154个 134字节

m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>r&&r[x]&&[-1,0,1,2].map(d=>r[r[x]=0,/1/.test(m)?g(_,x+d%2,y+~-d%2):++n,x]=1)),n=0)|n/4

在线尝试!

怎么样?

方法

从每个可能的单元格开始,我们将矩阵充满,并在途中清除所有单元格。每当矩阵不包含更多1时,我们就会增加可能路径的数量n

由于在最后一个单元格上选择的方向,每个有效路径都会被计数4次,实际上这并不重要。因此,最终结果为n / 4

递归函数

而不是像这样从第二个map()的回调中调用递归函数g() ...

m=>m.map((r,y)=>r.map((_,x)=>(g=(x,y,r=m[y])=>...g(x+dx,y+dy)...)(x,y)))

...我们直接将递归函数g() 定义为map()的回调

m=>m.map((r,Y)=>r.map(g=(_,x,y,r=m[y=1/y?y:Y])=>...g(_,x+dx,y+dy)...))

尽管y=1/y?y:Y设置y的初始值需要很长的公式,但这总共节省了2个字节。

注释代码

m =>                           // given the input matrix m[][]
  m.map((r, Y) =>              // for each row r[] at position Y in m[][]:
    r.map(g = (                //   for each entry in r[], use g() taking:
      _,                       //     - the value of the cell (ignored)
      x,                       //     - the x coord. of this cell
      y,                       //     - either the y coord. or an array (1st iteration),
                               //       in which case we'll set y to Y instead
      r = m[y = 1 / y ? y : Y] //     - r = the row we're currently located in
    ) =>                       //       (and update y if necessary)
      r && r[x] &&             //     do nothing if this cell doesn't exist or is 0
      [-1, 0, 1, 2].map(d =>   //     otherwise, for each direction d,
        r[                     //     with -1 = West, 0 = North, 1 = East, 2 = South:
          r[x] = 0,            //       clear the current cell
          /1/.test(m) ?        //       if the matrix still contains at least one '1':
            g(                 //         do a recursive call to g() with:
              _,               //           a dummy first parameter (ignored)
              x + d % 2,       //           the new value of x
              y + ~-d % 2      //           the new value of y
            )                  //         end of recursive call
          :                    //       else (we've found a valid path):
            ++n,               //         increment n
          x                    //       \_ either way,
        ] = 1                  //       /  do r[x] = 1 to restore the current cell to 1
      )                        //     end of map() over directions
    ),                         //   end of map() over the cells of the current row
    n = 0                      //   start with n = 0
  ) | n / 4                    // end of map() over the rows; return n / 4

10

果冻12 11字节

ŒṪŒ!ạƝ€§ÐṂL

在线尝试!


说明。

ŒṪ               Positions of snake blocks.
  Œ!             All permutations.
                 For each permutation:
    ạƝ€             Calculate the absolute difference for each neighbor pair
       §            Vectorized sum.
                 Now we have a list of Manhattan distance between snake
                    blocks. Each one is at least 1.
        ÐṂL      Count the number of minimum values.
                    Because it's guaranteed that there exists a valid snake,
                    the minimum value is [1,1,1,...,1].

新功能非常有用。
user202729

§ỊML而不是§ỊP€S保存一个字节怎么样-我认为它应该起作用?
乔纳森·艾伦

...或§ÐṂL更快一点。
乔纳森·艾伦

@JonathanAllan仅在结果为非零时起作用。
user202729 '18

@JonathanAllan所以它实际上可以工作。
user202729 '18

8

Python 2中257 246 241 234 233 227个 214 210字节

lambda b:sum(g(b,i,j)for j,l in e(b)for i,_ in e(l))
e=enumerate
def g(b,x,y):d=len(b[0])>x>-1<y<len(b);c=eval(`b`);c[d*y][d*x]=0;return d and b[y][x]and('1'not in`c`or sum(g(c,x+a,y)+g(c,x,y+a)for a in(1,-1)))

在线尝试!


已保存

  • -8个字节,感谢Kevin Cruijssen
  • -14个字节,感谢user202729


1
正确的工作语言?
尼尔,

5

Python 2,158字节

E=enumerate
g=lambda P,x,y:sum(g(P-{o},*o)for o in P if x<0 or abs(x-o[0])+abs(y-o[1])<2)+0**len(P)
lambda L:g({(x,y)for y,r in E(L)for x,e in E(r)if e},-1,0)

在线尝试!


3

Haskell187155字节

r=filter
l=length
(a,b)?(x,y)=abs(a-x)+abs(b-y)==1
l#x=sum[p!r(/=p)l|p<-x]
p![]=1
p!l=l#r(p?)l
f x|l<-[(i,j)|i<-[0..l x-1],j<-[0..l(x!!0)-1],x!!i!!j>0]=l#l

在线尝试!

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.