in reply to (dkubb) Re: (2) YAL10CI (Yet Another LUHN-10 Checksum Implementation)
in thread YAL10CI (Yet Another LUHN-10 Checksum Implementation)

This algorith fails on '49927398716' in my test case. That was the code given on the LUHN-10 website. It comes up with a sum of 62 when it should be a sum of 70 per the original algorithm.

I am curious if you can explain how the

($sum += chop $number) ... ($sum += $LUHN10_map[chop $number]) while $ +number ne '';
logic works. I just (like 1 minute ago) learned about the bi-stable operator.


While typing this, I figured out why this failed my test case. The call to '...' is persistant across subroutine calls. In my test case, I use

('125', '49927398716', '4992739872')
and it failed on '49927398716'. When I used
('125', '49927398716', '49927398716','4992739872')
it failed on the 1st '49927398716' and on '4992739872' so I can only assume this operator maintains its state.

UPDATE: This also fails on '620' since the bi-stable does not flip state if the side that is being evaluated returns false(or 0). So a number ending in '0' will not be processed correctly.

Replies are listed 'Best First'.
(dkubb) Re: (4) YAL10CI (Yet Another LUHN-10 Checksum Implementation)
by dkubb (Deacon) on Mar 13, 2001 at 10:09 UTC

    johannz you are right! I had no idea the range operator (...) was persistent across subroutine calls. I expected it to maintain it's state while inside the while loop, but reset itself each time the subroutine was called.

    perlop gives an explanation of the ... operator. It's definately something I have not used much before, or seen used, so I wanted to give it a try.

    While I was trying to figure out why my example didn't work in all cases, I came up with the following that returned the correct values during testing:

    sub dkubb_LUHN10 { my $number = shift || return 0; my $sum; $sum += chop($number) + $LUHN10_map[chop $number] while "$number"; ($sum % 10 == 0) || 0; }

      Running this under -w gives warnings on odd lengths for $number. You can shut them up with only a little slowdown with the following:

      sub dkubb_LUHN10_2 { my $number = shift || return 0; my $sum; $sum += (chop($number) || 0) + $LUHN10_map[chop($number) || 0] while "$number"; ($sum % 10 == 0) || 0; }