列表编号半径验证

时间:2017-10-11 20:48:42

标签: haskell

我再一次需要你的专业知识,因为我缺乏经验,我发现自己在与Haskell挣扎。我有一个列表(不准确),我需要检查该列表中的数字,以便在半径为5的数字中没有,例如,我的列表中有数字300,我检查是否有'那里有295号和305号,如果还没有,那么300就会进入另一个列表(rInac)

dig :: Int -> [Int] 
dig 0 = []
dig n = dig (n `div` 10) ++ [n `mod` 10]

inac :: [Int]
inac = [x | x <- [1..999], x `mod` sum (dig x) == 0]

rInac :: [Int]
rInac = [x | x <- inac, rAux x]

rAux :: Int -> Bool 
rAux n = n `elem` inac

现在我只检查数字(n)是否属于列表,我的问题是,我不确定如何做5个半径的事情...... 提前谢谢!

2 个答案:

答案 0 :(得分:0)

您可以使用any函数来确定列表是否包含满足某个谓词的值。例如:

any odd [1,2,3,4]   -- True
any odd [2,4]       -- False

您所要做的就是创建一个谓词函数来确定数字是否位于半径5中:

rAux :: Int -> Bool 
rAux n = any isWithinFive inac
    where 
        isWithinFive x = x >= n-5 && x <= n+5

但是,这会产生一个 rInac列表。由于每个数字都在半径5范围内,因此该谓词将适用于inac列表中的每个数字。我怀疑你真正想要的是检查给定数字中5的数字是否存在,但不包括给定数字本身:

rAux :: Int -> Bool 
rAux n = any isWithinFive inac
    where 
        isWithinFive x = x /= n && x >= n-5 && x <= n+5

答案 1 :(得分:0)

假设您的列表已对有界类型(例如Int)进行排序,并且您觉得它的值永远不会接近边界(在64位计算机上大约+/- 2 ^ 63),以下代码应该是相当直观和高效(即,如果ghc优化器正在执行其工作,则在恒定空间中为O(n)):

gapped :: Int -> [Int] -> [Int]
gapped g a = map fst $ filter test $ zip a $ zip (minBound:a) (tail a ++ [maxBound])
  where
    test (x, (l, u)) = l+g < x && x < u-g

例如,使用您的其他代码,gapped 5 inac会产生:

  

[90,126,162,171,180,300,342,351,432,531,540,576,612,660,666,684,690,756,792,810,840,846,864,888,954,960,966,972,990,999]

这是你要找的答案吗?