commit e35bd4e67fe0806a2df1de17c73e968070fc6897
parent c59151f6dc7ff16e5884f08cd55adc1df15781a9
Author: Samir Parikh <noreply@samirparikh.com>
Date: Fri, 26 Aug 2022 22:10:05 +0000
initial commit
Diffstat:
A | luhn/HELP.md | | | 36 | ++++++++++++++++++++++++++++++++++++ |
A | luhn/Luhn.pm | | | 30 | ++++++++++++++++++++++++++++++ |
A | luhn/README.md | | | 88 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | luhn/luhn.t | | | 171 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 325 insertions(+), 0 deletions(-)
diff --git a/luhn/HELP.md b/luhn/HELP.md
@@ -0,0 +1,35 @@
+# Help
+
+## Running the tests
+
+There is a Perl 5 script with the extension `.t`, which will be used to test
+your solution. You can run through the tests by using the command:
+
+```bash
+`prove .`
+```
+
+## Submitting your solution
+
+You can submit your solution using the `exercism submit Luhn.pm` 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 [Perl 5 track's documentation](https://exercism.org/docs/tracks/perl5)
+- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
+- 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:
+
+- [/r/perl5](https://www.reddit.com/r/perl5) is the perl5 subreddit.
+- [StackOverflow](http://stackoverflow.com/questions/tagged/perl5) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.
+\ No newline at end of file
diff --git a/luhn/Luhn.pm b/luhn/Luhn.pm
@@ -0,0 +1,30 @@
+package Luhn;
+
+use strict;
+use warnings;
+use feature qw<say>;
+
+use Exporter qw<import>;
+our @EXPORT_OK = qw<is_luhn_valid>;
+
+sub is_luhn_valid {
+ my ($input) = @_;
+ #print "input was originally '$input'\n";
+ $input =~ s/\s+//g; # remove whitespace
+ #print "input = $input\n";
+
+ # return false if string is less than 2 digits
+ return 0 if ( length $input < 2 );
+
+ # return false if we find a non-decimal character
+ return 0 if ( $input =~ m/\D/ );
+ my @numbers = ( $input =~ m/\d/g ); # split out input into array
+ print join( ":", @numbers), "\n";
+
+ # the special variable $#numbers represents the index of the last element
+ # of the array @numbers
+
+ return undef;
+}
+
+1;
diff --git a/luhn/README.md b/luhn/README.md
@@ -0,0 +1,87 @@
+# Luhn
+
+Welcome to Luhn on Exercism's Perl 5 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](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 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.
+
+## Source
+
+### Created by
+
+- @bistik
+
+### Contributed to by
+
+- @alexkalderimis
+- @kytrinyx
+- @m-dango
+- @pgraemer
+- @rfilipo
+
+### Based on
+
+The Luhn Algorithm on Wikipedia - http://en.wikipedia.org/wiki/Luhn_algorithm
+\ No newline at end of file
diff --git a/luhn/luhn.t b/luhn/luhn.t
@@ -0,0 +1,171 @@
+#!/usr/bin/env perl
+use Test2::V0;
+use JSON::PP;
+use constant JSON => JSON::PP->new;
+
+use FindBin qw<$Bin>;
+use lib $Bin, "$Bin/local/lib/perl5";
+
+use Luhn qw<is_luhn_valid>;
+
+my @test_cases = do { local $/; @{ JSON->decode(<DATA>) }; };
+plan 19;
+
+imported_ok qw<is_luhn_valid> or bail_out;
+
+for my $case (@test_cases) {
+ is( is_luhn_valid( $case->{input}{value} ),
+ $case->{expected}
+ ? T
+ : DF,
+ $case->{description}
+ );
+}
+
+__DATA__
+[
+ {
+ "description": "single digit strings can not be valid",
+ "expected": false,
+ "input": {
+ "value": "1"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "a single zero is invalid",
+ "expected": false,
+ "input": {
+ "value": "0"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "a simple valid SIN that remains valid if reversed",
+ "expected": true,
+ "input": {
+ "value": "059"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "a simple valid SIN that becomes invalid if reversed",
+ "expected": true,
+ "input": {
+ "value": "59"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "a valid Canadian SIN",
+ "expected": true,
+ "input": {
+ "value": "055 444 285"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "invalid Canadian SIN",
+ "expected": false,
+ "input": {
+ "value": "055 444 286"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "invalid credit card",
+ "expected": false,
+ "input": {
+ "value": "8273 1232 7352 0569"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "invalid long number with an even remainder",
+ "expected": false,
+ "input": {
+ "value": "1 2345 6789 1234 5678 9012"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "valid number with an even number of digits",
+ "expected": true,
+ "input": {
+ "value": "095 245 88"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "valid number with an odd number of spaces",
+ "expected": true,
+ "input": {
+ "value": "234 567 891 234"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "valid strings with a non-digit added at the end become invalid",
+ "expected": false,
+ "input": {
+ "value": "059a"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "valid strings with punctuation included become invalid",
+ "expected": false,
+ "input": {
+ "value": "055-444-285"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "valid strings with symbols included become invalid",
+ "expected": false,
+ "input": {
+ "value": "055# 444$ 285"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "single zero with space is invalid",
+ "expected": false,
+ "input": {
+ "value": " 0"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "more than a single zero is valid",
+ "expected": true,
+ "input": {
+ "value": "0000 0"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "input digit 9 is correctly converted to output digit 9",
+ "expected": true,
+ "input": {
+ "value": "091"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "using ascii value for non-doubled non-digit isn't allowed",
+ "expected": false,
+ "input": {
+ "value": "055b 444 285"
+ },
+ "property": "valid"
+ },
+ {
+ "description": "using ascii value for doubled non-digit isn't allowed",
+ "expected": false,
+ "input": {
+ "value": ":9"
+ },
+ "property": "valid"
+ }
+]