在Haskell中生成所有可能的路径
我不擅长措辞,所以请容忍我 我正在做一个问题,需要我在Haskell中以列表的形式生成所有可能的数字 例如,如果x=3,y=2,我必须生成如下列表:在Haskell中生成所有可能的路径,haskell,numbers,combinations,Haskell,Numbers,Combinations,我不擅长措辞,所以请容忍我 我正在做一个问题,需要我在Haskell中以列表的形式生成所有可能的数字 例如,如果x=3,y=2,我必须生成如下列表: [[1,1,1], [1,2,1], [2,1,1], [2,2,1], [1,1,2], [1,2,2], [2,1,2], [2,2,2]] λ> map (99:) [[1],[2],[3],[4],[5],[6],[7]] [[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]] pre
[[1,1,1], [1,2,1], [2,1,1], [2,2,1], [1,1,2], [1,2,2], [2,1,2], [2,2,2]]
λ> map (99:) [[1],[2],[3],[4],[5],[6],[7]]
[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]
prepend2 yss x = map (x:) yss
λ> map (prepend2 [[1],[2],[3],[4],[5],[6],[7]]) [97,98,99]
[[[97,1],[97,2],[97,3],[97,4],[97,5],[97,6],[97,7]],[[98,1],[98,2],[98,3],[98,4],[98,5],[98,6],[98,7]],[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]]
x和y被传递到函数中,它必须处理任何非零正整数x和y
我完全迷路了,甚至不知道如何开始
对于任何愿意帮助我的人,请尽量让数学方面的解释尽可能容易理解。我真的不擅长数学。假设这是家庭作业,我会给你答案的一部分,并告诉你我是如何思考这类问题的。这有助于在GHCi中进行实验,并构建我们需要的部件。我们需要的一件事是能够生成从1到
y
的数字列表。假设y
为7。然后:
λ> [1..7]
[1,2,3,4,5,6,7]
但正如您稍后将看到的,我们真正需要的不是一个简单的列表,而是一个我们可以构建的列表列表。像这样:
λ> map (:[]) [1..7]
[[1],[2],[3],[4],[5],[6],[7]]
这基本上是说获取数组中的每个元素,并将其前置到空列表[]
。现在我们可以编写一个函数来完成这项工作
makeListOfLists y = map (:[]) [1..y]
接下来,我们需要一种为列表中的每个元素预先添加新元素的方法。大概是这样的:
[[1,1,1], [1,2,1], [2,1,1], [2,2,1], [1,1,2], [1,2,2], [2,1,2], [2,2,2]]
λ> map (99:) [[1],[2],[3],[4],[5],[6],[7]]
[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]
prepend2 yss x = map (x:) yss
λ> map (prepend2 [[1],[2],[3],[4],[5],[6],[7]]) [97,98,99]
[[[97,1],[97,2],[97,3],[97,4],[97,5],[97,6],[97,7]],[[98,1],[98,2],[98,3],[98,4],[98,5],[98,6],[98,7]],[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]]
(我在这里使用99而不是1,这样你就可以很容易地看到数字的来源。)因此我们可以编写一个函数来实现这一点:
prepend x yss = map (x:) yss
最终,我们希望能够获取一个列表和一个列表列表,并对列表中的每个元素调用prepend
,将其添加到列表中的每个元素。我们可以再次使用map
函数来实现这一点。但是,事实证明,如果我们将参数的顺序切换到prepend
,则这样做会更容易一些,如下所示:
[[1,1,1], [1,2,1], [2,1,1], [2,2,1], [1,1,2], [1,2,2], [2,1,2], [2,2,2]]
λ> map (99:) [[1],[2],[3],[4],[5],[6],[7]]
[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]
prepend2 yss x = map (x:) yss
λ> map (prepend2 [[1],[2],[3],[4],[5],[6],[7]]) [97,98,99]
[[[97,1],[97,2],[97,3],[97,4],[97,5],[97,6],[97,7]],[[98,1],[98,2],[98,3],[98,4],[98,5],[98,6],[98,7]],[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]]
然后我们可以这样做:
[[1,1,1], [1,2,1], [2,1,1], [2,2,1], [1,1,2], [1,2,2], [2,1,2], [2,2,2]]
λ> map (99:) [[1],[2],[3],[4],[5],[6],[7]]
[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]
prepend2 yss x = map (x:) yss
λ> map (prepend2 [[1],[2],[3],[4],[5],[6],[7]]) [97,98,99]
[[[97,1],[97,2],[97,3],[97,4],[97,5],[97,6],[97,7]],[[98,1],[98,2],[98,3],[98,4],[98,5],[98,6],[98,7]],[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]]
现在我们可以编写这个函数:
supermap xs yss = map (prepend2 yss) xs
以你的例子来说,如果x=2,y=3,那么我们需要的答案是:
λ> let yss = makeListOfLists 3
λ> supermap [1..3] yss
[[[1,1],[1,2],[1,3]],[[2,1],[2,2],[2,3]],[[3,1],[3,2],[3,3]]]
(如果这就是我们所需要的,我们可以使用列表理解更容易地做到这一点。但是,由于我们需要能够对任意的x执行此操作,列表理解将不起作用。)
希望你能从这里开始,把它扩展到任意的x。假设这是家庭作业,我会给你答案的一部分,告诉你我是如何思考这类问题的。这有助于在GHCi中进行实验,并构建我们需要的部件。我们需要的一件事是能够生成从1到
y
的数字列表。假设y
为7。然后:
λ> [1..7]
[1,2,3,4,5,6,7]
但正如您稍后将看到的,我们真正需要的不是一个简单的列表,而是一个我们可以构建的列表列表。像这样:
λ> map (:[]) [1..7]
[[1],[2],[3],[4],[5],[6],[7]]
这基本上是说获取数组中的每个元素,并将其前置到空列表[]
。现在我们可以编写一个函数来完成这项工作
makeListOfLists y = map (:[]) [1..y]
接下来,我们需要一种为列表中的每个元素预先添加新元素的方法。大概是这样的:
[[1,1,1], [1,2,1], [2,1,1], [2,2,1], [1,1,2], [1,2,2], [2,1,2], [2,2,2]]
λ> map (99:) [[1],[2],[3],[4],[5],[6],[7]]
[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]
prepend2 yss x = map (x:) yss
λ> map (prepend2 [[1],[2],[3],[4],[5],[6],[7]]) [97,98,99]
[[[97,1],[97,2],[97,3],[97,4],[97,5],[97,6],[97,7]],[[98,1],[98,2],[98,3],[98,4],[98,5],[98,6],[98,7]],[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]]
(我在这里使用99而不是1,这样你就可以很容易地看到数字的来源。)因此我们可以编写一个函数来实现这一点:
prepend x yss = map (x:) yss
最终,我们希望能够获取一个列表和一个列表列表,并对列表中的每个元素调用prepend
,将其添加到列表中的每个元素。我们可以再次使用map
函数来实现这一点。但是,事实证明,如果我们将参数的顺序切换到prepend
,则这样做会更容易一些,如下所示:
[[1,1,1], [1,2,1], [2,1,1], [2,2,1], [1,1,2], [1,2,2], [2,1,2], [2,2,2]]
λ> map (99:) [[1],[2],[3],[4],[5],[6],[7]]
[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]
prepend2 yss x = map (x:) yss
λ> map (prepend2 [[1],[2],[3],[4],[5],[6],[7]]) [97,98,99]
[[[97,1],[97,2],[97,3],[97,4],[97,5],[97,6],[97,7]],[[98,1],[98,2],[98,3],[98,4],[98,5],[98,6],[98,7]],[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]]
然后我们可以这样做:
[[1,1,1], [1,2,1], [2,1,1], [2,2,1], [1,1,2], [1,2,2], [2,1,2], [2,2,2]]
λ> map (99:) [[1],[2],[3],[4],[5],[6],[7]]
[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]
prepend2 yss x = map (x:) yss
λ> map (prepend2 [[1],[2],[3],[4],[5],[6],[7]]) [97,98,99]
[[[97,1],[97,2],[97,3],[97,4],[97,5],[97,6],[97,7]],[[98,1],[98,2],[98,3],[98,4],[98,5],[98,6],[98,7]],[[99,1],[99,2],[99,3],[99,4],[99,5],[99,6],[99,7]]]
现在我们可以编写这个函数:
supermap xs yss = map (prepend2 yss) xs
以你的例子来说,如果x=2,y=3,那么我们需要的答案是:
λ> let yss = makeListOfLists 3
λ> supermap [1..3] yss
[[[1,1],[1,2],[1,3]],[[2,1],[2,2],[2,3]],[[3,1],[3,2],[3,3]]]
(如果这就是我们所需要的,我们可以使用列表理解更容易地做到这一点。但是,由于我们需要能够对任意的x执行此操作,列表理解将不起作用。)
希望您可以从这里开始,并将其扩展到任意x。对于特定的x,如前所述,列表理解将起到作用,假设x等于3,我们将编写以下代码:
generate y = [[a,b,c] | a<-[1..y], b<-[1..y], c <-[1..y]]
为嵌套列表定义了条带。通过合并列表项,可以说减少了层次结构。比如打电话
strip [[1],[2],[3]]
生成输出:
[1,2,3]
[[[1,1],[2,1]],[[1,2],[2,2]]]
这是个棘手的问题
在递归的最后一步,当第二个参数等于2时,函数将[1..y]的每个项与同一列表的每个元素映射到一个新列表中。比如说
map (\a-> map (:a:[]) [1..2]) [1..2])
生成输出:
[1,2,3]
[[[1,1],[2,1]],[[1,2],[2,2]]]
剥离功能将其转化为:
[[1,1],[2,1],[1,2],[2,2]]
对于递归的初始步骤,当x大于2时,populate执行几乎相同的操作,只是这次它将列表的项映射到递归调用生成的列表。最后:
populate 2 3
为我们提供了期望的结果:
[[1,1,1],[2,1,1],[1,2,1],[2,2,1],[1,1,2],[2,1,2],[1,2,2],[2,2,2]]
正如我前面提到的,这种方法既不是最有效的,也不是最可读的,但我认为它解决了问题。事实上,从理论上讲,在不大量使用递归的情况下解决此问题的唯一方法是使用列表理解语句构建字符串,而不是动态编译该字符串,根据我作为程序员的短期经验,这从来都不是一个好的解决方案。对于特定的x,如前所述,列表理解可以做到这一点,假设x等于3,我们可以写以下内容:
generate y = [[a,b,c] | a<-[1..y], b<-[1..y], c <-[1..y]]
为嵌套列表定义了条带。通过合并列表项,可以说减少了层次结构。比如打电话
strip [[1],[2],[3]]
生成输出:
[1,2,3]
[[[1,1],[2,1]],[[1,2],[2,2]]]
这是个棘手的问题
在递归的最后一步,当第二个参数等于2时,函数将[1..y]的每个项与同一列表的每个元素映射到一个新列表中。比如说
map (\a-> map (:a:[]) [1..2]) [1..2])
生成输出:
[1,2,3]
[[[1,1],[2,1]],[[1,2],[2,2]]]
剥离功能将其转化为:
[[1,1],[2,1],[1,2],[2,2]]
对于递归的初始步骤,当x大于2时,populate执行几乎相同的操作,只是这次它使用