Skip to content

Instantly share code, notes, and snippets.

@yoh2
Created January 21, 2017 17:40
Show Gist options
  • Save yoh2/11ab5feffc349e4b513e62b58b3e8036 to your computer and use it in GitHub Desktop.
Save yoh2/11ab5feffc349e4b513e62b58b3e8036 to your computer and use it in GitHub Desktop.
import qualified Data.Map as M (lookup)
import Data.Map (Map, fromList)
import Data.List (permutations)
import Data.Maybe (fromJust)
dictionaryFromList :: [Int] -> Map Char Int
dictionaryFromList xs = fromList $ zip ['a' .. 'j'] xs
transformByMap :: Ord a => [a] -> Map a b -> [b]
transformByMap xs dic = map (fromJust . flip M.lookup dic) xs
-- 桁の並びを反転したマイナンバー上位11桁から
-- チェックディジットを求める。
checkdigit_r :: [Int] -> Int
checkdigit_r xs = let
c = 11 - (calc 1 xs) `mod` 11
in
if c >= 10 then 0 else c
where
calc n ys | n >= 12 = 0
| n >= 7 = head ys * (n - 5) + calc (n + 1) (tail ys)
| otherwise = head ys * (n + 1) + calc (n + 1) (tail ys)
verify :: [Int] -> Bool
verify xs = let (y:ys) = reverse xs
in checkdigit_r ys == y
-- 'a' .. 'j' がそれぞれ 0 .. 9 のいずれかの数字と
-- 一対一対応する12文字の文字列のリストを受け取り、
-- (チェックディジットを満たす数, 満たさない数)
-- を返す。
possibility xss = let
dictionaries = map dictionaryFromList $ permutations [0..9]
fromDicList = map transformByMap xss
verifyDic dic = and $ map (\fromDic -> verify $ fromDic dic) fromDicList
in
foldl (\(a, b) dic -> if verifyDic dic then (a + 1, b) else (a, b + 1))
(0, 0)
dictionaries
-- 適当に生成した10個で試しています。
main = print $ possibility [
"gggfheiggejh", -- (666574866497)
"bcheiggijdfi", -- (127486689358)
"gcfijggiicfb", -- (625896688251)
"igeihgfeacee", -- (864876540244)
"jhbgcjijfege", -- (971629895464)
"adjhhigiiefd", -- (039778688453)
"bihgbggafced", -- (187616605243)
"iidigaghjjjj", -- (883860679999)
"ihahjggcdhif", -- (870796623785)
"bbfbijeahfbf" -- (115189407515)
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment