Haskell 表示为列表列表的2dm矩阵中的邻居

Haskell 表示为列表列表的2dm矩阵中的邻居,haskell,Haskell,我不知道我怎么能在haskell做到。例如,我有这样的矩阵 [[1,2],[3,4]] 我想为这个矩阵生成一个包含每个元素所有可能邻居的列表 预期结果是: [[1,2],[1,3],[1,4],[2,1],[2,3],[2,4],[3,1],[3,2],[3,4],[4,1],[4,2],[4,3]] 我知道如何使用每个单元的相邻连线创建列表: pos how = [ (0+dx,0+dy) | dx <- [0..(how-2)], dy <- [0..how-1] ] ::

我不知道我怎么能在haskell做到。例如,我有这样的矩阵

[[1,2],[3,4]]
我想为这个矩阵生成一个包含每个元素所有可能邻居的列表

预期结果是:

[[1,2],[1,3],[1,4],[2,1],[2,3],[2,4],[3,1],[3,2],[3,4],[4,1],[4,2],[4,3]]
我知道如何使用每个单元的相邻连线创建列表:

pos how = [ (0+dx,0+dy) | dx <- [0..(how-2)], dy <- [0..how-1] ] :: [(Int,Int)]
neighbour (x,y) how = [ (x+dx,y+dy) | dy <- [-1..1], dx <- [-1..1],
                                      x+dx >= 0, y+dy >= 0, x+dx<=how-2, y+dy <= how-1,
                                      (x,y)/=(x+dx,y+dy) ] :: [(Int,Int)]
all_n how = [ p | x <- pos how, let p = neighbour x how ] :: [[(Int,Int)]]

pos-how=[(0+dx,0+dy)| dx让我为你建议的方法画一个非常不同的草图。当谈到邻居时,我会说e的d-邻居是元素e向d方向的一步。例如,在矩阵
[[1,2],[3,4]]
,数字
2
是数字
1
的右邻居。我们需要使用一些库代码

import Data.List
我们将从最简单的事情开始:让我们找到一维列表的正确邻居

rightList (x:y:rest) = (x,y) : rightList (y:rest)
rightList _ = []
我们可以通过不确定地选择矩阵中的一行并找到该行中的所有右邻域来找到矩阵中的所有右邻域

right m = m >>= rightList
我们可以使用任何查找邻居的函数,并通过反转元组来创建查找其他方向邻居的函数。例如,左邻居与右邻居相同,但元组元素交换,因此:

swap (x,y) = (y,x)
co direction = map swap . direction
left = co right
向下邻域呢?实际上,向下邻域是转置矩阵中的正确邻域:

down = right . transpose
up   = co down
下一个感兴趣的方向是右邻域。这一个有点棘手;我们要做的是沿着两个平行的列表走,但被一个抵消

downRight (xs:ys:rest) = zip xs (drop 1 ys) ++ downRight (ys:rest)
downRight _            = []
upLeft = co downRight
最后还有一个方向,即向上的右邻域;如果我们把矩阵颠倒过来,这些就是向下的右邻域

upRight  = downRight . reverse
downLeft = co upRight
最后,为了形成所有的邻域,我们可以不确定地选择一个邻域方向,然后找到该方向上的所有邻域

allDirections = [right, left, up, down,
                 downRight, upLeft, upRight, downLeft]
neighbors m = allDirections >>= ($m)

输出不完全符合您指定的顺序,但我想这可能没什么关系。

让我为您建议的方法勾勒一个非常不同的方法。当谈到邻居时,我会说e的d-邻居是元素e向d方向的一步。例如,在矩阵
[[1,2],[3,4]]
,数字
2
是数字
1
的右邻居。我们需要使用一些库代码

import Data.List
我们将从最简单的事情开始:让我们找到一维列表的正确邻居

rightList (x:y:rest) = (x,y) : rightList (y:rest)
rightList _ = []
我们可以通过不确定地选择矩阵中的一行并找到该行中的所有右邻域来找到矩阵中的所有右邻域

right m = m >>= rightList
我们可以使用任何查找邻居的函数,并通过反转元组来创建查找其他方向邻居的函数。例如,左邻居与右邻居相同,但元组元素交换,因此:

swap (x,y) = (y,x)
co direction = map swap . direction
left = co right
向下邻域呢?实际上,向下邻域是转置矩阵中的正确邻域:

down = right . transpose
up   = co down
下一个感兴趣的方向是右邻域。这一个有点棘手;我们要做的是沿着两个平行的列表走,但被一个抵消

downRight (xs:ys:rest) = zip xs (drop 1 ys) ++ downRight (ys:rest)
downRight _            = []
upLeft = co downRight
最后还有一个方向,即向上的右邻域;如果我们把矩阵颠倒过来,这些就是向下的右邻域

upRight  = downRight . reverse
downLeft = co upRight
最后,为了形成所有的邻域,我们可以不确定地选择一个邻域方向,然后找到该方向上的所有邻域

allDirections = [right, left, up, down,
                 downRight, upLeft, upRight, downLeft]
neighbors m = allDirections >>= ($m)

输出的顺序与您指定的顺序不完全一致,但我想这可能没有多大关系。

为了纠正您现在的代码,我提供了几个问题,这些问题经过深思熟虑的回答可能会帮助您取得进展:

  • how-2
    是件奇怪的事情。为什么
    2
    是正确的减法数字
  • all\n
    的类型很奇怪。为什么它是一个函数?(它的参数代表什么?)为什么它返回一个嵌套列表,而不是一个平面列表
  • 看起来您只跟踪一个尺寸参数,但您的矩阵是二维矩阵。为什么会有这样的差异?(为什么没有宽度和高度参数?)
  • 有了坐标后,您知道如何从矩阵中提取该位置的元素吗?(提示:有一个函数<代码>(!!):[a]->Int->[a]
)如果您有一个坐标列表,您知道如何为列表中的每个元素执行此操作吗?(提示:有一个函数<代码>映射:(a->b>)([a]->[b]))
祝你好运!

为了纠正你现在的代码,我提供了几个问题,深思熟虑的回答可能会帮助你取得进步:

  • how-2
    是件奇怪的事情。为什么
    2
    是正确的减法数字
  • all\n
    的类型很奇怪。为什么它是一个函数?(它的参数代表什么?)为什么它返回一个嵌套列表,而不是一个平面列表
  • 看起来您只跟踪一个尺寸参数,但您的矩阵是二维矩阵。为什么会有这样的差异?(为什么没有宽度和高度参数?)
  • 有了坐标后,您知道如何从矩阵中提取该位置的元素吗?(提示:有一个函数<代码>(!!):[a]->Int->[a])如果您有一个坐标列表,您知道如何为列表中的每个元素执行此操作吗?(提示:有一个函数<代码>映射:(a->b>)([a]->[b]))

祝你好运!

现在很难弄清楚你在问什么。你能再清楚一点吗?例如,你如何定义一个“邻居”?为什么
[1,4]
会包括在你的预期结果列表中?如果手机触摸到其他人,即使是角落里的人也是她的邻居,为什么
[1,4]
在你的预期结果列表中?它不是
[1,2]
[3,4]
的邻居。1用它的角点触摸4 oi48.tinypic.com/20sc2n.jpg你看不到吗?好的,我现在知道了。你应该编辑你的问题,让它更清楚。你现在问的问题真的很难弄清楚。你能稍微冷静一点吗