-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*.beam | ||
*.ez | ||
build | ||
erl_crash.dump |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Help | ||
|
||
## Running the tests | ||
|
||
To run the tests, run the command `gleam test` from within the exercise directory. | ||
|
||
## Submitting your solution | ||
|
||
You can submit your solution using the `exercism submit src/luhn.gleam` command. | ||
This command will upload your solution to the Exercism website and print the solution page's URL. | ||
|
||
It's possible to submit an incomplete solution which allows you to: | ||
|
||
- See how others have completed the exercise | ||
- Request help from a mentor | ||
|
||
## Need to get help? | ||
|
||
If you'd like help solving the exercise, check the following pages: | ||
|
||
- The [Gleam track's documentation](https://exercism.org/docs/tracks/gleam) | ||
- The [Gleam track's programming category on the forum](https://forum.exercism.org/c/programming/gleam) | ||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) | ||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) | ||
|
||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. | ||
|
||
To get help if you're having trouble, you can use one of the following resources: | ||
|
||
- [gleam.run](https://gleam.run/documentation/) is the gleam official documentation. | ||
- [Discord](https://discord.gg/Fm8Pwmy) is the discord channel. | ||
- [StackOverflow](https://stackoverflow.com/questions/tagged/gleam) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# Luhn | ||
|
||
Welcome to Luhn on Exercism's Gleam Track. | ||
If you need help running the tests or submitting your code, check out `HELP.md`. | ||
|
||
## Instructions | ||
|
||
Given a number determine whether or not it is valid per the Luhn formula. | ||
|
||
The [Luhn algorithm][luhn] is a simple checksum formula used to validate a variety of identification numbers, such as credit card numbers and Canadian Social Insurance Numbers. | ||
|
||
The task is to check if a given string is valid. | ||
|
||
## Validating a Number | ||
|
||
Strings of length 1 or less are not valid. | ||
Spaces are allowed in the input, but they should be stripped before checking. | ||
All other non-digit characters are disallowed. | ||
|
||
### Example 1: valid credit card number | ||
|
||
```text | ||
4539 3195 0343 6467 | ||
``` | ||
|
||
The first step of the Luhn algorithm is to double every second digit, starting from the right. | ||
We will be doubling | ||
|
||
```text | ||
4_3_ 3_9_ 0_4_ 6_6_ | ||
``` | ||
|
||
If doubling the number results in a number greater than 9 then subtract 9 from the product. | ||
The results of our doubling: | ||
|
||
```text | ||
8569 6195 0383 3437 | ||
``` | ||
|
||
Then sum all of the digits: | ||
|
||
```text | ||
8+5+6+9+6+1+9+5+0+3+8+3+3+4+3+7 = 80 | ||
``` | ||
|
||
If the sum is evenly divisible by 10, then the number is valid. | ||
This number is valid! | ||
|
||
### Example 2: invalid credit card number | ||
|
||
```text | ||
8273 1232 7352 0569 | ||
``` | ||
|
||
Double the second digits, starting from the right | ||
|
||
```text | ||
7253 2262 5312 0539 | ||
``` | ||
|
||
Sum the digits | ||
|
||
```text | ||
7+2+5+3+2+2+6+2+5+3+1+2+0+5+3+9 = 57 | ||
``` | ||
|
||
57 is not evenly divisible by 10, so this number is not valid. | ||
|
||
[luhn]: https://en.wikipedia.org/wiki/Luhn_algorithm | ||
|
||
## Source | ||
|
||
### Created by | ||
|
||
- @natanaelsirqueira | ||
|
||
### Based on | ||
|
||
The Luhn Algorithm on Wikipedia - https://en.wikipedia.org/wiki/Luhn_algorithm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
name = "luhn" | ||
version = "0.1.0" | ||
|
||
[dependencies] | ||
gleam_bitwise = "~> 1.2" | ||
gleam_otp = "~> 0.7 or ~> 1.0" | ||
gleam_stdlib = "~> 0.32 or ~> 1.0" | ||
simplifile = "~> 1.0" | ||
gleam_erlang = ">= 0.25.0 and < 1.0.0" | ||
|
||
[dev-dependencies] | ||
exercism_test_runner = "~> 1.4" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# This file was generated by Gleam | ||
# You typically do not need to edit this file | ||
|
||
packages = [ | ||
{ name = "argv", version = "1.0.1", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "A6E9009E50BBE863EB37D963E4315398D41A3D87D0075480FC244125808F964A" }, | ||
{ name = "exercism_test_runner", version = "1.7.0", build_tools = ["gleam"], requirements = ["argv", "gap", "glance", "gleam_community_ansi", "gleam_erlang", "gleam_json", "gleam_stdlib", "simplifile"], otp_app = "exercism_test_runner", source = "hex", outer_checksum = "2FC1BADB19BEC2AE77BFD2D3A606A014C85412A7B874CAFC4BA8CF04B0B257CD" }, | ||
{ name = "gap", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_stdlib"], otp_app = "gap", source = "hex", outer_checksum = "2EE1B0A17E85CF73A0C1D29DA315A2699117A8F549C8E8D89FA8261BE41EDEB1" }, | ||
{ name = "glance", version = "0.8.2", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "ACF09457E8B564AD7A0D823DAFDD326F58263C01ACB0D432A9BEFDEDD1DA8E73" }, | ||
{ name = "gleam_bitwise", version = "1.3.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_bitwise", source = "hex", outer_checksum = "B36E1D3188D7F594C7FD4F43D0D2CE17561DE896202017548578B16FE1FE9EFC" }, | ||
{ name = "gleam_community_ansi", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "FE79E08BF97009729259B6357EC058315B6FBB916FAD1C2FF9355115FEB0D3A4" }, | ||
{ name = "gleam_community_colour", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "A49A5E3AE8B637A5ACBA80ECB9B1AFE89FD3D5351FF6410A42B84F666D40D7D5" }, | ||
{ name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" }, | ||
{ name = "gleam_json", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "8B197DD5D578EA6AC2C0D4BDC634C71A5BCA8E7DB5F47091C263ECB411A60DF3" }, | ||
{ name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" }, | ||
{ name = "gleam_stdlib", version = "0.36.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "C0D14D807FEC6F8A08A7C9EF8DFDE6AE5C10E40E21325B2B29365965D82EB3D4" }, | ||
{ name = "glexer", version = "0.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glexer", source = "hex", outer_checksum = "4484942A465482A0A100936E1E5F12314DB4B5AC0D87575A7B9E9062090B96BE" }, | ||
{ name = "simplifile", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "EB9AA8E65E5C1E3E0FDCFC81BC363FD433CB122D7D062750FFDF24DE4AC40116" }, | ||
{ name = "thoas", version = "0.4.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "4918D50026C073C4AB1388437132C77A6F6F7C8AC43C60C13758CC0ADCE2134E" }, | ||
] | ||
|
||
[requirements] | ||
exercism_test_runner = { version = "~> 1.4" } | ||
gleam_bitwise = { version = "~> 1.2" } | ||
gleam_erlang = { version = ">= 0.25.0 and < 1.0.0"} | ||
gleam_otp = { version = "~> 0.7 or ~> 1.0" } | ||
gleam_stdlib = { version = "~> 0.32 or ~> 1.0" } | ||
simplifile = { version = "~> 1.0" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import gleam/int | ||
import gleam/list | ||
import gleam/string | ||
|
||
pub fn valid(value: String) -> Bool { | ||
let digits = | ||
value | ||
|> string.replace(" ", "") | ||
|> string.to_graphemes() | ||
|> list.try_map(int.parse) | ||
|
||
case digits { | ||
Ok(digits) -> list.length(digits) > 1 && luhn_sum(digits) % 10 == 0 | ||
_ -> False | ||
} | ||
} | ||
|
||
fn luhn_sum(digits: List(Int)) -> Int { | ||
list.index_fold(list.reverse(digits), 0, fn(sum, n, index) { | ||
case int.is_odd(index), n * 2 { | ||
False, _ -> sum + n | ||
True, double if double <= 9 -> sum + double | ||
True, double -> sum + double - 9 | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import exercism/test_runner | ||
import luhn | ||
|
||
pub fn main() { | ||
test_runner.main() | ||
} | ||
|
||
pub fn single_digit_strings_can_not_be_valid_test() { | ||
let assert False = luhn.valid("1") | ||
} | ||
|
||
pub fn a_single_zero_is_invalid_test() { | ||
let assert False = luhn.valid("0") | ||
} | ||
|
||
pub fn a_simple_valid_sin_that_remains_valid_if_reversed_test() { | ||
let assert True = luhn.valid("059") | ||
} | ||
|
||
pub fn a_simple_valid_sin_that_becomes_invalid_if_reversed_test() { | ||
let assert True = luhn.valid("59") | ||
} | ||
|
||
pub fn a_valid_canadian_sin_test() { | ||
let assert True = luhn.valid("055 444 285") | ||
} | ||
|
||
pub fn invalid_canadian_sin_test() { | ||
let assert False = luhn.valid("055 444 286") | ||
} | ||
|
||
pub fn invalid_credit_card_test() { | ||
let assert False = luhn.valid("8273 1232 7352 0569") | ||
} | ||
|
||
pub fn invalid_long_number_with_an_even_remainder_test() { | ||
let assert False = luhn.valid("1 2345 6789 1234 5678 9012") | ||
} | ||
|
||
pub fn invalid_long_number_with_a_remainder_divisible_by_5_test() { | ||
let assert False = luhn.valid("1 2345 6789 1234 5678 9013") | ||
} | ||
|
||
pub fn valid_number_with_an_even_number_of_digits_test() { | ||
let assert True = luhn.valid("095 245 88") | ||
} | ||
|
||
pub fn valid_number_with_an_odd_number_of_spaces_test() { | ||
let assert True = luhn.valid("234 567 891 234") | ||
} | ||
|
||
pub fn valid_strings_with_a_non_digit_added_at_the_end_become_invalid_test() { | ||
let assert False = luhn.valid("059a") | ||
} | ||
|
||
pub fn valid_strings_with_punctuation_included_become_invalid_test() { | ||
let assert False = luhn.valid("055-444-285") | ||
} | ||
|
||
pub fn valid_strings_with_symbols_included_become_invalid_test() { | ||
let assert False = luhn.valid("055# 444$ 285") | ||
} | ||
|
||
pub fn single_zero_with_space_is_invalid_test() { | ||
let assert False = luhn.valid(" 0") | ||
} | ||
|
||
pub fn more_than_a_single_zero_is_valid_test() { | ||
let assert True = luhn.valid("0000 0") | ||
} | ||
|
||
pub fn input_digit_9_is_correctly_converted_to_output_digit_9_test() { | ||
let assert True = luhn.valid("091") | ||
} | ||
|
||
pub fn very_long_input_is_valid_test() { | ||
let assert True = luhn.valid("9999999999 9999999999 9999999999 9999999999") | ||
} | ||
|
||
pub fn valid_luhn_with_an_odd_number_of_digits_and_non_zero_first_digit_test() { | ||
let assert True = luhn.valid("109") | ||
} | ||
|
||
pub fn using_ascii_value_for_non_doubled_non_digit_isn_t_allowed_test() { | ||
let assert False = luhn.valid("055b 444 285") | ||
} | ||
|
||
pub fn using_ascii_value_for_doubled_non_digit_isn_t_allowed_test() { | ||
let assert False = luhn.valid(":9") | ||
} | ||
|
||
pub fn non_numeric_non_space_char_in_the_middle_with_a_sum_that_s_divisible_by_10_isn_t_allowed_test() { | ||
let assert False = luhn.valid("59%59") | ||
} |