使用布尔值列出 Haskell 中的组合
List combinations in Haskell with booleans
所以,我最近开始学习 Haskell,我遇到了一个问题,我需要计算所有可能的结果 (2^n) 如果翻转 n 个硬币。例如,如果掷 2 个硬币,输出应该是 [[H, H], [H, T], [T, H], [T, T]]。同样,对于 3 个硬币,它应该是 [[H, H, H], [H, H, T], [H, T, H], [T, H, H], [H, T, T], [ T, T, H], [T, H, T], [T, T, T]]。我的函数不适用于 n 的任意值。它只有在我以前知道 n 的情况下才有效。我正在考虑使用递归,但我不确定语法。
这是我的代码:
outcomes(x:xs) = [[a, b] | a <- states x, b <- states (head xs)]
其中,函数状态为:
states _ = [True, False]
此函数适用于 n = 2。请告诉我如何使其适用于任何输入 n。
由于您希望您的函数适用于任意次数的翻转 n
,它可能应该接受一个 Int 参数:否则您将如何获得一个 Int?而且,正如评论中所建议的那样,递归是在 Haskell 中执行类似循环的事情的方法,您将需要一个基本案例和一个递归案例。对于计数,0 是一个自然的基本情况,也是这里使用的最佳情况,但是使用 1 作为基本情况对于初学者来说更容易理解一些,所以我们让函数 break for n=0
现在。
因此,您需要一个具有两种模式的函数:
outcomes :: Int -> [[Bool]]
outcomes 1 = _
outcomes n = _
1 的结果应该是什么,即翻转一次?一旦你有了它,你能根据 outcomes (n - 1)
实现 outcomes n
吗?如果是这样,你就完成了。如果没有,您最好 material 提出一个新问题,因为您已经完成了解决方案的一半。
额外加分,一旦完成,看看你是否能充分理解递归,为 outcomes 0
选择一个可以替代 outcomes 1
作为你的基本情况的好值。
你可以在这里使用递归。我们可以构造一个函数,它接受一个元素列表 [a]
和一个 Int
,所以:
outcomes :: [a] -> Int -> [[a]]
如果整数小于或等于零,则只有一个可能的结果是空列表。所以我们 return 一个包含一个空列表的列表:
outcomes _ n | n <= 0 = [[]]
至于递归的情况,我们可以从列表中取出一个元素,然后使用相同的值列表进行递归,但是我们创建的结果少了一个元素,然后我们将我们取出的元素添加到这些结果中。
outcomes ls n = [ … | x < ls, xs <- … ]
这里我将 …
部分留作练习。在第一个 …
片段中,您需要在 xs
前面加上 x
。在第二个中,您需要进行递归调用。
因此,将其放在一起,我们将 outcomes
实现为:
outcomes :: [a] -> Int -> [[a]]
outcomes _ n | n <= 0 = [[]]
outcomes ls n = [ … | x < ls, xs <- … ]
所以,我最近开始学习 Haskell,我遇到了一个问题,我需要计算所有可能的结果 (2^n) 如果翻转 n 个硬币。例如,如果掷 2 个硬币,输出应该是 [[H, H], [H, T], [T, H], [T, T]]。同样,对于 3 个硬币,它应该是 [[H, H, H], [H, H, T], [H, T, H], [T, H, H], [H, T, T], [ T, T, H], [T, H, T], [T, T, T]]。我的函数不适用于 n 的任意值。它只有在我以前知道 n 的情况下才有效。我正在考虑使用递归,但我不确定语法。
这是我的代码:
outcomes(x:xs) = [[a, b] | a <- states x, b <- states (head xs)]
其中,函数状态为:
states _ = [True, False]
此函数适用于 n = 2。请告诉我如何使其适用于任何输入 n。
由于您希望您的函数适用于任意次数的翻转 n
,它可能应该接受一个 Int 参数:否则您将如何获得一个 Int?而且,正如评论中所建议的那样,递归是在 Haskell 中执行类似循环的事情的方法,您将需要一个基本案例和一个递归案例。对于计数,0 是一个自然的基本情况,也是这里使用的最佳情况,但是使用 1 作为基本情况对于初学者来说更容易理解一些,所以我们让函数 break for n=0
现在。
因此,您需要一个具有两种模式的函数:
outcomes :: Int -> [[Bool]]
outcomes 1 = _
outcomes n = _
1 的结果应该是什么,即翻转一次?一旦你有了它,你能根据 outcomes (n - 1)
实现 outcomes n
吗?如果是这样,你就完成了。如果没有,您最好 material 提出一个新问题,因为您已经完成了解决方案的一半。
额外加分,一旦完成,看看你是否能充分理解递归,为 outcomes 0
选择一个可以替代 outcomes 1
作为你的基本情况的好值。
你可以在这里使用递归。我们可以构造一个函数,它接受一个元素列表 [a]
和一个 Int
,所以:
outcomes :: [a] -> Int -> [[a]]
如果整数小于或等于零,则只有一个可能的结果是空列表。所以我们 return 一个包含一个空列表的列表:
outcomes _ n | n <= 0 = [[]]
至于递归的情况,我们可以从列表中取出一个元素,然后使用相同的值列表进行递归,但是我们创建的结果少了一个元素,然后我们将我们取出的元素添加到这些结果中。
outcomes ls n = [ … | x < ls, xs <- … ]
这里我将 …
部分留作练习。在第一个 …
片段中,您需要在 xs
前面加上 x
。在第二个中,您需要进行递归调用。
因此,将其放在一起,我们将 outcomes
实现为:
outcomes :: [a] -> Int -> [[a]]
outcomes _ n | n <= 0 = [[]]
outcomes ls n = [ … | x < ls, xs <- … ]