diff options
Diffstat (limited to 'aoc2023-gleam/src/day12')
-rw-r--r-- | aoc2023-gleam/src/day12/.gitignore | 1 | ||||
-rw-r--r-- | aoc2023-gleam/src/day12/solve.gleam | 91 |
2 files changed, 92 insertions, 0 deletions
diff --git a/aoc2023-gleam/src/day12/.gitignore b/aoc2023-gleam/src/day12/.gitignore new file mode 100644 index 0000000..ae40cea --- /dev/null +++ b/aoc2023-gleam/src/day12/.gitignore @@ -0,0 +1 @@ +input.txt
\ No newline at end of file diff --git a/aoc2023-gleam/src/day12/solve.gleam b/aoc2023-gleam/src/day12/solve.gleam new file mode 100644 index 0000000..06c7098 --- /dev/null +++ b/aoc2023-gleam/src/day12/solve.gleam @@ -0,0 +1,91 @@ +import adglent.{First, Second} +import gleam/io +import gleam/string +import gleam/list +import gleam/int +import gleam/result +import utilities/memo.{type Cache} + +type ParserState = + #(String, List(Int), Int, Bool) + +fn parse_folds(input: String, folds: Int) { + let records = string.split(input, "\n") + use record <- list.map(records) + let assert Ok(#(template, sets_str)) = string.split_once(record, " ") + + let template = + template + |> list.repeat(folds) + |> list.intersperse("?") + |> string.concat + let sets = + sets_str + |> string.split(",") + |> list.map(int.parse) + |> result.values + |> list.repeat(folds) + |> list.flatten() + + #(template, sets) +} + +fn do_count( + template: String, + groups: List(Int), + left: Int, + gap: Bool, + cache: Cache(ParserState, Int), +) -> Int { + use <- memo.memoize(cache, #(template, groups, left, gap)) + case template, groups, left, gap { + "", [], 0, _ -> 1 + "?" <> t_rest, [g, ..g_rest], 0, False -> + do_count(t_rest, g_rest, g - 1, g == 1, cache) + { + do_count(t_rest, groups, 0, False, cache) + } + "?" <> t_rest, [], 0, False + | "?" <> t_rest, _, 0, True + | "." <> t_rest, _, 0, _ -> do_count(t_rest, groups, 0, False, cache) + "#" <> t_rest, [g, ..g_rest], 0, False -> + do_count(t_rest, g_rest, g - 1, g == 1, cache) + "?" <> t_rest, gs, l, False | "#" <> t_rest, gs, l, False -> + do_count(t_rest, gs, l - 1, l == 1, cache) + _, _, _, _ -> 0 + } +} + +fn count_solutions(acc: Int, condition: #(String, List(Int))) -> Int { + use cache: Cache(ParserState, Int) <- memo.create() + let #(template, groups) = condition + acc + do_count(template, groups, 0, False, cache) +} + +pub fn part1(input: String) { + input + |> parse_folds(1) + |> list.fold(0, count_solutions) + |> string.inspect +} + +pub fn part2(input: String) { + input + |> parse_folds(5) + |> list.fold(0, count_solutions) + |> string.inspect +} + +pub fn main() { + let assert Ok(part) = adglent.get_part() + let assert Ok(input) = adglent.get_input("12") + case part { + First -> + part1(input) + |> adglent.inspect + |> io.println + Second -> + part2(input) + |> adglent.inspect + |> io.println + } +} |