首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell中的Luhn算法

Haskell中的Luhn算法
EN

Stack Overflow用户
提问于 2017-02-03 06:28:44
回答 1查看 1.2K关注 0票数 0

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

代码语言:javascript
复制
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

例如,

代码语言:javascript
复制
luhn 49927398716 ==> True
luhn 49927398717 ==> False

现在我必须创建一个新的函数sigLuhn,在给定一个整数n的情况下,使用luhn n == True,然后sigLuhn n给出数字,这样如果我们将数字加到最后的数字到n,那么新的数字也会验证Luhn算法;如果是luhn n == False,函数会给出一个错误。例如,

代码语言:javascript
复制
sigLuhn 49927398716 ==> [8]

因为如果我们调用n = 49927398716

代码语言:javascript
复制
luhn (10*n + 8) ==> True

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

代码语言:javascript
复制
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吗?非常感谢。

EN

回答 1

Stack Overflow用户

发布于 2017-02-03 10:25:20

我是去年秋天在班上布置的。这是最好的解决方案之一。

代码语言:javascript
复制
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]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42013519

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档