Luhn.pm (1387B) - raw
1 package Luhn; 2 3 use strict; 4 use warnings; 5 use feature qw<say>; 6 7 use Exporter qw<import>; 8 our @EXPORT_OK = qw<is_luhn_valid>; 9 10 use List::Util qw(sum); 11 12 sub step1 { 13 my ( $digit ) = @_; 14 if ( $digit * 2 > 9 ) { 15 return $digit * 2 - 9; 16 } else { 17 return $digit * 2; 18 } 19 } 20 21 sub is_luhn_valid { 22 my ($input) = @_; 23 24 # remove whitespace 25 $input =~ s/\s+//g; 26 27 # return false if string is less than 2 digits 28 return 0 if ( length $input < 2 ); 29 30 # return false if we find a non-decimal character 31 return 0 if ( $input =~ m/\D/ ); 32 33 # split input into array 34 my @numbers = ( $input =~ m/\d/g ); 35 36 # the special variable $#numbers represents the index of the last element 37 # of the array @numbers 38 39 if ( $#numbers % 2 ) { # even number of digits, e.g. 1234 40 for ( my $i = 0; $i < $#numbers; $i += 2 ) { 41 $numbers[$i] = step1( $numbers[$i] ); 42 } 43 } else { # odd number of digits, e.g. 123 44 for ( my $i = 1; $i < $#numbers; $i += 2 ) { 45 $numbers[$i] = step1( $numbers[$i] ); 46 } 47 } 48 49 # fancy way of saying that if the sum of the numbers in the array is NOT 50 # divisible by zero (in which case `sum( @numbers ) % 10` returns a non 51 # zero number which evaluates to true) we return false (0). Otherwise, 52 # return true (1). 53 return sum( @numbers ) % 10 ? 0 : 1; 54 55 } 56 57 1;