Credit card problem from Chapter 01

This commit is contained in:
Logan McGrath 2021-08-12 15:56:01 -07:00
parent 82667ad5f8
commit a71926c399
4 changed files with 104 additions and 0 deletions

10
hie.yaml Normal file
View File

@ -0,0 +1,10 @@
cradle:
stack:
- path: "lib"
component: "homework:lib"
- path: "app"
component: "homework:exe"
- path: "test"
component: "homework:test"

View File

@ -23,6 +23,7 @@ source-repository head
library library
exposed-modules: exposed-modules:
Homework Homework
Homework.Ch01
other-modules: other-modules:
Paths_homework Paths_homework
hs-source-dirs: hs-source-dirs:
@ -48,6 +49,7 @@ test-suite test
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0
main-is: Spec.hs main-is: Spec.hs
other-modules: other-modules:
Homework.Ch01Spec
Paths_homework Paths_homework
hs-source-dirs: hs-source-dirs:
test test

39
lib/Homework/Ch01.hs Normal file
View File

@ -0,0 +1,39 @@
module Homework.Ch01 where
-- This calls reverse on toDigitsRev because I somehow did this backwards by default.
toDigits :: Integer -> [Integer]
toDigits = rev [] . toDigitsRev
where
rev acc (x : xs) = rev (x : acc) xs
rev acc [] = acc
-- I don't know how I managed it, but turning the number into an array already reversed it?
toDigitsRev :: Integer -> [Integer]
toDigitsRev n
| n < 1 = []
| otherwise =
let leftDigit = n `mod` 10
shiftedDigits = n `div` 10
in leftDigit : toDigitsRev shiftedDigits
doubleEveryOther :: [Integer] -> [Integer]
doubleEveryOther (odd' : even' : rest) = odd' : (even' * 2) : doubleEveryOther rest
doubleEveryOther rest = rest
sumDigits :: [Integer] -> Integer
sumDigits = sumDigits' 0 . flattenDigits [] . eachToDigits []
where
eachToDigits acc (x : xs) = eachToDigits (toDigits x : acc) xs
eachToDigits acc [] = acc
flattenDigits acc ((x : xs) : rest) = flattenDigits (x : acc) (xs : rest)
flattenDigits acc ([] : rest) = flattenDigits acc rest
flattenDigits acc [] = acc
sumDigits' acc (x : xs) = sumDigits' (acc + x) xs
sumDigits' acc [] = acc
validate :: Integer -> Bool
validate n = f n `mod` 10 == 0
where
f = sumDigits . doubleEveryOther . toDigitsRev

53
test/Homework/Ch01Spec.hs Normal file
View File

@ -0,0 +1,53 @@
module Homework.Ch01Spec where
import Homework.Ch01
import Test.Hspec
spec :: Spec
spec = describe "Credit Card Validation" $ do
describe "toDigits" $ do
context "n is less than 1" $ do
it "returns an empty list" $ do
toDigits 0 `shouldBe` []
context "n contains a single digit" $ do
it "creates a list with one digit" $ do
toDigits 9 `shouldBe` [9]
context "n contains more than one digit" $ do
it "creates a list of digits" $ do
toDigits 12345 `shouldBe` [1, 2, 3, 4, 5]
describe "toDigitsRev" $ do
context "n is less than 1" $ do
it "returns an empty list" $ do
toDigitsRev 0 `shouldBe` []
context "n contains a single digit" $ do
it "creates a list with one digit" $ do
toDigitsRev 9 `shouldBe` [9]
context "n contains more than one digit" $ do
it "creates a list of the digits in reverse order" $ do
toDigitsRev 12345 `shouldBe` [5, 4, 3, 2, 1]
describe "doubleEveryOther" $ do
context "list length is odd" $ do
it "does not double the last digit" $ do
doubleEveryOther [1, 2, 3, 4, 5] `shouldBe` [1, 4, 3, 8, 5]
context "list length is even" $ do
it "doubles every other digit" $ do
doubleEveryOther [1, 2, 3, 4, 5, 6] `shouldBe` [1, 4, 3, 8, 5, 12]
describe "sumDigits" $ do
it "splits doubled digits into single digits and sums all single digits together" $ do
sumDigits [16, 7, 12, 5] `shouldBe` 22
describe "validate" $ do
it "returns True for a valid credit card number" $ do
validate 5105105105105100 `shouldBe` True
validate 2223577120017656 `shouldBe` True
it "returns False for invalid credit card number" $ do
validate 5105105105105101 `shouldBe` False
validate 2223573420017656 `shouldBe` False