Skip to content

Commit

Permalink
Sync Luhn with problem specifications (#199)
Browse files Browse the repository at this point in the history
  • Loading branch information
kahgoh authored Feb 22, 2024
1 parent bb71601 commit 70c2852
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 34 deletions.
3 changes: 2 additions & 1 deletion exercises/practice/luhn/.meta/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"contributors": [
"adolfopa",
"etrepum",
"yurrriq"
"yurrriq",
"kahgoh"
],
"files": {
"solution": [
Expand Down
48 changes: 25 additions & 23 deletions exercises/practice/luhn/.meta/example.lfe
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
(defmodule luhn
(export (valid? 1)
(create 1)
(checksum 1)))
(export (valid? 1))
)

(defun valid? (number) (== (rem (checksum number) 10) 0))
(defun valid? (number)
(case (checksum (lists:reverse number) 0 0)
((tuple 'ok count total) (when (> count 1)) (== (rem total 10) 0))
(_ 'false)
)
)

(defun create (number)
(lists:flatten `(,number ,(- #\: (rem (checksum (++ number "0")) 10)))))
(defun checksum
(('() count total) (tuple 'ok count total))
(((cons 32 reversed-number) count total) (checksum reversed-number count total))
(((cons h reversed-number) count total)
(when (=< #\0 h) (=< h #\9))
(checksum reversed-number
(+ count 1)
(+ total (number-to-add count (- h #\0)))
)
)
((_ count total) (tuple 'invalid count total))
)

(defun checksum (number)
(checksum
(lists:reverse
(lists:filter
(lambda (c)
(=< #\0 c #\9))
number))
'odd
0))
(defun number-to-add
((count digit) (when (== (rem count 2) 0)) digit)
((_ digit) (when (< digit 5)) (* digit 2))
((_ digit) (- (* digit 2) 9))
)

(defun checksum
([() _ total] total)
([(cons h reversed-number) 'odd total]
(checksum reversed-number 'even (- (+ total h) #\0)))
([(cons h reversed-number) 'even total] (when (< h #\5))
(checksum reversed-number 'odd (+ total (* (- h #\0) 2))))
([(cons h reversed-number) 'even total] (when (>= h #\5))
(checksum reversed-number 'odd (- (+ total (* (- h #\0) 2)) 9))))
9 changes: 9 additions & 0 deletions exercises/practice/luhn/.meta/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ description = "invalid credit card"
[20e67fad-2121-43ed-99a8-14b5b856adb9]
description = "invalid long number with an even remainder"

[7e7c9fc1-d994-457c-811e-d390d52fba5e]
description = "invalid long number with a remainder divisible by 5"

[ad2a0c5f-84ed-4e5b-95da-6011d6f4f0aa]
description = "valid number with an even number of digits"

Expand All @@ -57,6 +60,12 @@ description = "more than a single zero is valid"
[ab56fa80-5de8-4735-8a4a-14dae588663e]
description = "input digit 9 is correctly converted to output digit 9"

[b9887ee8-8337-46c5-bc45-3bcab51bc36f]
description = "very long input is valid"

[8a7c0e24-85ea-4154-9cf1-c2db90eabc08]
description = "valid luhn with an odd number of digits and non zero first digit"

[39a06a5a-5bad-4e0f-b215-b042d46209b1]
description = "using ascii value for non-doubled non-digit isn't allowed"

Expand Down
2 changes: 1 addition & 1 deletion exercises/practice/luhn/src/luhn.app.src
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
%% -*- erlang -*-
{application, 'luhn',
[{description, ""},
[{description, "Given a number determine whether or not it is valid per the Luhn formula."},
{vsn, "0.0.1"},
{modules,
['luhn']},
Expand Down
5 changes: 5 additions & 0 deletions exercises/practice/luhn/src/luhn.lfe
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(defmodule luhn
(export (valid? 1))
)

; Please implement the `valid?` function.
72 changes: 63 additions & 9 deletions exercises/practice/luhn/test/luhn-tests.lfe
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,68 @@

(include-lib "ltest/include/ltest-macros.lfe")

(deftest invalid
(is-not (luhn:valid? "1111"))
(is-not (luhn:valid? "738")))
(deftest single-digit-strings-can-not-be-valid
(is-not (luhn:valid? "1")))

(deftest valid
(is (luhn:valid? "8739567"))
(is (luhn:valid? "8763"))
(is (luhn:valid? "2323 2005 7766 3554")))
(deftest a-single-zero-is-invalid
(is-not (luhn:valid? "0")))

(deftest create
(is-equal "2323 2005 7766 3554" (luhn:create "2323 2005 7766 355")))
(deftest a-simple-valid-SIN-that-remains-valid-reversed
(is (luhn:valid? "059")))

(deftest a-simple-valid-SIN-that-becomes-invalid-if-reversed
(is (luhn:valid? "59")))

(deftest a-valid-Canadian-SIN
(is (luhn:valid? "055 444 285")))

(deftest invalid-Canadian-SIN
(is-not (luhn:valid? "055 444 286")))

(deftest invalid-credit-card
(is-not (luhn:valid? "8273 1232 7352 0569")))

(deftest invalid-long-number-with-an-even-remainder
(is-not (luhn:valid? "1 2345 6789 1234 5678 9012")))

(deftest invalid-long-with-a-remainder-divisible-by-5
(is-not (luhn:valid? "1 2345 6789 1234 5678 9013")))

(deftest valid-number-with-an-even-number-of-digits
(is (luhn:valid? "095 245 88")))

(deftest valid-number-with-an-odd-number-of-spaces
(is (luhn:valid? "234 567 891 234")))

(deftest valid-strings-with-a-non-digit-added-at-the-end-become-invalid
(is-not (luhn:valid? "059a")))

(deftest valid-strings-with-punctuation-included-become-invalid
(is-not (luhn:valid? "055-444-285")))

(deftest valid-strings-with-symbols-included-become-invalid
(is-not (luhn:valid? "055# 444$ 285")))

(deftest single-zero-with-space-is-invalid
(is-not (luhn:valid? " 0")))

(deftest more-than-a-single-zero-is-valid
(is (luhn:valid? "0000 0")))

(deftest input-digit-9-is-correctly-converted-to-output-digit-9
(is (luhn:valid? "091")))

(deftest very-long-input-is-valid
(is (luhn:valid? "9999999999 9999999999 9999999999 9999999999")))

(deftest valid-luhn-with-an-odd-number-of-digits-and-non-zero-first-digit
(is (luhn:valid? "109")))

(deftest using-ascii-value-for-non-doubled-non-digit-isnt-allowed
(is-not (luhn:valid? "055b 444 285")))

(deftest using-ascii-value-for-doubled-non-digit-isnt-allowed
(is-not (luhn:valid? ":9")))

(deftest non-numeric-non-space-char-in-the-middle-with-a-sum-thats-divisible-by-10-isnt-allowed
(is-not (luhn:valid? "59%59")))

0 comments on commit 70c2852

Please sign in to comment.