-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday05.hs
76 lines (63 loc) · 2.84 KB
/
day05.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
import Data.List
import Data.List.Split (splitOn)
import Control.Monad ((>=>))
import Control.Arrow ((>>>),(&&&),(***))
main = let day = "05" in do
txt <- readFile (day<>".txt")
putStrLn ("Opening Advent calendar door "<>day<>" where")
putStrLn (" part 1 = "<>show (solve1 txt))
putStrLn (" part 2 = "<>show (solve2 txt))
solve1 = minimum . mapAll . (id *** chainr . map converter) . parse
where mapAll (seeds, f) = map f seeds
converter :: [(Int,Int,Int)] -> Int -> Int
converter [] v = v
converter ((dst,src,len):mappings) v
| src <= v&&v < src+len = (+) (dst-src) v
| otherwise = converter mappings v
solve2 = fst . minimum . catMapAll . (intervals *** bindr . map iconverter) . parse
where catMapAll (vals, m) = concatMap m vals
iconverter :: [(Int,Int,Int)] -> (Int,Int) -> [(Int,Int)]
iconverter [] i = [i]
iconverter ((dst,src,len):mappings) i =
let (moved,leftovers) = mapWithin (src,src+len-1) (dst-src) i
in moved ++ concatMap (iconverter mappings) leftovers
where
mapWithin (l,r) d (il,ir)
| r< il || ir <l = ([], [(il,ir)])
| l<=il && ir<=r = ([(il+d,ir+d)], [ ])
| l<=il && r <ir = ([(il+d, r+d)], [ (r+1,ir)])
| il< l && ir<=r = ([( l+d,ir+d)], [(il,l-1) ])
| il< l && r <ir = ([( l+d, r+d)], [(il,l-1),(r+1,ir)])
intervals [] = []
intervals (start:len:rest) = (start,start+len-1) : intervals rest
parse :: String -> ([Int], [[(Int,Int,Int)]])
parse = (parseSeeds . head &&& map parseMap . tail) . splitOn "\n\n"
where parseSeeds = map read . words . drop 6
parseMap = map perLine . tail . lines
perLine = (\[dst,src,len] -> (dst,src,len)) . map read . words
chainr :: Foldable t => t (a -> a) -> (a -> a)
chainr = foldr (>>>) id
bindr :: (Foldable t,Monad m) => t (a -> m a) -> a -> m a
bindr = foldr (>=>) return
{-NOTE old solution
solve1 = minimum . applyMaps . parse
where applyMaps (seeds,maps) = map (chainr (converter <$> maps)) seeds
converter mapping v = foldr (\(dst,src,len) x -> if src<=v&&v<src+len then v-src+dst else x) v mapping-}
{-NOTE unused helpers
chainl :: Foldable t => t (a -> a) -> (a -> a)
chainl = foldr (.) id
bindl :: (Foldable t,Monad m) => t (a -> m a) -> a -> m a
bindl = foldr (<=<) return
-- NOTICE that
-- foldl (.) id .=. foldr (.) id
-- i.e.
-- chainl .=. chainr
-- Therefore we instead use 'l' and 'r' to denote *direction* of composition
-- chainl [f,g,h] = (f . g . h)
-- chainr [f,g,h] = (f >>> g >>> h)
-- bindl [f,g,h] = (f <=< g <=< h)
-- bindr [f,g,h] = (f >=> g >=> h)
-- Maybe we should call them
-- chainf, bindf (function; or forward..)
-- chainb, bindb (binding; or backward..)
-- instead?? that may make it even more confusing xD -}