获取所有可能的邻居坐标

Get all possible neighbour coordinates

我用 (Int, Int, Int)

类型的元组表示 3D 坐标

为了获得坐标的直接邻居,我做了这样的事情:

neighbours (x,y,z) =
    [(x',y',z') | x' <- [(x-1)..(x+1)], y' <- [(y-1)..(y+1)], z' <- [(z-1)..(z+1)], (x,y,z) /= (x',y',z')]

现在,我也需要使用 4D 坐标,我可以做一些非常相似的事情来获得具有 4 个元素的元组的邻居,它会起作用。但是,我需要复制我为 3D 坐标所做的所有功能,这次是为 4D 坐标。

为了避免这种情况,我想基本上用 Int 列表替换元组,现在对于 3D 坐标来说,例如 [9, 3, 0] 和 4D 坐标 [5, 1, 0, 1] 和等等。

如何获得数组为 Int 的邻居?我尝试使用列表理解,但未能找到解决方案。

PS:我是Haskell和函数式编程的新手

您可以递归地进行,并根据 N-D 邻居实现 (N+1)-D 邻居。

本质上,如果你有一个 (N+1)-D 点 [x1,...,xNplus1] 这是 x1 : xs 的形式,其中 xs 是一个 N-D 点。因此,如果您已经知道 xs 的邻居列表,则可以将其转换为 x1 : xs.

的邻居列表

这是一个简单的尝试,应该差不多可以。

almostNeighbours :: [Int] -> [[Int]]
almostNeighbours []     = [[]]
almostNeighbours (x:xs) =
   [ x' : xs'
   | x' <- [x-1 .. x+1] , xs' <- almostNeighbours xs ]

请注意,我们确实将该点本身包含在邻居列表中。如果不这样做,在递归情况下将不会产生足够的分数。 (我建议说服自己,事实确实如此。)

如果您不想要该点本身,您可以随时使用附加函数将其删除,而不会影响递归定义。

最后,请注意上面的代码可能不会像您原来的那样快,因为访问列表比元组慢。


次要替代方案:使用应用样式我们可以稍微缩短代码。

almostNeighbours :: [Int] -> [[Int]]
almostNeighbours []     = pure []
almostNeighbours (x:xs) = (:) <$> [x-1 .. x+1] <*> almostNeighbours xs