"Me too": :roll:
function isLuhnValid(cc as String) as Boolean:
digisum = [0,1,2,3,4,5,6,7,8,9,0,2,4,6,8,1,3,5,7,9]
sum = 0: ofs = 0
for i = len(cc) to 1 step -1:
sum = sum + digisum[strtoi(mid(cc,i,1)) + ofs]
ofs = 10 - ofs
end for
return sum mod 10 = 0
end function
Differences
- is faster (in the unlikely event that matters; 1/3 less time)
- is less readable (hey, i did not say it's an advantage)
- can be turned into a one-liner since has no IFs (i.e. `function isLuhnValid(cc as String) as Boolean: digisum = [0,1,2,3,4,5,6,7,8,9,0,2,4,6,8,1,3,5,7,9]: sum = 0: ofs = 0: for i = len(cc) to 1 step -1: sum = sum + digisum[strtoi(mid(cc,i,1)) + ofs]: ofs = 10 - ofs: end for: return sum mod 10 = 0: end function`)
Following belltown's performance notes, i toyed with a roByteArray version:
function isLuhnValid2(cc as String) as Boolean:
if len(cc) mod 2 > 0 then ofs = 10 else ofs = 0
ba = createObject("roByteArray")
ba.fromAsciiString(cc)
digisum = [0,1,2,3,4,5,6,7,8,9,0,2,4,6,8,1,3,5,7,9]
sum = 0
for each x in ba:
sum = sum + digisum[x - 48 + ofs]
ofs = 10 - ofs
end for
return sum mod 10 = 0
end function
This one is even faster (0.6x of isLuhnValid time, >2x faster than destruk's) but even less readable and it gets ugly if there are non-digits in the string (not that the other functions return correct result in such case - they don't - but this one gives me the creeps) - so i consider it of cryptozoological interest; e.g. trying to understand how it does it.
RokuMarkn's version is probably as close to golden middle as it goes - with the only note to pull digitsum init outside the loop.