哈斯克尔汉明数字

时间:2013-03-23 17:37:31

标签: haskell factors hamming-numbers

我需要定义唯一素数因子为2,3和5的汉明数字列表。 (即2 ^ i * 3 ^ j * 5 ^ k形式的数字。序列以1,2,3,4,5,6,8,9,10,12,15 ......开头)

我可以使用factors函数或其他方式执行此操作。下面的factors应该返回其参数的因子。我相信我已经正确实施了它。

   factors :: Int -> [Int]
   factors n = [x | x <- [1..(div n 2) ++ n], mod n x == 0]

我尝试使用列表推导制作2 ^ i * 3 ^ j * 5 ^ k的列表,但却一直坚持写守卫:

hamming :: [Int]
hamming = [n | n <- [1..], „where n is a member of helper“]

helper :: [Int]
helper = [2^i * 3^j * 5^k | i <- [0..], j <- [0..], k <- [0..]]

2 个答案:

答案 0 :(得分:11)

  

我可以使用factors函数或其他方式来完成。

我建议不这样做。

一种简单的方法是实现一个获得数字素数因子化的函数,然后就可以了

isHamming :: Integer -> Bool
isHamming n = all (< 7) $ primeFactors n

然后将用于过滤所有正整数的列表:

hammingNumbers :: [Integer]
hammingNumbers = filter isHamming [1 .. ]

另一种方法,更有效的是避免划分和过滤,并创建仅汉明数字的列表。

一种简单的方法是使用一个数字n是汉明数的事实,当且仅当

  • n == 1
  • n == 2*k,其中k是汉明号,或
  • n == 3*k,其中k是汉明号,或
  • n == 5*k,其中k是汉明号。

然后您可以创建所有汉明号码列表

hammingNumbers :: [Integer]
hammingNumbers = 1 : mergeUnique (map (2*) hammingNumbers)
                                 (mergeUnique (map (3*) hammingNumbers)
                                              (map (5*) hammingNumbers))

其中mergeUnique将两个已排序的列表合并在一起,删除重复项。

这已经相当有效了,但是it can be improved by avoiding producing duplicates from the beginning

答案 1 :(得分:2)

请注意,hamming设置为

{2^i*3^j*5^k | (i, j, k) ∈ T}

,其中

T = {(i, j, k) | i ∈ [0..], j ∈ [0..], k ∈ [0..]}

但我们不能使用[(i,j,k)| i&lt; - [0 ..],j&lt; - [0 ..],k&lt; - [0 ..]]。因为此列表以无限多个三元组开头,例如(0, 0, k) 鉴于任何(i,j,k)elem (i,j,k) T应在有限时间内返回True 听起来很熟悉?您可以回想一下之前提出的问题: haskell infinite list of incrementing pairs

在那个问题上,哈马尔给了答案。我们可以把它推广到三倍。

triples = [(i,j,t-i-j)| t <- [0..], i <- [0..t], j <- [0..t-i]]
hamming = [2^i*3^j*5^k | (i,j,k) <- triples]