-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDay06.hs
More file actions
76 lines (64 loc) · 2.81 KB
/
Day06.hs
File metadata and controls
76 lines (64 loc) · 2.81 KB
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
module Day06 (task01, task02) where
import Data.List.Split hiding (chunk)
import Utils
-- import Debug.Trace
task01 :: String -> String
task01 content =
let ls = lines content
(argument_lists, operators) = parseLines ls
in show $ sumOperations argument_lists operators
task02 :: String -> String
task02 content =
let ls = lines content
(operators, interval_lengths) = parseOperators2 ls
argument_lists = parseLines2 ls interval_lengths
in show $ sumOperations argument_lists operators
parseLines :: [String] -> ([[String]], [Char])
parseLines [] = ([], [])
parseLines (line:rest) =
let (argument_lists, operators) = parseLines rest
arguments_or_operators = words line
start = head arguments_or_operators
in
if start == "*" || start == "+"
then (argument_lists, map head arguments_or_operators)
else
let new_argument_lists = if null argument_lists
then map (: []) arguments_or_operators
else zipWith (:) arguments_or_operators argument_lists
in (new_argument_lists, operators)
sumOperations :: [[String]] -> [Char] -> Int
sumOperations argument_lists operations = sum $ applyOperations argument_lists operations
applyOperations :: [[String]] -> [Char] -> [Int]
applyOperations = zipWith applyOperation
applyOperation :: [String] -> Char -> Int
applyOperation arguments operator
| operator == '+' = sum $ map stringToInt arguments
| operator == '*' = product $ map stringToInt arguments
| otherwise = error "This should not be reachable."
parseLines2 :: [String] -> [Int] -> [[String]]
parseLines2 [] _ = error "Should not be reached."
parseLines2 (line:rest) interval_lengths
| head line == '+' || head line == '*' = map (\l -> replicate (l-1) "") interval_lengths
| otherwise =
let argument_lists = parseLines2 rest interval_lengths
in parseLine2 line interval_lengths argument_lists
parseLine2 :: String -> [Int] -> [[String]] -> [[String]]
parseLine2 _ [] argument_lists = argument_lists
parseLine2 _ _ [] = error "Should not be reached."
parseLine2 line (l:interval_lengths) (arguments:argument_lists) =
let (unstripped_chunk, rest) = splitAt l line
chunk = take (l - 1) unstripped_chunk
new_arguments = parseChunk chunk arguments
in new_arguments:parseLine2 rest interval_lengths argument_lists
parseOperators2 :: [String] -> ([Char], [Int])
parseOperators2 [] = error "Should not be reached"
parseOperators2 (line:rest)
| head line == '+' || head line == '*' = unzip $ map (\op -> (head op, length op)) (drop 1 $ split (keepDelimsL $ oneOf "*+") (line ++ " "))
| otherwise = parseOperators2 rest
parseChunk :: String -> [String] -> [String]
parseChunk = zipWith parseNumber
parseNumber :: Char -> String -> String
parseNumber digit number
| digit == ' ' = number
| otherwise = digit:number