我正在寻找一种方法来做这样的事情。 假设我们从1开始。对于每个数字奇数,我们将它+5添加到列表的末尾。对于每个偶数,我们将它添加+3,将+7添加到列表的末尾。列表看起来像这样
[1,6,9,13,14,18,17,21,21,25,......]
我如何在Haskell中做这样的事情?
我知道你可以列出一个列表,其中每个元素都依赖于前面的元素,但是当多个元素依赖于同一个元素时你是如何做到的,并且你不知道哪个组取决于哪个元素除非你从头开始?
答案 0 :(得分:13)
以下解决方案使用自引用惰性列表,因此@GaneshSittampalam没有解决方案的线性时间问题:
xs = 1 : concatMap extras xs where
extras x
| odd x = [x+5]
| otherwise = [x+3,x+7]
答案 1 :(得分:7)
如果一次只生成一个元素,那么它与您的操作方式非常相似。在这种情况下,您将传递单个值以跟踪下一个元素的“种子”。在这种情况下,您只需传下一个列表:
xs = process [1]
-- notice no [] case as we don't expect it to be needed
process (n:ns) = n:process (ns ++ extras)
where
extras
| n `mod` 2 == 0 = [n+3, n+7]
| otherwise = [n+5]
一般的想法是process
的参数包含我们知道应该在输出列表中的所有数字,但是我们还没有添加“结果”数字。为了取得进展,我们检查其中的第一个,通过将其置于结果的头部来“输出”它,并计算随后的数字并将它们放入等待处理的列表中。通过将它们放在最后,我们确保一切都可以转变,可以这么说。
请注意,使用naive list concatenation将它们放在最后意味着此算法在技术上会花费线性时间来通过列表生成下一个数字。这可以通过使用更有效的数据结构来处理,例如Data.Sequence。
答案 2 :(得分:0)
我的Haskell很糟糕,所以这里是假代码的大纲。
你可以使用过滤器。
请注意,对于任何奇数:2x + 1
您将在列表中添加2x + 6
永远偶数:2x
你将添加2x + 3和2x + 7
这样:
filter (f) naturalNumbers
where f(x) :
true if (x-7) % 2 == 0
true if (x-6) % 2 == 0
true if (x-3) % 2 == 0
false otherwise