-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay09.hs
67 lines (53 loc) · 1.65 KB
/
Day09.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
module Main where
import Advent.Utils (run)
import Control.Arrow ((&&&))
import Data.Char (digitToInt)
import Data.Maybe (fromMaybe, isJust, isNothing)
type Input = String
-- alias just to keep functions organized
type UnpackedBlock = [Maybe Int]
type PackedBlock = [Maybe Int]
-- NOTE: Look into segment trees
testInput :: Input
testInput =
prepare
[ "2333133121414131402"
]
-- unpack input string
inflate :: String -> UnpackedBlock
inflate = go 0 0
where
go :: Int -> Int -> String -> UnpackedBlock
go _ _ [] = []
go idx fileId (d : ds) =
let
count = digitToInt d
in
if even idx
then replicate count (Just fileId) <> go (idx + 1) (fileId + 1) ds
else replicate count Nothing <> go (idx + 1) fileId ds
pack :: UnpackedBlock -> PackedBlock
pack block = go 0 block (reverse $ filter isJust block)
where
expectedLen :: Int
expectedLen = uncurry (-) $ (length &&& (length . filter isNothing)) block
go :: Int -> UnpackedBlock -> [Maybe Int] -> PackedBlock
go len (x : xs) rev@(y : ys)
| len >= expectedLen = []
| otherwise =
if isNothing x
then y : go (succ len) xs ys
else x : go (succ len) xs rev
go _ _ _ = []
packWholeFiles :: UnpackedBlock -> PackedBlock
packWholeFiles = undefined
checksum :: PackedBlock -> Int
checksum = sum . zipWith (*) [0 ..] . map (fromMaybe 0)
part1 :: Input -> Int
part1 = checksum . pack . inflate
part2 :: Input -> Int
part2 = checksum . packWholeFiles . inflate
prepare :: [String] -> Input
prepare = head
main :: IO ()
main = run part1 part2 prepare