-
Notifications
You must be signed in to change notification settings - Fork 0
/
run.hs
47 lines (37 loc) · 1.26 KB
/
run.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
{-# LANGUAGE RecordWildCards #-}
import Control.Arrow ((&&&))
import Data.Char (ord, chr)
import Data.List (intercalate, sortOn, isInfixOf)
import Data.MultiSet (MultiSet)
import qualified Data.MultiSet as MS
import Text.Parsec
data Room = Room { name :: [String]
, sector :: Int
, checksum :: String }
deriving (Show)
number = (read :: String -> Int) <$> many1 digit
parseRoom =
Room <$> (many1 (many1 letter <* char '-'))
<*> number
<*> between (char '[') (char ']') (many1 letter)
unsafeRight (Right x) = x
parseAll = map unsafeRight .
map (parse parseRoom "") . lines
validate :: Room -> Bool
validate Room {..} =
(== checksum)
. map fst
. take 5
. sortOn swap
. MS.toOccurList
. MS.fromList $ concat name
where swap (x, y) = (-y, x)
decrypt :: Room -> String
decrypt Room {..} = intercalate " " . map (map decrypt') $ name
where decrypt' = chr . (+ 97) . (`mod` 26) . (+ sector) . (+ (negate 97)) . ord
part1 = sum . map sector . filter validate
part2 = map (sector . snd) . filter (isInfixOf "north" . fst) . map (decrypt &&& id) . filter validate
main = do
input <- parseAll <$> readFile "input.txt"
print (part1 input)
print (head $ part2 input)