2015-07-01 160 views
1

我期待luhn 5594589764218858 = True但它始终是False卢恩算法实现

-- Get the last digit from a number 
lastDigit :: Integer -> Integer 
lastDigit 0 = 0 
lastDigit n = mod n 10 

-- Drop the last digit from a number 
dropLastDigit :: Integer -> Integer 
dropLastDigit n = div n 10 

toRevDigits :: Integer -> [Integer] 
toRevDigits n 
    | n <= 0 = [] 
    | otherwise = lastDigit n : toRevDigits (dropLastDigit n) 

-- Double every second number in a list starting on the left. 
doubleEveryOther :: [Integer] -> [Integer] 
doubleEveryOther []  = [] 
doubleEveryOther (x : []) = [x] 
doubleEveryOther (x : y : z) = x : (y * 2) : doubleEveryOther z 

-- Calculate the sum of all the digits in every Integer. 
sumDigits :: [Integer] -> Integer 
sumDigits []   = 0 
sumDigits (x : []) = x 
sumDigits (x : y)  = (lastDigit x) + (dropLastDigit x) + sumDigits y 

-- Validate a credit card number using the above functions. 
luhn :: Integer -> Bool 
luhn n 
    | sumDigits (doubleEveryOther (toRevDigits n)) `div` 10 == 0 = True 
    | otherwise             = False 

我知道这是可以做到容易,但我下面的一个Haskell introductory。我认为我唯一的问题是luhn函数。该课程提到的问题可能会发生,因为toRevDigits反转数字,但我认为它应该工作。

+1

我会建议为每个组件编写一些测试(如果你有一点时间,学习快速检查的好机会)。 – jberryman

+1

@BradyDean你的'sumDigits'函数是错误的。考虑这个例子。 'lastDigit 123'返回'3'。 'dropLastDigit 123'返回'12'。然而'3 + 12'不等于数字的总和('1 + 2 + 3')。 – Jubobs

+0

数字被分割。 'sumDigits [10,5,18,4] = 1 + 0 + 5 + 1 + 8 + 4 = 19'是我要去的 –

回答

1

该片段x `div` 10 == 0不是正确的检查,x可以被十整除;您应该使用`mod`。此外,该公式是不正确:

sumDigits (x : []) = x 

(尝试,例如sumDigits [10])。它可以是固定的,但删除它更简单,仍然是正确的。

+0

哇,我多次阅读代码,从未注意到这一点。代码正在与这些更改一起工作。 –

+1

@BradyDean以我的经验,你无法通过阅读代码来发现错误。我也没有在这种情况下,我在你的手工编写的例子中运行代码片断,看看它会做什么,以及是否符合我的预期,寻找与我的期望不符的最小功能。这是一个强大的技术,我鼓励你采用。 –

+0

是的,我在课程中给出了例子,但我没有太多的工作。 –