-
Notifications
You must be signed in to change notification settings - Fork 0
/
05b.hs
53 lines (41 loc) · 1.63 KB
/
05b.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
-- ghc 05b.hs
-- Runtime: 92m27s :')
data SeedRange = SeedRange Int Int Int
parseRange :: String -> SeedRange
parseRange line =
case (map read . words $ line) of
(dest:src:len:[]) -> SeedRange dest src len
parseMapsImpl :: [String] -> [[SeedRange]] -> [[SeedRange]]
parseMapsImpl [] result = result
parseMapsImpl (line:rest) result =
if line == ""
then parseMapsImpl (drop 1 rest) ([]:result)
else case result of
(ranges:rest2) -> parseMapsImpl rest (((parseRange line):ranges):rest2)
_ -> parseMapsImpl rest result
parseMaps :: [String] -> [[SeedRange]]
parseMaps lines = parseMapsImpl lines []
chunked :: [Int] -> [(Int, Int)]
chunked [] = []
chunked (x:y:xs) = ((x,y):(chunked xs))
parse :: [String] -> ([(Int, Int)], [[SeedRange]])
parse (seedStr:rest) = (chunked . map read . drop 1 . words $ seedStr, parseMaps rest)
traverseRanges :: [SeedRange] -> Int -> Int
traverseRanges [] seed = seed
traverseRanges ((SeedRange dest src len):rest) seed =
if src <= seed && seed < src + len
then seed - src + dest
else traverseRanges rest seed
traverseMaps :: [[SeedRange]] -> Int -> Int
traverseMaps [] seed = seed
traverseMaps (ranges:rest) seed = traverseMaps rest (traverseRanges ranges seed)
minOf :: (Int -> Int) -> [(Int, Int)] -> Int
minOf f [] = 2^60
minOf f ((start, 0):rest) = minOf f rest
minOf f ((start, len):rest) =
min (f start) (minOf f ((start + 1, len - 1):rest))
calculate :: ([(Int, Int)], [[SeedRange]]) -> Int
calculate (seeds, maps) = minOf (traverseMaps (reverse maps)) seeds
solve :: [String] -> String
solve = (++ "\n") . show . calculate . parse
main = interact (solve . lines)