diff options
Diffstat (limited to 'aoc2023')
-rw-r--r-- | aoc2023/src/day9/.gitignore | 1 | ||||
-rw-r--r-- | aoc2023/src/day9/solve.gleam | 69 | ||||
-rw-r--r-- | aoc2023/test/day9/day9_test.gleam | 52 |
3 files changed, 122 insertions, 0 deletions
diff --git a/aoc2023/src/day9/.gitignore b/aoc2023/src/day9/.gitignore new file mode 100644 index 0000000..ae40cea --- /dev/null +++ b/aoc2023/src/day9/.gitignore @@ -0,0 +1 @@ +input.txt
\ No newline at end of file diff --git a/aoc2023/src/day9/solve.gleam b/aoc2023/src/day9/solve.gleam new file mode 100644 index 0000000..ce061ae --- /dev/null +++ b/aoc2023/src/day9/solve.gleam @@ -0,0 +1,69 @@ +import adglent.{First, Second} +import gleam/io +import gleam/list +import gleam/string +import gleam/int + +fn parse(input: String, backwards backwards: Bool) -> List(List(Int)) { + use line <- list.map(string.split(input, "\n")) + use n_str <- list.map(maybe_backwards(string.split(line, " "), backwards)) + let assert Ok(n) = int.parse(n_str) + n +} + +fn maybe_backwards(xs: List(a), backwards: Bool) -> List(a) { + case backwards { + False -> list.reverse(xs) + True -> xs + } +} + +fn is_constant(ns: List(Int)) -> Bool { + case list.unique(ns) { + [_] -> True + _ -> False + } +} + +fn take_derivative(ns: List(Int)) -> List(Int) { + ns + |> list.window_by_2 + |> list.map(fn(tup) { tup.0 - tup.1 }) +} + +fn extrapolate(ns: List(Int)) { + case is_constant(ns), ns { + True, [n, ..] -> n + False, [n, ..] -> n + extrapolate(take_derivative(ns)) + } +} + +fn part(input: String, backwards backwards: Bool) { + input + |> parse(backwards: backwards) + |> list.fold(0, fn(acc, ns) { extrapolate(ns) + acc }) + |> string.inspect +} + +pub fn part1(input: String) { + part(input, backwards: False) +} + +pub fn part2(input: String) { + part(input, backwards: True) +} + +pub fn main() { + let assert Ok(part) = adglent.get_part() + let assert Ok(input) = adglent.get_input("9") + case part { + First -> + part1(input) + |> adglent.inspect + |> io.println + Second -> + part2(input) + |> adglent.inspect + |> io.println + } +} diff --git a/aoc2023/test/day9/day9_test.gleam b/aoc2023/test/day9/day9_test.gleam new file mode 100644 index 0000000..84fd3ba --- /dev/null +++ b/aoc2023/test/day9/day9_test.gleam @@ -0,0 +1,52 @@ +import gleam/list +import showtime/tests/should +import adglent.{type Example, Example} +import day9/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( + "0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45", + "114", + ), +] + +/// Add examples for part 2 here: +/// ```gleam +///const part2_examples: List(Example(Problem2AnswerType)) = [Example("some input", "")] +/// ``` +const part2_examples: List(Example(Problem2AnswerType)) = [ + Example( + "0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45", + "2", + ), +] + +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) +} |