二进制数的惰性列表,其中k为1

时间:2014-04-29 18:15:12

标签: list haskell binary lazy-evaluation

如何实现 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]之前。

3 个答案:

答案 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次(使用k0,然后使用k-11等,并++结果。

答案 2 :(得分:1)

以下是使用applicative functor的解决方案。

generate 0 = [[]]
generate k = (:) <$> [1,0] <*> generate (k-1)

我想知道如何表明这确实是懒惰的?