From eba49e7b761d485fe99d0c19cd578c164855d28c Mon Sep 17 00:00:00 2001 From: Max Duval Date: Wed, 10 Dec 2025 20:01:32 +0000 Subject: [PATCH] feat: 2025 day 10 part 1 --- src/gloat.gleam | 3 + src/solve_2025_10.gleam | 118 ++++++++++++++++++++++++++++++++++++++++ test/test_2025_10.gleam | 24 ++++++++ 3 files changed, 145 insertions(+) create mode 100644 src/solve_2025_10.gleam create mode 100644 test/test_2025_10.gleam diff --git a/src/gloat.gleam b/src/gloat.gleam index 0f7fd78..04a62c1 100644 --- a/src/gloat.gleam +++ b/src/gloat.gleam @@ -14,6 +14,7 @@ import solve_2025_06 import solve_2025_07 import solve_2025_08 import solve_2025_09 +import solve_2025_10 pub fn main() -> Nil { case argv.load().arguments { @@ -40,6 +41,8 @@ pub fn main() -> Nil { display(#(2025, 8), solve_2025_08.part_one, solve_2025_08.part_two) ["2025", "9"] -> display(#(2025, 9), solve_2025_09.part_one, solve_2025_09.part_two) + ["2025", "10"] -> + display(#(2025, 10), solve_2025_10.part_one, solve_2025_10.part_two) ["2025", _] -> io.print("No solutions for 2025") _ -> io.print("Please provide the following arguments: ") } diff --git a/src/solve_2025_10.gleam b/src/solve_2025_10.gleam new file mode 100644 index 0000000..45bdc3f --- /dev/null +++ b/src/solve_2025_10.gleam @@ -0,0 +1,118 @@ +import gleam/float +import gleam/int +import gleam/list +import gleam/result +import gleam/string + +pub fn part_one(input: String) -> Int { + use accumulator, indicator <- list.fold(parse(input), 0) + echo indicator + accumulator + press(indicator, 1) +} + +fn press(indicator: Indicator, presses: Int) { + let max = indicator.buttons |> list.length + + case + list.combinations(indicator.buttons, presses) + |> list.find(fn(buttons) { + // echo #(indicator.diagram |> format, buttons, buttons |> list.map(format)) + indicator.diagram == list.fold(buttons, 0, int.bitwise_exclusive_or) + }) + { + Ok(buttons) -> { + buttons |> list.each(display) + display(indicator.diagram) + presses + } + Error(_) if presses > max -> { + echo "Something awful happened" + 0 + } + Error(_) -> press(indicator, presses + 1) + } +} + +pub fn part_two(input: String) -> Int { + // echo parse(input) + -1 +} + +type Indicator { + Indicator(diagram: Int, buttons: List(Int), joltage: List(Int)) +} + +fn parse(input: String) -> List(Indicator) { + use line <- list.flat_map(string.split(input, "\n")) + let parts = line |> string.split(" ") + + case + parts |> list.flat_map(strip(#("[", "]"), _)), + parts |> list.flat_map(strip(#("(", ")"), _)), + parts |> list.flat_map(strip(#("{", "}"), _)) + { + [diagram], [_, ..] as buttons, [joltage] -> { + let diagram = + diagram + |> string.replace(".", "0") + |> string.replace("#", "1") + |> string.reverse + |> int.base_parse(2) + |> result.unwrap(-1) + let buttons = + buttons + |> list.map(fn(button) { + let digits = + button + |> string.split(",") + |> list.flat_map(digitise) + // |> echo + use accumulator, position <- list.fold(digits, 0) + let mask = + int.power(2, int.to_float(position)) + |> result.unwrap(-1.0) + |> float.truncate + // echo #(position, mask |> int.to_base2) + int.bitwise_or(accumulator, mask) + }) + let joltage = joltage |> string.split(",") |> list.flat_map(digitise) + [Indicator(diagram:, buttons:, joltage:)] + } + _, _, _ -> [] + } + // todo + // +} + +/// Could be made generic with `parser: fn(String) -> Result(a, b)` +fn digitise(value: String) { + case int.parse(value) { + Ok(digit) -> [digit] + Error(_) -> [] + } +} + +/// Makes a bitmask easy to view and debug +/// - `0000000001` ← 1 +/// - `0000000011` ← 3 +/// - `0000101010` ← 42 +fn format(value: Int) { + value |> int.to_base2 |> string.pad_start(10, "0") +} + +fn display(value: Int) { + echo #(format(value), value) + value +} + +fn strip(sides: #(String, String), part: String) -> List(String) { + let #(prefix, suffix) = sides + case part |> string.starts_with(prefix) && part |> string.ends_with(suffix) { + True -> [ + part + |> string.drop_start(string.length(prefix)) + |> string.drop_end(string.length(suffix)), + ] + False -> [] + } +} diff --git a/test/test_2025_10.gleam b/test/test_2025_10.gleam new file mode 100644 index 0000000..3cb5ad7 --- /dev/null +++ b/test/test_2025_10.gleam @@ -0,0 +1,24 @@ +import gleam/string +import solve_2025_10 + +const input = " +[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7} +[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2} +[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5} +" + +pub fn part_one_test() { + let result = + input + |> string.trim + |> solve_2025_10.part_one + assert result == 7 +} + +pub fn part_two_test() { + let result = + input + |> string.trim + |> solve_2025_10.part_two + assert result == -1 +} -- 2.51.2