diff options
author | H.J <thechairman@thechairman.info> | 2024-06-03 17:16:30 -0400 |
---|---|---|
committer | H.J <thechairman@thechairman.info> | 2024-06-03 17:16:30 -0400 |
commit | 23c7ca166ac87a339c6ee6ed71aed41afefb5513 (patch) | |
tree | 904bea816aa94775084dc08ea740ac692112184a /aoc2017-gleam/src/aoc_2017/day_6.gleam | |
parent | a679186bed8e5e284604fab7ef8ac932b66d4d51 (diff) | |
download | gleam_aoc-23c7ca166ac87a339c6ee6ed71aed41afefb5513.tar.gz gleam_aoc-23c7ca166ac87a339c6ee6ed71aed41afefb5513.zip |
gleam 2017 up to day 7 part 1
Diffstat (limited to 'aoc2017-gleam/src/aoc_2017/day_6.gleam')
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_6.gleam | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/aoc2017-gleam/src/aoc_2017/day_6.gleam b/aoc2017-gleam/src/aoc_2017/day_6.gleam new file mode 100644 index 0000000..84222e1 --- /dev/null +++ b/aoc2017-gleam/src/aoc_2017/day_6.gleam @@ -0,0 +1,65 @@ +import gary.{type ErlangArray} +import gary/array +import gleam/bool +import gleam/int +import gleam/list +import gleam/result +import gleam/set.{type Set} +import gleam/string + +pub fn parse(input) -> ErlangArray(Int) { + input + |> string.split("\t") + |> list.map(int.parse) + |> result.values() + |> array.from_list(default: -1) + |> array.make_fixed() +} + +pub fn pt_1(input: ErlangArray(Int)) { + check_cycle(input, set.from_list([input]), 1).1 +} + +pub fn pt_2(input: ErlangArray(Int)) { + let #(target, cycle) = check_cycle(input, set.from_list([input]), 1) + cycle - check_cycle(input, set.from_list([input, target]), 1).1 +} + +fn get_max(array: ErlangArray(Int)) -> #(Int, Int) { + use index, value, max <- array.fold(over: array, from: #(-1, -1)) + case value > max.1 { + True -> #(index, value) + False -> max + } +} + +fn redistribute( + array: ErlangArray(Int), + pointer: Int, + remaining: Int, +) -> ErlangArray(Int) { + use <- bool.guard(remaining == 0, array) + case array.get(from: array, at: pointer) { + Error(_) -> redistribute(array, 0, remaining) + Ok(n) -> { + let assert Ok(updated_array) = + array.set(into: array, at: pointer, put: n + 1) + redistribute(updated_array, pointer + 1, remaining - 1) + } + } +} + +fn check_cycle( + current: ErlangArray(Int), + cache: Set(ErlangArray(Int)), + cycle: Int, +) -> #(ErlangArray(Int), Int) { + let #(index, to_redistribute) = current |> get_max + let assert Ok(zeroed) = array.set(into: current, at: index, put: 0) + let next = redistribute(zeroed, index + 1, to_redistribute) + + case set.contains(cache, next) { + True -> #(next, cycle) + False -> check_cycle(next, set.insert(cache, next), cycle + 1) + } +} |