用布尔值列出Haskell中的组合



所以,我最近开始学习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.

您可以在这里使用递归。我们可以构造一个函数,它接受一个包含元素[a]和一个元素Int的列表,因此:

outcomes :: [a] -> Int -> [[a]]

如果整数小于等于0,那么只有一个可能的结果:空列表。因此,返回一个包含一个空列表的列表:

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 <- … ]

因为你想让你的函数工作在任意数量的翻转n,它应该接受一个Int形参:否则你怎么得到一个Int?而且,正如评论中建议的那样,递归是在Haskell中做类似循环的事情的方式,因此您将需要一个基本情况和一个递归情况。对于计数,0是一个自然的基础情况,也是这里使用的最佳情况,但是使用1作为基础情况对于初学者来说更容易理解,所以我们现在只让n=0的函数中断。

因此,您需要一个具有两种模式的函数:
outcomes :: Int -> [[Bool]]
outcomes 1 = _
outcomes n = _

1的结果应该是什么,即一次翻转?一旦你有了这个,你能在outcomes (n - 1)的基础上实现outcomes n吗?如果是这样,你就完蛋了。如果没有,你会有更好的材料来做新问题,因为你已经得到了解决方案的一半。

作为额外的学分,一旦这样做了,看看你是否能很好地理解递归,为outcomes 0选择一个好的值,可以代替outcomes 1作为你的基本情况。

最新更新