diff options
-rw-r--r-- | aoc2023/src/day12/.gitignore | 1 | ||||
-rw-r--r-- | aoc2023/src/day12/solve.gleam | 80 | ||||
-rw-r--r-- | aoc2023/test/day12/day12_test.gleam | 48 |
3 files changed, 129 insertions, 0 deletions
diff --git a/aoc2023/src/day12/.gitignore b/aoc2023/src/day12/.gitignore new file mode 100644 index 0000000..ae40cea --- /dev/null +++ b/aoc2023/src/day12/.gitignore @@ -0,0 +1 @@ +input.txt
\ No newline at end of file diff --git a/aoc2023/src/day12/solve.gleam b/aoc2023/src/day12/solve.gleam new file mode 100644 index 0000000..578fa5f --- /dev/null +++ b/aoc2023/src/day12/solve.gleam @@ -0,0 +1,80 @@ +import adglent.{First, Second} +import gleam/io +import gleam/string +import gleam/list +import gleam/int +import gleam/result +import gleam/dict.{type Dict} + +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) -> Int { + case template, groups, left, gap { + "", [], 0, _ -> 1 + "?" <> t_rest, [g, ..g_rest], 0, False -> + do_count(t_rest, g_rest, g - 1, g == 1) + { + do_count(t_rest, groups, 0, False) + } + "?" <> t_rest, [], 0, False + | "?" <> t_rest, _, 0, True + | "." <> t_rest, _, 0, _ -> do_count(t_rest, groups, 0, False) + "#" <> t_rest, [g, ..g_rest], 0, False -> + do_count(t_rest, g_rest, g - 1, g == 1) + "?" <> t_rest, gs, l, False | "#" <> t_rest, gs, l, False -> + do_count(t_rest, gs, l - 1, l == 1) + _, _, _, _ -> 0 + } +} + +fn count_solutions(acc: Int, condition: #(String, List(Int))) -> Int { + let #(template, groups) = condition + acc + do_count(template, groups, 0, False) +} + +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 + } +} diff --git a/aoc2023/test/day12/day12_test.gleam b/aoc2023/test/day12/day12_test.gleam new file mode 100644 index 0000000..3daf0e9 --- /dev/null +++ b/aoc2023/test/day12/day12_test.gleam @@ -0,0 +1,48 @@ +import gleam/list +import showtime/tests/should +import adglent.{type Example, Example} +import day12/solve + +type Problem1AnswerType = + String + +type Problem2AnswerType = + String + +/// Add examples for part 1 here: +/// ```gleam +///const part1_examples: List(Example(Problem1AnswerType)) = [Example("some input", "")] +/// ``` +const part1_examples: List(Example(Problem1AnswerType)) = [ + Example( + "???.### 1,1,3 +.??..??...?##. 1,1,3 +?#?#?#?#?#?#?#? 1,3,1,6 +????.#...#... 4,1,1 +????.######..#####. 1,6,5 +?###???????? 3,2,1", + "21", + ), +] + +/// Add examples for part 2 here: +/// ```gleam +///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")] +/// ``` +const part2_examples: List(Example(Problem2AnswerType)) = [] + +pub fn part1_test() { + part1_examples + |> should.not_equal([]) + use example <- list.map(part1_examples) + solve.part1(example.input) + |> should.equal(example.answer) +} + +pub fn part2_test() { + part2_examples + |> should.not_equal([]) + use example <- list.map(part2_examples) + solve.part2(example.input) + |> should.equal(example.answer) +} |