-
-
Notifications
You must be signed in to change notification settings - Fork 7
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
8 changed files
with
312 additions
and
1 deletion.
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
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 |
---|---|---|
@@ -1,2 +1,2 @@ | ||
func flatten(iterable): | ||
pass | ||
pass |
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,64 @@ | ||
# 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 |
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,19 @@ | ||
{ | ||
"authors": [ | ||
"pfertyk" | ||
], | ||
"files": { | ||
"solution": [ | ||
"luhn.gd" | ||
], | ||
"test": [ | ||
"luhn_test.gd" | ||
], | ||
"example": [ | ||
".meta/example.gd" | ||
] | ||
}, | ||
"blurb": "Given a number determine whether or not it is valid per the Luhn formula.", | ||
"source": "The Luhn Algorithm on Wikipedia", | ||
"source_url": "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,22 @@ | ||
@export var card_num : String | ||
|
||
|
||
func valid(): | ||
var num = card_num.replace(" ", "") | ||
if len(num) <= 1: | ||
return false | ||
|
||
var checksum = 0 | ||
for index in range(len(num)): | ||
var char = num[len(num) - 1 - index] | ||
if not char.is_valid_int(): | ||
return false | ||
if index % 2 == 1: | ||
var digit = int(char) | ||
digit *= 2 | ||
if digit > 9: | ||
digit -= 9 | ||
checksum += digit | ||
else: | ||
checksum += int(char) | ||
return checksum % 10 == 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,76 @@ | ||
# This is an auto-generated file. | ||
# | ||
# Regenerating this file via `configlet sync` will: | ||
# - Recreate every `description` key/value pair | ||
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications | ||
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) | ||
# - Preserve any other key/value pair | ||
# | ||
# As user-added comments (using the # character) will be removed when this file | ||
# is regenerated, comments can be added via a `comment` key. | ||
|
||
[792a7082-feb7-48c7-b88b-bbfec160865e] | ||
description = "single digit strings can not be valid" | ||
|
||
[698a7924-64d4-4d89-8daa-32e1aadc271e] | ||
description = "a single zero is invalid" | ||
|
||
[73c2f62b-9b10-4c9f-9a04-83cee7367965] | ||
description = "a simple valid SIN that remains valid if reversed" | ||
|
||
[9369092e-b095-439f-948d-498bd076be11] | ||
description = "a simple valid SIN that becomes invalid if reversed" | ||
|
||
[8f9f2350-1faf-4008-ba84-85cbb93ffeca] | ||
description = "a valid Canadian SIN" | ||
|
||
[1cdcf269-6560-44fc-91f6-5819a7548737] | ||
description = "invalid Canadian SIN" | ||
|
||
[656c48c1-34e8-4e60-9a5a-aad8a367810a] | ||
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" | ||
|
||
[ef081c06-a41f-4761-8492-385e13c8202d] | ||
description = "valid number with an odd number of spaces" | ||
|
||
[bef66f64-6100-4cbb-8f94-4c9713c5e5b2] | ||
description = "valid strings with a non-digit added at the end become invalid" | ||
|
||
[2177e225-9ce7-40f6-b55d-fa420e62938e] | ||
description = "valid strings with punctuation included become invalid" | ||
|
||
[ebf04f27-9698-45e1-9afe-7e0851d0fe8d] | ||
description = "valid strings with symbols included become invalid" | ||
|
||
[08195c5e-ce7f-422c-a5eb-3e45fece68ba] | ||
description = "single zero with space is invalid" | ||
|
||
[12e63a3c-f866-4a79-8c14-b359fc386091] | ||
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" | ||
|
||
[f94cf191-a62f-4868-bc72-7253114aa157] | ||
description = "using ascii value for doubled non-digit isn't allowed" | ||
|
||
[8b72ad26-c8be-49a2-b99c-bcc3bf631b33] | ||
description = "non-numeric, non-space char in the middle with a sum that's divisible by 10 isn't allowed" |
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,5 @@ | ||
@export var card_num : String | ||
|
||
|
||
func valid(): | ||
pass |
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,117 @@ | ||
func test_single_digit_strings_can_not_be_valid(solution_script): | ||
solution_script.card_num = "1" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_a_single_zero_is_invalid(solution_script): | ||
solution_script.card_num = "0" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_a_simple_valid_sin_that_remains_valid_if_reversed(solution_script): | ||
solution_script.card_num = "059" | ||
return [solution_script.valid(), true] | ||
|
||
|
||
func test_a_simple_valid_sin_that_becomes_invalid_if_reversed(solution_script): | ||
solution_script.card_num = "59" | ||
return [solution_script.valid(), true] | ||
|
||
|
||
func test_a_valid_canadian_sin(solution_script): | ||
solution_script.card_num = "055 444 285" | ||
return [solution_script.valid(), true] | ||
|
||
|
||
func test_invalid_canadian_sin(solution_script): | ||
solution_script.card_num = "055 444 286" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_invalid_credit_card(solution_script): | ||
solution_script.card_num = "8273 1232 7352 0569" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_invalid_long_number_with_an_even_remainder(solution_script): | ||
solution_script.card_num = "1 2345 6789 1234 5678 9012" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_invalid_long_number_with_a_remainder_divisible_by_5(solution_script): | ||
solution_script.card_num = "1 2345 6789 1234 5678 9013" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_valid_number_with_an_even_number_of_digits(solution_script): | ||
solution_script.card_num = "095 245 88" | ||
return [solution_script.valid(), true] | ||
|
||
|
||
func test_valid_number_with_an_odd_number_of_spaces(solution_script): | ||
solution_script.card_num = "234 567 891 234" | ||
return [solution_script.valid(), true] | ||
|
||
|
||
func test_valid_strings_with_a_non_digit_added_at_the_end_become_invalid(solution_script): | ||
solution_script.card_num = "059a" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_valid_strings_with_punctuation_included_become_invalid(solution_script): | ||
solution_script.card_num = "055-444-285" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_valid_strings_with_symbols_included_become_invalid(solution_script): | ||
solution_script.card_num = "055# 444$ 285" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_single_zero_with_space_is_invalid(solution_script): | ||
solution_script.card_num = " 0" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_more_than_a_single_zero_is_valid(solution_script): | ||
solution_script.card_num = "0000 0" | ||
return [solution_script.valid(), true] | ||
|
||
|
||
func test_input_digit_9_is_correctly_converted_to_output_digit_9(solution_script): | ||
solution_script.card_num = "091" | ||
return [solution_script.valid(), true] | ||
|
||
|
||
func test_very_long_input_is_valid(solution_script): | ||
solution_script.card_num = "9999999999 9999999999 9999999999 9999999999" | ||
return [solution_script.valid(), true] | ||
|
||
|
||
func test_valid_luhn_with_an_odd_number_of_digits_and_non_zero_first_digit(solution_script): | ||
solution_script.card_num = "109" | ||
return [solution_script.valid(), true] | ||
|
||
|
||
func test_using_ascii_value_for_non_doubled_non_digit_isn_t_allowed(solution_script): | ||
solution_script.card_num = "055b 444 285" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_using_ascii_value_for_doubled_non_digit_isn_t_allowed(solution_script): | ||
solution_script.card_num = ":9" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_non_numeric_non_space_char_in_the_middle_with_a_sum_that_s_divisible_by_10_isn_t_allowed(solution_script): | ||
solution_script.card_num = "59%59" | ||
return [solution_script.valid(), false] | ||
|
||
|
||
func test_is_valid_can_be_called_repeatedly(solution_script): | ||
# This test was added, because we saw many implementations | ||
# in which the first call to valid() worked, but the | ||
# second call failed. | ||
solution_script.card_num = "055 444 285" | ||
return [solution_script.valid(), true] | ||
return [solution_script.valid(), true] |