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 operands

Part 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 operators

Code

You can get the code from Codeberg.