-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay13.hs
102 lines (89 loc) · 3.03 KB
/
Day13.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
{-# LANGUAGE TemplateHaskell #-}
module Day13
( part1
, part2
) where
import Data.Bifunctor (bimap, first)
import Data.Bits (shiftL, shiftR, (.&.))
import Data.ByteString (ByteString)
import Data.Char (ord)
import Data.IntMap.Strict (IntMap, assocs, fromList,
insertWith, (!))
import Data.IntSet (IntSet, insert, size, toList)
import Data.List (permutations)
import Data.Sequence (Seq ((:<|), (:|>)))
import qualified Data.Sequence as Sq (fromList, length)
import FlatParse.Basic (anyAsciiDecimalInt, eof,
isLatinLetter, optional_, runParser,
satisfy, skipSatisfy, some, string,
switch, (<|>))
import Helpers.Parsers.FlatParse (extract)
import qualified Helpers.Parsers.FlatParse as F (Parser)
import Helpers.Search.Int (travelingSalesman)
type Edges = IntMap Int
type Parser = F.Parser (IntSet, Edges)
parseInput :: Parser
parseInput = parseLine <|> (eof >> return (mempty, mempty))
parseLine :: Parser
parseLine = do
firstNode <- ord . head <$> some (satisfy isLatinLetter)
$(string " would ")
op <-
$(switch
[|case _ of
"gain " -> return id
"lose " -> return negate|])
gainLoss <- anyAsciiDecimalInt
$(string " happiness unit")
optional_ . skipSatisfy $ (== 's')
$(string " by sitting next to ")
secondNode <- ord . head <$> some (satisfy isLatinLetter)
$(string ".\n")
bimap
(insert firstNode . insert secondNode)
(insertWith (+) (encodeRaw firstNode secondNode) (op gainLoss))
<$> parseInput
encodeRaw :: Int -> Int -> Int
encodeRaw a b = u + shiftL l 7
where
l = min a b
u = max a b
encode :: Int -> (Int, Int) -> Int
encode bitSize (a, b) = a + shiftL b bitSize
decode :: Int -> (Int, Int)
decode i = (i .&. 127, shiftR i 7)
simplify :: (IntSet, IntMap Int) -> (Int, IntMap Int)
simplify (nodes, rawEdges) = (numBits, edges)
where
numBits = ceiling . logBase 2 . fromIntegral . size $ nodes
assocMap = fromList . flip zip [0 ..] . toList $ nodes
edges =
fromList
. map
(bimap
(encode numBits . bimap (assocMap !) (assocMap !) . decode)
negate)
. assocs
$ rawEdges
addMe :: (IntSet, IntMap Int) -> (IntSet, IntMap Int)
addMe (nodes, rawEdges) = (nodes', rawEdges')
where
nodes' = insert 0 nodes
rawEdges' = foldr (flip (insertWith (+)) 0) rawEdges . toList $ nodes
part1 :: Bool -> ByteString -> String
part1 _ =
show
. negate
. uncurry travelingSalesman
. simplify
. extract
. runParser parseInput
part2 :: Bool -> ByteString -> String
part2 _ =
show
. negate
. uncurry travelingSalesman
. simplify
. addMe
. extract
. runParser parseInput