无限计数器的无限列表

Posted

技术标签:

【中文标题】无限计数器的无限列表【英文标题】:Infinite list of infinite counters 【发布时间】:2012-02-04 12:12:29 【问题描述】:

对于那些心存疑虑的人,这不是功课,只是好奇。

给定一个有限的字母表,是否有可能构造一个无限长的单词列表?

即给定字母"ab"

是否可以构造列表:

["aaaaaa...", "baaaaa...", "abaaaa...", "bbaaaa...", "aabaaa...", ...]

其中... 表示无限长的列表(和列表的列表)。

一个天真的尝试是:

counters alphabet = [c:ounter | ounter <- counters alphabet, c <- alphabet]

但这不起作用,因为它是递归的。

当然,在工作版本中,如果您尝试打印结果,您只会看到第一个元素被打印为字母表中第一个元素的无限列表。但是,您应该可以这样做:

mapM_ (print . take 2) . take 4 . counters $ "ab"

并查看输出:

aa
ba
ab
bb

【问题讨论】:

你知道有无数个单词,所以列表不会包括所有这些? 是的,但是您在问题中写了“所有无限长的单词”;这不是全部,只有从某个角度由“a”组成的那些。 如果您只对延伸到aaa... 的字符串感到满意,那么为什么不直接生成所有有限词并添加aaa... @redxaxder 我试过了。有许多令人讨厌的特殊情况,因为序列"", "a", "aa", "aaa", ... 中的所有有限词都会产生相同的无限词。我没有同时找到一个相当优雅(少数特殊情况)和相当高效(例如不使用nub)的解决方案。 @redxaxder,抱歉这么慢。我将有限长度与固定长度混淆了。是的,我明白你现在在说什么。谢谢。 【参考方案1】:

为什么不fix呢?

ghci> let bar = let foo ~(st:sts) = [c:st | c <- "ab"] ++ foo sts in fix foo
ghci> take 5 . map (take 5) $ bar
["aaaaa","baaaa","abaaa","bbaaa","aabaa"]
take 10 . map (take 5) $ bar
["aaaaa","baaaa","abaaa","bbaaa","aabaa","babaa","abbaa","bbbaa","aaaba","baaba"]

【讨论】:

甜蜜!我开始意识到需要惰性模式,因为无法确定结果是否为非空。【参考方案2】:

可能不是最有效的解决方案,但至少它有效:

counters alphabet = map f [0..]
  where f n = let (q, r) = quotRem n (length alphabet) in alphabet !! r : f q
> take 10 $ map (take 5) $ counters "ab"
["aaaaa","baaaa","abaaa","bbaaa","aabaa","babaa","abbaa","bbbaa","aaaba","baaba"]

【讨论】:

【参考方案3】:

您可能会发现以下方法很有趣/令人困惑:

duplicates s ss = cycle ss : duplicates s (ss >>= \c -> s >> [c])
counters = transpose . join duplicates

这来自于观察到第一个字母遵循模式"ababab...",第二个字母遵循模式"aabbaabbaabb...",第三个字母遵循模式"aaaabbbbaaaabbbb...",等等。

【讨论】:

【参考方案4】:

这个呢?

f@(a:as) = a:('b':a):concatMap (\x -> ['a':x,'b':x]) as where a = ['a','a'..]

如果您认为(\x -&gt; ['a':x,'b':x]) 更优雅,也可以将Applicative 写成([('a':),('b':)] &lt;*&gt;) . pure

【讨论】:

【参考方案5】:

进程看起来像是用左边的最低有效位编码一个以 N 为底的数字,所以我们可以将其处理为

    使用您的字母作为字母,创建一个“以 N 为基数”的函数fmap f[0..]repeat $ head alphabets 附加到列表的每个元素。

【讨论】:

【参考方案6】:

基于丹尼尔的想法的另一个版本:

counters = transpose $ map cycle $ iterate (>>= \x -> [x,x]) "ab"

【讨论】:

喜欢简单!从任何字母表生成单词的好方法!对于任何想知道的人,(&gt;&gt;= \x -&gt; [x,x]) 等于 concat . map (\x -&gt; [x,x]) 用于列表。因此,复杂性也是最佳的。

以上是关于无限计数器的无限列表的主要内容,如果未能解决你的问题,请参考以下文章

动画迭代计数无限循环

使用 Icarus Verilog 模拟程序计数器设计时的无限循环

为啥这会导致无限循环

简单的例子进入无限循环

玩笑无限期挂起,不运行任何测试

025 程序的循环结构