本文介绍了无限制的汉明序列中的最新技术的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! (这很令人兴奋!)我知道,题材是众所周知的。最先进的技术(在Haskell以及其他语言中)用于高效生成无限增加的汉明数字序列,无重复和无遗漏,长期以来一直如下(AFAIK - 顺便说一句,它相当于 original Edsger Dijkstra's code ) : hamm :: [Integer] hamm = 1:map(2 *)hamm`union` map 3 *)hamm`union` map(5 *)hamm 其中 union a @(x:xs)b @(y:ys)= case LT - > x:联合xs b EQ - > x:union xs ys GT - > y:union a ys 我问的问题是,你能找到方法吗?使其更有效率在任何重大措施?它仍然是最先进的,或者事实上有可能改善这一点,以便更快地运行 并且更好 经验增长点开机? 如果您的答案是是,请显示代码并讨论它的速度和经验增长顺序与上述相比(它运行在对于前几十万个数字产生的〜n ^ 1.05 .. n ^ 1.10 )。另外,如果它存在,这个高效的算法可以扩展到用任何给定的素数集合生成一个平滑数字序列吗? 解析方案如果一个常数因子加速计数显着,那么我可以提供更加高效的版本: hamm :: [Integer] hamm = mrg1 hamm3(map(2 *)hamm)其中 hamm5 =迭代(5 *)1 hamm3 = mrg1 hamm5(map(3 *)hamm3)合并@(x:xs)b @(y:ys) | x |否则= y:合并ys mrg1(x:xs)ys = x:合并xs ys 您可以很容易地推广它以平滑给定素数组的数字: hamm :: [Integer] - > ; [Integer] hamm [] = [1] hamm [p] = iterate(p *)1 hamm ps = foldl'next(iterate(q *)1)qs 其中(q:qs)= sortBy(反转比较)ps 下一步prev m = let res = mrg1 prev(map(m *)res)res merge a @ x:xs)b @(y:ys) | x |否则= y:合并ys mrg1(x:xs)ys = x:合并xs ys 效率更高,因为该算法不会产生任何重复,并且使用更少的内存。在你的版本中,当产生 h 附近的汉明数字时, h / 5 和 h 必须在内存中。在我的版本中,只有完整列表中 h / 2 和 h 之间的部分以及 h / 3 和 h 需要在内存中。由于3-5列表非常稀疏,并且k-平滑数字的密度减少,所以这两个列表部分需要的内存少得多,完整列表的大部分都是。 这两种算法的一些时间生成 k 好吧,它看起来不变,我认为这两个变体都有相同的计算复杂性,但我还没有拿出铅笔和纸张来证明这一点,也没有打算这样做。 (this is exciting!) I know, the subject matter is well known. The state of the art (in Haskell as well as other languages) for efficient generation of unbounded increasing sequence of Hamming numbers, without duplicates and without omissions, has long been the following (AFAIK - and btw it is equivalent to the original Edsger Dijkstra's code too):hamm :: [Integer]hamm = 1 : map (2*) hamm `union` map (3*) hamm `union` map (5*) hamm where union a@(x:xs) b@(y:ys) = case compare x y of LT -> x : union xs b EQ -> x : union xs ys GT -> y : union a ysThe question I'm asking is, can you find the way to make it more efficient in any significant measure? Is it still the state of the art or is it in fact possible to improve this to run twice faster and with better empirical orders of growth to boot?If your answer is yes, please show the code and discuss its speed and empirical orders of growth in comparison to the above (it runs at about ~ n^1.05 .. n^1.10 for first few hundreds of thousands of numbers produced). Also, if it exists, can this efficient algorithm be extended to producing a sequence of smooth numbers with any given set of primes? 解决方案 If a constant factor speedup counts as significant, then I can offer a significantly more efficient version:hamm :: [Integer]hamm = mrg1 hamm3 (map (2*) hamm) where hamm5 = iterate (5*) 1 hamm3 = mrg1 hamm5 (map (3*) hamm3) merge a@(x:xs) b@(y:ys) | x < y = x : merge xs b | otherwise = y : merge a ys mrg1 (x:xs) ys = x : merge xs ysYou can easily generalise it to smooth numbers for a given set of primes:hamm :: [Integer] -> [Integer]hamm [] = [1]hamm [p] = iterate (p*) 1hamm ps = foldl' next (iterate (q*) 1) qs where (q:qs) = sortBy (flip compare) ps next prev m = let res = mrg1 prev (map (m*) res) in res merge a@(x:xs) b@(y:ys) | x < y = x : merge xs b | otherwise = y : merge a ys mrg1 (x:xs) ys = x : merge xs ysIt's more efficient because that algorithm doesn't produce any duplicates and it uses less memory. In your version, when a Hamming number near h is produced, the part of the list between h/5 and h has to be in memory. In my version, only the part between h/2 and h of the full list, and the part between h/3 and h of the 3-5-list needs to be in memory. Since the 3-5-list is much sparser, and the density of k-smooth numbers decreases, those two list parts need much less memory that the larger part of the full list.Some timings for the two algorithms to produce the k Hamming number, with empirical complexity of each target relative to the previous, excluding and including GC time: k Yours (MUT/GC) Mine (MUT/GC) 10^5 0.03/0.01 0.01/0.01 -- too short to say much, really2*10^5 0.07/0.02 0.02/0.015*10^5 0.17/0.06 0.968 1.024 0.06/0.04 1.199 1.314 10^6 0.36/0.13 1.082 1.091 0.11/0.10 0.874 1.0702*10^6 0.77/0.27 1.097 1.086 0.21/0.21 0.933 1.0005*10^6 1.96/0.71 1.020 1.029 0.55/0.59 1.051 1.090 10^7 4.05/1.45 1.047 1.043 1.14/1.25 1.052 1.0682*10^7 8.73/2.99 1.108 1.091 2.31/2.65 1.019 1.0535*10^7 21.53/7.83 0.985 1.002 6.01/7.05 1.044 1.057 10^8 45.83/16.79 1.090 1.093 12.42/15.26 1.047 1.084As you can see, the factor between the MUT times is about 3.5, but the GC time is not much different. Well, it looks constant, and I think both variants have the same computational complexity, but I haven't pulled out pencil and paper to prove it, nor do I intend to. 这篇关于无限制的汉明序列中的最新技术的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-12 09:43