-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path05.hs
67 lines (55 loc) · 2.1 KB
/
05.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import Crypto.Hash
import Crypto.Hash.Algorithms (MD5)
import Data.ByteString.Builder
import Data.Char (digitToInt)
import Data.List
import qualified Data.ByteString.Lazy as L
import qualified Data.Map.Strict as M
toStrictByteString = L.toStrict . toLazyByteString
md5 :: Builder -> String
md5 b = show (hash (toStrictByteString b) :: Digest MD5)
hashIdAndIndex :: Builder -> Int -> String
hashIdAndIndex b i = md5 (b `mappend` intDec i)
startsWithFiveZeros :: String -> Bool
startsWithFiveZeros s = "00000" `isPrefixOf` s
allHashes :: Builder -> [String]
allHashes b = [hashIdAndIndex b i | i <- [1..]]
findPassword :: Builder -> String
findPassword b = take 8 (map
(\s -> s !! 5)
(filter
startsWithFiveZeros
(allHashes b)))
-- Part 2.
insertIfNotPresent :: Ord k => k -> a -> M.Map k a -> M.Map k a
insertIfNotPresent k v m = if (M.member k m)
then m
else (M.insert k v m)
legalPos :: Char -> Maybe Int
legalPos p = if (p `elem` ['0' .. '7'])
then Just (digitToInt p)
else Nothing
insertPart :: String -> M.Map Int Char -> M.Map Int Char
insertPart s m = case (legalPos k) of
Just x -> insertIfNotPresent x v m
Nothing -> m
where k = s !! 5
v = s !! 6
buildMap :: M.Map Int Char -> [String] -> M.Map Int Char
buildMap m (h:hs) = case (M.size m) of
8 -> m
_ -> if (startsWithFiveZeros h)
then buildMap (insertPart h m) hs
else buildMap m hs
mapToString :: M.Map Int Char -> String
mapToString m = foldl (\acc x -> acc ++ [x]) "" m
findPassword' :: Builder -> String
findPassword' b = mapToString $ buildMap M.empty (allHashes b)
-- Main.
main = do
input <- getLine
let builder = (stringUtf8 input)
let pw1 = findPassword builder
putStrLn . show $ pw1
let pw2 = findPassword' builder
putStrLn . show $ pw2