Validate International Securities Identification Number: Difference between revisions

Content added Content deleted
Line 1,485: Line 1,485:


Or, making alternative choices from the standard libraries:
Or, making alternative choices from the standard libraries:
<lang haskell>import qualified Data.Map as M
<lang haskell>import Data.Bifunctor (first)
import Data.Bifunctor (first)
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
import Data.Maybe (fromMaybe)


-------------------- VALID ISIN STRING -------------------
validISIN, isinPattern, luhn :: String -> Bool
validISIN = (&&) . isinPattern <*> (luhn . (show =<<) . stringInts)


validISIN :: String -> Bool
validISIN =
(&&) . isinPattern
<*> (luhn . (show =<<) . stringInts)

isinPattern :: String -> Bool
isinPattern s =
isinPattern s =
12 == length s &&
12 == length s
all (`elem` capitals) l &&
&& all (`elem` capitals) l
all (`elem` (capitals ++ digits)) m && head r `elem` digits
&& all (`elem` (capitals ++ digits)) m
&& head r `elem` digits
where
where
[l, m, r] = bites [2, 9, 1] s
[l, m, r] = bites [2, 9, 1] s


luhn :: String -> Bool
luhn x = 0 == rem (s1 + s2) 10
luhn x = 0 == rem (s1 + s2) 10
where
where
odds = [(: []), const []]
odds = [(: []), const []]
evens = reverse odds
evens = reverse odds
stream f =
stream f = concat $ zipWith ($) (cycle f) (stringInts $ reverse x)
concat $
zipWith
($)
(cycle f)
(stringInts $ reverse x)
s1 = sum (stream odds)
s1 = sum (stream odds)
s2 =
s2 = sum $ sum . stringInts . show . (2 *) <$> stream evens
sum $
sum . stringInts . show
. (2 *) <$> stream evens


charMap :: M.Map Char Int
charMap :: M.Map Char Int
charMap = M.fromList $ zip (digits ++ capitals) [0 ..]
charMap = M.fromList $ zip (digits <> capitals) [0 ..]


stringInts :: String -> [Int]
stringInts :: String -> [Int]
Line 1,516: Line 1,531:
bites ns xs =
bites ns xs =
(reverse . fst) $
(reverse . fst) $
foldr
foldr (\x (a, r) -> first (: a) (splitAt x r)) ([], xs) (reverse ns)
(\x (a, r) -> first (: a) (splitAt x r))
([], xs)
(reverse ns)


capitals, digits :: String
capitals, digits :: String
capitals = ['A' .. 'Z']
capitals = ['A' .. 'Z']

digits = ['0' .. '9']
digits = ['0' .. '9']


--------------------------- TEST -------------------------
main :: IO ()
main :: IO ()
main =
main =
mapM_
mapM_
(print . ((,) <*> validISIN))
(print . ((,) <*> validISIN))
[ "US0378331005"
[ "US0378331005",
, "US0373831005"
"US0373831005",
, "U50378331005"
"U50378331005",
, "US03378331005"
"US03378331005",
, "AU0000XVGZA3"
"AU0000XVGZA3",
, "AU0000VXGZA3"
"AU0000VXGZA3",
, "FR0000988040"
"FR0000988040"
]</lang>
]</lang>
{{Out}}
{{Out}}