I really enjoyed today's puzzle. At first glance, it seems pretty complicated, but if you know how to code up a backtracking algorithm, there isn't too much else to it. I refactored my solution to part 1 to make solving part 2 straightforward. It took a while to run, but I didn't have to implement caching to get it to finish in a reasonable time. Well, that's all I have for today:
import gleam/int import gleam/io import gleam/list.{Continue, Stop} import gleam/string import gleam/result import simplifile as file const example = " 190: 10 19 3267: 81 40 27 83: 17 5 156: 15 6 7290: 6 8 6 15 161011: 16 10 13 192: 17 8 14 21037: 9 7 18 13 292: 11 6 16 20 " pub fn main() { let assert Ok(input) = file.read("input") let assert 3749 = part1(example) let assert 11387 = part2(example) part1(input) |> int.to_string |> io.println part2(input) |> int.to_string |> io.println } fn parse_input(input: String) -> List(#(Int, List(Int))) { input |> string.trim |> string.split("\n") |> list.map(fn(line) { let assert [result, params] = string.split(line, ":") let assert Ok(result) = int.parse(result) let params = params |> string.trim |> string.split(" ") |> list.map(fn(param) { param |> int.parse |> result.unwrap(0) }) #(result, params) }) } type EquationResult { Solvable Unsolvable } fn solve_equation(result: Int, params: List(Int), operators: List(fn(Int, Int) -> Int)) -> EquationResult { case params { [a] if a == result -> Solvable [a] -> Unsolvable [a, b, ..rest] -> { list.fold_until(operators, Unsolvable, fn(solvable, op) { case solve_equation(result, [op(a, b), ..rest], operators) { Unsolvable -> Continue(solvable) Solvable -> Stop(Solvable) } }) } _ -> Unsolvable } } fn calibration_result(input: String, operators: List(fn(Int, Int) -> Int)) -> Int { input |> parse_input |> list.fold(0, fn(count, equation) { let #(result, params) = equation case solve_equation(result, params, operators) { Solvable -> count + result Unsolvable -> count } }) } fn part1(input: String) -> Int { calibration_result(input, [int.multiply, int.add]) } fn concat(a: Int, b: Int) -> Int { int.to_string(a) |> string.append(int.to_string(b)) |> int.parse |> result.unwrap(0) } fn part2(input: String) -> Int { calibration_result(input, [int.multiply, int.add, concat]) }
Top comments (0)