diff --git a/exercises/luhn/canonical-data.json b/exercises/luhn/canonical-data.json index 6136287523..87e2c236a5 100644 --- a/exercises/luhn/canonical-data.json +++ b/exercises/luhn/canonical-data.json @@ -1,70 +1,34 @@ { - "#": [ - "The only note about this exercise is to make sure that the methods used", - "to check if a number is valid and to compute its checksum DO NOT modify", - "the value of the internal attributes. ", - "I say this because I've seen for the Python testcases that it needs a last", - "test to call the validation method twice to assure this. ", - "Simply assure that the two methods are const methods (to use a C++ notation)", - "using the tools available in your language. ", - "Here is a pretty universal solution for the validation method: ", - "`return (0 === (this.checksum % 10)) ? true : false;`" - ], - "cases": [ - { - "description": "check digit", - "input": 34567, - "expected": 7 - }, - { - "description": "check digit with input ending in zero", - "input": 91370, - "expected": 0 - }, - { - "description": "check addends", - "input": 12121, - "expected": [1, 4, 1, 4, 1] - }, - { - "description": "check too large addends", - "input": 8631, - "expected": [7, 6, 6, 1] - }, - { - "description": "checksum", - "input": 4913, - "expected": 22 - }, - { - "description": "checksum of larger number", - "input": 201773, - "expected": 21 - }, - { - "description": "check invalid number", - "input": 738, - "expected": false - }, - { - "description": "check valid number", - "input": 8739567, - "expected": true - }, - { - "description": "create valid number", - "input": 123, - "expected": 1230 - }, - { - "description": "create larger valid number", - "input": 873956, - "expected": 8739567 - }, - { - "description": "create even larger valid number", - "input": 837263756, - "expected": 8372637564 - } - ] + "valid": [ + { + "description": "single digit strings can not be valid", + "input": "1", + "expected": false + }, + { + "description": "A single zero is invalid", + "input": "0", + "expected": false + }, + { + "description": "valid Canadian SIN", + "input": "046 454 286", + "expected": true + }, + { + "description": "invalid Canadian SIN", + "input": "046 454 287", + "expected": false + }, + { + "description": "invalid credit card", + "input": "8273 1232 7352 0569", + "expected": false + }, + { + "description": "strings that contain non-digits are not valid", + "input": "827a 1232 7352 0569", + "expected": false + } + ] } diff --git a/exercises/luhn/description.md b/exercises/luhn/description.md index 2f9da2b1a1..d22781a1d7 100644 --- a/exercises/luhn/description.md +++ b/exercises/luhn/description.md @@ -1,53 +1,80 @@ -The Luhn formula is a simple checksum formula used to validate a variety -of identification numbers, such as credit card numbers and Canadian -Social Insurance Numbers. - -The formula verifies a number against its included check digit, which is -usually appended to a partial number to generate the full number. This -number must pass the following test: - -- Counting from rightmost digit (which is the check digit) and moving - left, double the value of every second digit. -- For any digits that thus become 10 or more, subtract 9 from the - result. - - 1111 becomes 2121. - - 8763 becomes 7733 (from 2×6=12 → 12-9=3 and 2×8=16 → 16-9=7). -- Add all these digits together. - - 1111 becomes 2121 sums as 2+1+2+1 to give a check digit of 6. - - 8763 becomes 7733, and 7+7+3+3 is 20. - -If the total ends in 0 (put another way, if the total modulus 10 is -congruent to 0), then the number is valid according to the Luhn formula; -else it is not valid. So, 1111 is not valid (as shown above, it comes -out to 6), while 8763 is valid (as shown above, it comes out to 20). - -Write a program that, given a number - -- Can check if it is valid per the Luhn formula. This should treat, for - example, "2323 2005 7766 3554" as valid. -- Can return the checksum, or the remainder from using the Luhn method. -- Can add a check digit to make the number valid per the Luhn formula and - return the original number plus that digit. This should give "2323 2005 7766 - 3554" in response to "2323 2005 7766 355". - -## About Checksums - -A checksum has to do with error-detection. There are a number of different -ways in which a checksum could be calculated. - -When transmitting data, you might also send along a checksum that says how -many bytes of data are being sent. That means that when the data arrives on -the other side, you can count the bytes and compare it to the checksum. If -these are different, then the data has been garbled in transmission. - -In the Luhn problem the final digit acts as a sanity check for all the prior -digits. Running those prior digits through a particular algorithm should give -you that final digit. - -It doesn't actually tell you if it's a real credit card number, only that it's -a plausible one. It's the same thing with the bytes that get transmitted -- -you could have the right number of bytes and still have a garbled message. So -checksums are a simple sanity-check, not a real in-depth verification of the -authenticity of some data. It's often a cheap first pass, and can be used to -quickly discard obviously invalid things. +The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) 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 write a function that checks if a given string is valid. + +Validating a Number +------ + +As an example, here is a valid (but fictitious) Canadian Social Insurance +Number. + +``` +046 454 286 +``` + +The first step of the Luhn algorithm is to double every second digit, +starting from the right. We will be doubling + +``` +_4_ 4_4 _8_ +``` + +If doubling the number results in a number greater than 9 then subtract 9 +from the product. The results of our doubling: + +``` +086 858 276 +``` + +Then sum all of the digits + +``` +0+8+6+8+5+8+2+7+6 = 50 +``` + +If the sum is evenly divisible by 10, then the number is valid. This number is valid! + +An example of an invalid Canadian SIN where we've changed the final digit + +``` +046 454 287 +``` + +Double the second digits, starting from the right + +``` +086 858 277 +``` + +Sum the digits + +``` +0+8+6+8+5+8+2+7+7 = 51 +``` + +51 is not evenly divisible by 10, so this number is not valid. + +---- + +An example of an invalid credit card account + +``` +8273 1232 7352 0569 +``` + +Double the second digits, starting from the right + +``` +7253 2262 5312 0539 +``` + +Sum the digits + +``` +7+2+5+3+2+2+5+2+5+3+1+2+0+5+3+9 = 57 +``` + +57 is not evenly divisible by 10, so this number is not valid.