Day 6 was all about the data input; the actual "calculating the answer" part was almost trivial.
Part 1
We're given some arithmetic problems, written in columns, like this:
123 328 51 64
45 64 387 23
6 98 215 314
* + * + The task is to solve each column.
My first thought was to read the data file as a traditional parsing problem. There were some headaches with that, making sure the whitespace was consumed in the right places. But overall, it wasn't too hard.
data Operator = Add | Mul deriving (Show, Eq)
sumsP = (,) <$> (operandsP <* endOfLine) <*> operatorLineP
operandsP = operandLineP `sepBy` endOfLine
operandLineP = ((many spP) *> (decimal `sepBy1` (many1 spP))) <* (many spP)
operatorLineP = ((many spP) *> (operatorP `sepBy1` (many1 spP))) <* (many spP)
operatorP = (Add <$ "+") <|> (Mul <$ "*")
spP = char ' 'That gave me a list of list of operands, row-wise. I transpose that to get it column-wise, then do the calculations as a zip with a helper.
part1 text = calculateAll (transpose operands) operators
where (operands, operators) = successfulParse text
calculateAll :: [[Int]] -> [Operator] -> Int
calculateAll operands operators = sum $ zipWith calculate operators operands
calculate :: Operator -> [Int] -> Int
calculate Add operands = sum operands
calculate Mul operands = product operandsPart 2
Now I have to treat the input as separate columns. I'd love to say I had a grand plan for solving this, but I ended up mucking around in the repl, hacking away until I got something in the right shape.
My process went like this.
Read the text, split it into lines.
ghci> text <- readFile "../data/advent06a.txt"
ghci> lines text
["123 328 51 64 "," 45 64 387 23 "," 6 98 215 314","* + * + "]Split the lines into the operands and operators.
ghci> fromJust $ unsnoc $ lines text
(["123 328 51 64 "," 45 64 387 23 "," 6 98 215 314"],"* + * + ")
ghci> (operands, operators) = fromJust $ unsnoc $ lines text
ghci> operands
["123 328 51 64 "," 45 64 387 23 "," 6 98 215 314"]
ghci> operators
"* + * + "Transpose the operands so they're given column-wise.
ghci> transpose operands
["1 ","24 ","356"," ","369","248","8 "," "," 32","581","175"," ","623","431"," 4"]The blank columns become blank strings. Use them to split the operands into their separate calculations.
ghci> splitWhen (all isSpace) $ transpose operands
[["1 ","24 ","356"],["369","248","8 "],[" 32","581","175"],["623","431"," 4"]]Use read to convert all the strings into numbers.
readOperands :: [[String]] -> [[Int]]
readOperands = fmap (fmap read)
ghci> readOperands $ splitWhen (all isSpace) $ transpose operands
[[1,24,356],[369,248,8],[32,581,175],[623,431,4]]That gives me the correct operands for the sums. I can use the same calculateAll function to do all the sums. Here's the final solution.
part2 text = calculateAll operands'' operators'
where strs = lines $ unpack text
(operands, operators) = fromJust $ unsnoc strs
operands' = splitWhen (all isSpace) $ transpose operands
operands'' = readOperands operands'
operators' = parseOperators $ pack operatorsCode
You can get the code from Codeberg.