如何实现 k 一个和 0 零的列表列表,列表 k-1 一个和 1 零,...,列出 0 和 k 零,以便可以懒惰地检索它们?
例如,如果 k = 3:
generate_list 3 = [[1,1,1],[0,1,1],[1,0,1],[1,1,0],[0,0,1],[0,1,0],[1,0,0],[0,0,0]]
感谢bheklilr提供建议。这是我的解决方案:
generate k = take (2^k) $ foldl (\x y -> zipWith (:) y x) (map (\x->[x]) (head rows)) (tail rows)
where
rows = map cycle $ map pattern [0..k-1]
pattern i = replicate (2^i) 1 ++ replicate (2^i) 0
但是有一个问题:
generate_list 3 = [[1,1,1], [0,1,1], [1,0,1], [1,1,0], [0,0,1], [0,1,0], [1,0,0], [0,0,0]]
generate 3 = [[1,1,1], [1,1,0], [1,0,1], [1,0,0], [0,1,1], [0,1,0], [0,0,1], [0,0,0]]
generate 3 !! 3 = [1,0,0] - it contains 1 one
generate_list 3 !! 3 = [1,1,0] - it contain 2 one
因此,对于generate_list
输出顺序中的任务顺序非常重要,[1,1,0]
必须在[1,0,0]
之前。
答案 0 :(得分:1)
使用Data.List
中的一些功能,这很容易解决。我会指出你的功能可能正在产生
[[1,1,1], [1,1,0], [1,0,1], [1,0,0], [0,1,1], [0,1,0], [0,0,1], [0,0,0]]
相反,它遵循模式和自然顺序。
此问题有两个部分,生成具有一定重复次数的交替1和0的列表(即[0, 1, 0, 1, ..]
,[0, 0, 1, 1, 0, 0, 1, 1, ..]
等),然后正确地将它们连接在一起。
对于第一个问题,replicate
函数非常方便。您可以使用
replicate (2^i) 0 ++ replicate (2^i) 1
2^i
是重复数字的位数,因此对于i = 0
,这将输出[0, 1]
,而对于i = 3
,它将输出[0, 0, 0, 0, 1, 1, 1, 1]
。
Data.List
中有一个函数会将此基本模式转换为无限流,反复重复,您必须自己找到它(提示:它具有类型签名{{ 1}}和hoogle)。由于该函数会生成无限列表,因此您必须使用[a] -> [a]
将其修剪为大小,其中take ???
是要修剪的长度。有了这个,你应该能够生成[真值表]的每一列,但从0开始,而你希望它从1开始。你能弄清楚如何首先生成它们吗?
既然你有一段代码来生成每一列,那么你需要一个函数来解决问题" zip"每列都在一起,但内置的???
函数在这里不起作用,因为它们一次只能在特定数量的列表上运行。是否有其他可以使用的功能,可以描述为n路拉链?
这应该可以让你开始,但是你需要填补几个空白。如果你再次陷入困境,只需评论并说出你所坚持的内容,但你真的应该尽可能自己解决这个问题。
答案 1 :(得分:1)
如何实现一个列表,其中k为1 0和0,列表为k-1 1和1 0,...,列表为0一,k在Haskell中为零,以便可以懒惰地检索它们? / p>
编写一个函数,用于创建包含m
个和n
个零的列表列表。然后调用此函数k
次(使用k
和0
,然后使用k-1
和1
等,并++
结果。
答案 2 :(得分:1)
以下是使用applicative functor的解决方案。
generate 0 = [[]]
generate k = (:) <$> [1,0] <*> generate (k-1)
我想知道如何表明这确实是懒惰的?