48 lines
1.4 KiB
Raku
48 lines
1.4 KiB
Raku
my @d = [^10] xx 5;
|
|
@d[$_][^5].=rotate($_), @d[$_][5..*].=rotate($_) for 1..4;
|
|
push @d: [@d[$_].reverse] for flat 1..4, 0;
|
|
|
|
my @i = 0,4,3,2,1,5,6,7,8,9;
|
|
|
|
my %h = flat (0,1,5,8,9,4,2,7,0).rotor(2 =>-1).map({.[0]=>.[1]}), 6=>3, 3=>6;
|
|
my @p = [^10],;
|
|
@p.push: [@p[*-1].map: {%h{$_}}] for ^7;
|
|
|
|
sub checksum (Int $int where * ≥ 0, :$verbose = True ) {
|
|
my @digits = $int.comb;
|
|
say "\nCheckdigit calculation for $int:";
|
|
say " i ni p(i, ni) c" if $verbose;
|
|
my ($i, $p, $c) = 0 xx 3;
|
|
say " $i 0 $p $c" if $verbose;
|
|
for @digits.reverse {
|
|
++$i;
|
|
$p = @p[$i % 8][$_];
|
|
$c = @d[$c; $p];
|
|
say "{$i.fmt('%2d')} $_ $p $c" if $verbose;
|
|
}
|
|
say "Checkdigit: {@i[$c]}";
|
|
+($int ~ @i[$c]);
|
|
}
|
|
|
|
sub validate (Int $int where * ≥ 0, :$verbose = True) {
|
|
my @digits = $int.comb;
|
|
say "\nValidation calculation for $int:";
|
|
say " i ni p(i, ni) c" if $verbose;
|
|
my ($i, $p, $c) = 0 xx 3;
|
|
for @digits.reverse {
|
|
$p = @p[$i % 8][$_];
|
|
$c = @d[$c; $p];
|
|
say "{$i.fmt('%2d')} $_ $p $c" if $verbose;
|
|
++$i;
|
|
}
|
|
say "Checkdigit: {'in' if $c}correct";
|
|
}
|
|
|
|
## TESTING
|
|
|
|
for 236, 12345, 123456789012 -> $int {
|
|
my $check = checksum $int, :verbose( $int.chars < 8 );
|
|
validate $check, :verbose( $int.chars < 8 );
|
|
validate +($check.chop ~ 9), :verbose( $int.chars < 8 );
|
|
}
|