How to resolve the algorithm Luhn test of credit card numbers step by step in the AppleScript programming language
Published on 12 May 2024 09:40 PM
How to resolve the algorithm Luhn test of credit card numbers step by step in the AppleScript programming language
Table of Contents
Problem Statement
The Luhn test is used by some credit card companies to distinguish valid credit card numbers from what could be a random selection of digits. Those companies using credit card numbers that can be validated by the Luhn test have numbers that pass the following test:
For example, if the trial number is 49927398716:
Write a function/method/procedure/subroutine that will validate a number with the Luhn test, and use it to validate the following numbers:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Luhn test of credit card numbers step by step in the AppleScript programming language
Source code in the applescript programming language
-- luhn :: String -> Bool
on luhn(s)
-- True if the digit string represents
-- a valid Luhn credit card number.
script divMod10Sum
on |λ|(a, x)
a + x div 10 + x mod 10
end |λ|
end script
0 = foldl(divMod10Sum, 0, ¬
zipWith(my mul, ¬
map(my int, reverse of (characters of s)), ¬
cycle({1, 2}))) mod 10
end luhn
--------------------------- TEST ---------------------------
on run
map(luhn, ¬
{"49927398716", "49927398717", ¬
"1234567812345678", "1234567812345670"})
--> {true, false, false, true}
end run
---------------- REUSABLE GENERIC FUNCTIONS ----------------
-- cycle :: [a] -> Generator [a]
on cycle(xs)
script
property lng : 1 + (length of xs)
property i : missing value
on |λ|()
if missing value is i then
set i to 1
else
set nxt to (1 + i) mod lng
if 0 = ((1 + i) mod lng) then
set i to 1
else
set i to nxt
end if
end if
return item i of xs
end |λ|
end script
end cycle
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- int :: String -> Int
on int(s)
s as integer
end int
-- length :: [a] -> Int
on |length|(xs)
set c to class of xs
if list is c or string is c then
length of xs
else
(2 ^ 29 - 1) -- (maxInt - simple proxy for non-finite)
end if
end |length|
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
-- 2nd class handler function lifted into 1st class script wrapper.
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
-- The list obtained by applying f
-- to each element of xs.
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- mul (*) :: Num a => a -> a -> a
on mul(a, b)
a * b
end mul
-- take :: Int -> [a] -> [a]
-- take :: Int -> String -> String
on take(n, xs)
set c to class of xs
if list is c then
if 0 < n then
items 1 thru min(n, length of xs) of xs
else
{}
end if
else if string is c then
if 0 < n then
text 1 thru min(n, length of xs) of xs
else
""
end if
else if script is c then
set ys to {}
repeat with i from 1 to n
set v to |λ|() of xs
if missing value is v then
return ys
else
set end of ys to v
end if
end repeat
return ys
else
missing value
end if
end take
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
on zipWith(f, xs, ys)
set lng to min(|length|(xs), |length|(ys))
if 1 > lng then return {}
set xs_ to take(lng, xs) -- Allow for non-finite
set ys_ to take(lng, ys) -- generators like cycle etc
set lst to {}
tell mReturn(f)
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs_, item i of ys_)
end repeat
return lst
end tell
end zipWith
on luhnTest(n)
-- Accept only text input.
if (n's class is not text) then return false
-- Edit out any spaces or dashes.
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to {space, "-"}
set n to n's text items
set AppleScript's text item delimiters to ""
set n to n as text
set AppleScript's text item delimiters to astid
-- Check that what's left is numeric.
try
n as number
on error
return false
end try
-- Do the calculation two digits at a time, starting at the end of the text and working back.
set sum to 0
repeat with i from ((count n) - 1) to 1 by -2
set n2 to (text i thru (i + 1) of n) as integer
tell n2 div 10 mod 10 * 2 to set sum to sum + it div 10 + it mod 10 + n2 mod 10
end repeat
-- If there's an odd digit left over, add that in too.
if (i is 2) then set sum to sum + (character 1 of n)
return (sum mod 10 is 0)
end luhnTest
-- Test code:
set testResults to {}
repeat with testNumber in {"49927398716", "49927398717", "1234567812345678", "1234567812345670"}
set end of testResults to {testNumber:testNumber's contents, valid:luhnTest(testNumber)}
end repeat
return testResults
{{testNumber:"49927398716", valid:true}, {testNumber:"49927398717", valid:false}, {testNumber:"1234567812345678", valid:false}, {testNumber:"1234567812345670", valid:true}}
You may also check:How to resolve the algorithm Sorting algorithms/Comb sort step by step in the Delphi programming language
You may also check:How to resolve the algorithm N-smooth numbers step by step in the J programming language
You may also check:How to resolve the algorithm Arithmetic-geometric mean/Calculate Pi step by step in the Julia programming language
You may also check:How to resolve the algorithm Repeat a string step by step in the Dyalect programming language
You may also check:How to resolve the algorithm Hello world/Text step by step in the SkookumScript programming language