2017-02-02 16 views
0

Я думаю, что я правильно вычислить Luhn algorithm в Haskell:Лун алгоритм в Haskell

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 n == False функция дает ошибку. Например,

sigLuhn 49927398716 ==> [8] 

, потому что если мы называем n = 49927398716 то

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

8 быть самым низким число от 0. Моя мысль следующая:

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? Большое спасибо.

+2

1. Это поможет, если вы предоставили своим функциям более описательные имена. Трудно сказать, что здесь происходит. 2. Прежде чем приступить к работе над первой частью, основанной на двух тестах, я продолжу тестирование перед тем, как продолжить. Я потратил много времени, исключая проверку фрагмента кода для ошибки, потому что я думал, что полностью его протестировал ... и не сделал этого. – Carcigenicate

+0

Извините, имя функции. Мне пришлось перевести на английский много слов, и я тоже забыл перевести название функций. – joseabp91

+0

Ну, честно говоря, я не знаю, что такое алгоритм Луна или как его реализовать, но для тех, кто может помочь вам в этом, вы должны попытаться сделать это как можно проще для них. – Carcigenicate

ответ

0

Я назначил его в классе прошлой осенью. Вот одно из лучших решений.

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] 
+0

Вы должны объяснить свои изменения. Это довольно расплывчато, как есть. – Carcigenicate

+0

Вы должны знать, что делает алгоритм Луна. Учитывая, что doubleAndSum суммирует цифры, удваивая четную цифру справа. Если удвоенная цифра превышает 9, эти цифры также суммируются. myLuhn преобразует вход Int в список одноразрядных Ints, вызывает doubleAndSum в списке и возвращает True или False в зависимости от того, является ли сумма mod10 равной 0. – RussAbbott