{-# Language QuasiQuotes #-}
module Main where
import Advent (format, counts)
import Data.Char (ord, chr)
import Data.List (sortBy)
import qualified Data.Map as Map
type Entry = ([String], Int, String)
main :: IO ()
IO ()
main =
do [([String], Int, String)]
input <- [format|2016 4 ((%a+-)*%d[%a*]%n)*|]
let valid :: [([String], Int, String)]
valid = [([String], Int, String)
e | ([String], Int, String)
e <- [([String], Int, String)]
input, ([String], Int, String) -> Bool
isGoodEntry ([String], Int, String)
e]
Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
sid | ([String]
_, Int
sid, String
_) <- [([String], Int, String)]
valid])
[Int] -> IO ()
forall a. Show a => a -> IO ()
print [Int
sid | e :: ([String], Int, String)
e@([String]
_, Int
sid, String
_) <- [([String], Int, String)]
valid, ([String], Int, String) -> String
decryptEntry ([String], Int, String)
e String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"northpole object storage"]
decryptEntry :: Entry -> String
decryptEntry :: ([String], Int, String) -> String
decryptEntry ([String]
name, Int
sid, String
_) = [String] -> String
unwords ((String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Char -> Char
decrypt Int
sid)) [String]
name)
isGoodEntry :: Entry -> Bool
isGoodEntry :: ([String], Int, String) -> Bool
isGoodEntry ([String]
name, Int
_, String
hash) = String
hash String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String -> String
computeHash ([String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
name)
computeHash :: String -> String
computeHash :: String -> String
computeHash String
x = Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
5 (((Char, Int) -> Char) -> [(Char, Int)] -> String
forall a b. (a -> b) -> [a] -> [b]
map (Char, Int) -> Char
forall a b. (a, b) -> a
fst (((Char, Int) -> (Char, Int) -> Ordering)
-> [(Char, Int)] -> [(Char, Int)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Char, Int) -> (Char, Int) -> Ordering
forall {a} {a}. (Ord a, Ord a) => (a, a) -> (a, a) -> Ordering
ordering (Map Char Int -> [(Char, Int)]
forall k a. Map k a -> [(k, a)]
Map.toList (String -> Map Char Int
forall (f :: * -> *) a. (Foldable f, Ord a) => f a -> Map a Int
counts String
x))))
where
ordering :: (a, a) -> (a, a) -> Ordering
ordering (a
xa,a
xn) (a
ya,a
yn)
= a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
yn a
xn
Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
xa a
ya
decrypt :: Int -> Char -> Char
decrypt :: Int -> Char -> Char
decrypt Int
n Char
c = Int -> Char
chr ((Char -> Int
ord Char
c Int -> Int -> Int
forall a. Num a => a -> a -> a
- Char -> Int
ord Char
'a' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
26 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Char -> Int
ord Char
'a')