diff --git a/gleam.toml b/gleam.toml index ea628b8..0cee624 100644 --- a/gleam.toml +++ b/gleam.toml @@ -12,6 +12,7 @@ gleam_stdlib = ">= 0.44.0 and < 1.0.0" argv = ">= 1.0.2 and < 2.0.0" simplifile = ">= 2.3.1 and < 3.0.0" gleam_yielder = ">= 1.1.0 and < 2.0.0" +gleam_regexp = ">= 1.1.1 and < 2.0.0" [dev-dependencies] gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/manifest.toml b/manifest.toml index 1732e2a..95f2da0 100644 --- a/manifest.toml +++ b/manifest.toml @@ -4,6 +4,7 @@ packages = [ { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" }, { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" }, + { name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" }, { name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" }, { name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" }, { name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" }, @@ -12,6 +13,7 @@ packages = [ [requirements] argv = { version = ">= 1.0.2 and < 2.0.0" } +gleam_regexp = { version = ">= 1.1.1 and < 2.0.0" } gleam_stdlib = { version = ">= 0.44.0 and < 1.0.0" } gleam_yielder = { version = ">= 1.1.0 and < 2.0.0" } gleeunit = { version = ">= 1.0.0 and < 2.0.0" } diff --git a/src/gloat.gleam b/src/gloat.gleam index cffdc49..157cfd6 100644 --- a/src/gloat.gleam +++ b/src/gloat.gleam @@ -10,6 +10,7 @@ import solve_2025_02 import solve_2025_03 import solve_2025_04 import solve_2025_05 +import solve_2025_06 pub fn main() -> Nil { case argv.load().arguments { @@ -28,6 +29,8 @@ pub fn main() -> Nil { display(#(2025, 4), solve_2025_04.part_one, solve_2025_04.part_two) ["2025", "5"] -> display(#(2025, 5), solve_2025_05.part_one, solve_2025_05.part_two) + ["2025", "6"] -> + display(#(2025, 6), solve_2025_06.part_one, solve_2025_06.part_two) ["2025", _] -> io.print("No solutions for 2025") _ -> io.print("Please provide the following arguments: ") } diff --git a/src/solve_2025_06.gleam b/src/solve_2025_06.gleam new file mode 100644 index 0000000..4d73323 --- /dev/null +++ b/src/solve_2025_06.gleam @@ -0,0 +1,106 @@ +import gleam/int +import gleam/list +import gleam/pair +import gleam/regexp +import gleam/string + +type Problem { + Problem(operation: fn(Int, Int) -> Int, numbers: List(Int)) +} + +pub fn part_one(input: String) -> Int { + let parse = fn(input: String) -> List(Problem) { + let assert Ok(re) = regexp.from_string(" +") + + let problems = + input + |> string.trim + |> string.split("\n") + |> list.map(fn(line) { + line + |> string.replace(" ", "") + |> string.trim + |> regexp.split(re, _) + |> list.map(string.trim) + }) + |> list.transpose + + use problem <- list.flat_map(problems) + + let to_numbers = fn(strings: List(String)) -> List(Int) { + use string <- list.flat_map(strings) + case int.parse(string) { + Ok(number) -> [number] + Error(_) -> [] + } + } + + case problem |> list.reverse { + ["+", ..rest] -> [Problem(int.add, to_numbers(rest))] + ["*", ..rest] -> [Problem(int.multiply, to_numbers(rest))] + _ -> [] + } + } + + use accumulator, problem <- list.fold(parse(input), 0) + case list.reduce(problem.numbers, problem.operation) { + Ok(solution) -> accumulator + solution + Error(_) -> accumulator + } +} + +pub fn part_two(input: String) -> Int { + // let assert Ok(re) = regexp.from_string("[  ]+") + + let parse = fn(input: String) -> List(Problem) { + let columns = + input + |> string.split("\n") + |> list.map(string.to_graphemes) + |> list.transpose + |> list.reverse + + let #(problems, _) = { + use accumulator: #(List(Problem), List(Int)), column <- list.fold( + columns, + #([], []), + ) + let #(problems, numbers) = accumulator + + let val = + string.join(column, "") |> string.replace(" ", "") |> string.trim + + let operation = case + val |> string.ends_with("+"), + val |> string.ends_with("*") + { + True, _ -> Ok(int.add) + _, True -> Ok(int.multiply) + False, False -> Error(Nil) + } + + let number = + val + |> string.replace("+", "") + |> string.replace("*", "") + |> string.trim + |> int.parse + + case operation, number { + Ok(operation), Ok(number) -> #( + [Problem(operation, [number, ..numbers]), ..problems], + [], + ) + Error(_), Ok(number) -> #(problems, [number, ..numbers]) + _, _ -> accumulator + } + } + problems + } + + use accumulator, problem <- list.fold(parse(input), 0) + case list.reduce(problem.numbers, problem.operation) { + Ok(solution) -> accumulator + solution + Error(_) -> accumulator + } +} diff --git a/test/test_2025_06.gleam b/test/test_2025_06.gleam new file mode 100644 index 0000000..c602b76 --- /dev/null +++ b/test/test_2025_06.gleam @@ -0,0 +1,24 @@ +import gleam/string +import solve_2025_06 + +const input = " +123 328 51 64  + 45 64 387 23  + 6 98 215 314 +* + * +  " + +pub fn part_one_test() { + let result = + input + |> string.trim + |> solve_2025_06.part_one + assert result == 4_277_556 +} + +pub fn part_two_test() { + let result = + input + |> string.trim + |> solve_2025_06.part_two + assert result == 3_263_827 +}