【问题标题】:Luhn algorithm in HaskellHaskell 中的 Luhn 算法
【发布时间】:2017-02-02 22:28:44
【问题描述】:

我想我已经在 Haskell 中正确计算了 Luhn algorithm

f1 :: Integer -> [Integer]
f1 x = if x < 10 then [x] else (f1 (div x 10))++[mod x 10]

f2 :: [Integer] -> [Integer]
f2 xs = [(!!) xs (x - 1) | x <- [1..(length xs)] , even x]

f3 :: [Integer] -> [Integer]
f3 xs = if mod (length xs) 2 /= 0 then (f2 xs) else (f2 (0:xs))

f4 :: [Integer] -> [Integer]
f4 xs = map (*2) (f3 xs)

f5 :: [Integer] -> [[Integer]]
f5 xs = map f1 xs

f6 :: [[Integer]] -> [Integer]
f6 [] = []
f6 (xs : xss) = xs++(f6 xss)

f7 :: [Integer] -> [Integer]
f7 xs = [(!!) xs (x - 1) | x <- [1..(length xs)] , odd x]

f8 :: [Integer] -> [Integer]
f8 xs = if mod (length xs) 2 /= 0 then (f7 xs) else (f7 (0:xs))

f9 :: [Integer] -> [Integer]
f9 xs = (f8 xs) ++ (f4 xs)

f :: Integer -> Integer
f x = sum (f6 (f5 (f9 xs)))
   where xs = f1 x

luhn :: Integer -> Bool
luhn x = if mod (f x) 10 == 0 then True else False

例如,

luhn 49927398716 ==> True
luhn 49927398717 ==> False

现在我必须创建一个新函数sigLuhn,这样,给定一个整数n,和luhn n == True,然后sigLuhn n 给出一个(或多个)数字,这样如果我们将数字添加到最后到n,那么新号码也验证了Luhn算法;如果luhn n == False 函数给出错误。例如,

sigLuhn 49927398716 ==> [8]

因为如果我们调用n = 49927398716 那么

luhn (10*n + 8) ==> True

80 中的最小整数。我的想法是下一个:

g1 :: Integer -> Integer
g1 x = div 10 x + 1

g2 :: Integer -> Integer -> Integer
g2 x y = x*(floor (10)^(g1 y)) + y

g3 :: Integer -> [Bool]
g3 x = [luhn (g2 x y) | y <- [1..]]

g4 :: [Bool] -> Int
g4 xs = minimum (elemIndices True xs)

g :: Integer -> Int
g x = g4 (g3 x)

sigLuhn :: Integer -> [Int]
sigLuhn x = if (luhn x) then [g x] else error "The conditions of Luhn's algorithm are not valid"

代码没有给出错误,但 sigLuhn 与此代码不正确。简而言之,如果我们假设函数luhn很好,你能帮我正确写sigLuhn吗?非常感谢。

【问题讨论】:

  • 1.如果你给你的函数提供更具描述性的名称,那将会有所帮助。很难说这里发生了什么。 2. 在假设第一部分基于几个测试工作之前,我会在继续之前做进一步的测试。我浪费了很多时间来排除检查一段代码的错误,因为我认为我已经彻底测试了它......但没有。
  • 抱歉,函数名称。我不得不把很多单词翻译成英文,我也忘了翻译函数的名称。
  • 好吧,老实说,我不知道 Luhn 算法是什么或者如何实现它,但是对于任何可以帮助你的人,你应该尽量让它尽可能简单为他们。
  • 我想在这里再说一遍,我几乎可以肯定luhn 是正确的。只有我要写得更好sigLuhn
  • 好吧,不幸的是,我帮不上那个忙。我会说通过检查每个辅助函数来开始调试,以确保它们返回您所期望的。

标签: haskell luhn


【解决方案1】:

我去年秋天把它分配在一个班级里。这是最好的解决方案之一。

doubleAndSum :: [Int] -> Int
doubleAndSum = fst . foldr (\i (acc, even) -> (acc + nextStep even i, not even)) (0,False)
  where 
    nextStep even i
        | even      = (uncurry (+) . (`divMod` 10) . (*2)) i
        | otherwise = i 

myLuhn :: Int -> Bool
myLuhn = (0 ==) . (`mod` 10) . doubleAndSum . (map (read . (: ""))) . show

testCC :: [Bool]
testCC = map myLuhn [49927398716, 49927398717, 1234567812345678, 1234567812345670]
-- => [True,False,False,True]

【讨论】:

  • 您应该解释您的更改。这是相当模糊的。
  • 你必须知道 Luhn 算法是做什么的。鉴于此, doubleAndSum 对数字求和,从右边加倍偶数。如果一个加倍的数字超过 9,这些数字也会相加。 myLuhn 将输入的 Int 转换为单位数 Int 的列表,在列表上调用 doubleAndSum,并根据 sum mod10 是否为 0 返回 True 或 False。
猜你喜欢
  • 1970-01-01
  • 2013-08-10
  • 1970-01-01
  • 2015-01-01
  • 2021-05-16
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多