package Luhn; use strict; use warnings; use feature qw; use Exporter qw; our @EXPORT_OK = qw; use List::Util qw(sum); sub step1 { my ( $digit ) = @_; if ( $digit * 2 > 9 ) { return $digit * 2 - 9; } else { return $digit * 2; } } sub is_luhn_valid { my ($input) = @_; # remove whitespace $input =~ s/\s+//g; # 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/ ); # split input into array my @numbers = ( $input =~ m/\d/g ); # the special variable $#numbers represents the index of the last element # of the array @numbers if ( $#numbers % 2 ) { # even number of digits, e.g. 1234 for ( my $i = 0; $i < $#numbers; $i += 2 ) { $numbers[$i] = step1( $numbers[$i] ); } } else { # odd number of digits, e.g. 123 for ( my $i = 1; $i < $#numbers; $i += 2 ) { $numbers[$i] = step1( $numbers[$i] ); } } # fancy way of saying that if the sum of the numbers in the array is NOT # divisible by zero (in which case `sum( @numbers ) % 10` returns a non # zero number which evaluates to true) we return false (0). Otherwise, # return true (1). return sum( @numbers ) % 10 ? 0 : 1; } 1;