diff options
author | H.J <thechairman@thechairman.info> | 2024-06-17 15:10:31 -0400 |
---|---|---|
committer | H.J <thechairman@thechairman.info> | 2024-06-17 15:10:31 -0400 |
commit | 413891726756aed407a2cfbceb4cf0e14bbcc982 (patch) | |
tree | 4b970eb97a54bcf84e01eea225a62f4ead7b621c | |
parent | 70fda8e4513d6de7d1a2cc6c701b7ae36cd83850 (diff) | |
download | gleam_aoc-413891726756aed407a2cfbceb4cf0e14bbcc982.tar.gz gleam_aoc-413891726756aed407a2cfbceb4cf0e14bbcc982.zip |
gleam 2017 day 14 complete
-rw-r--r-- | aoc2017-gleam/gleam.toml | 2 | ||||
-rw-r--r-- | aoc2017-gleam/manifest.toml | 2 | ||||
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_14.gleam | 79 | ||||
-rw-r--r-- | aoc2017-gleam/src/helpers/state.gleam | 55 |
4 files changed, 136 insertions, 2 deletions
diff --git a/aoc2017-gleam/gleam.toml b/aoc2017-gleam/gleam.toml index 669a48d..b1de573 100644 --- a/aoc2017-gleam/gleam.toml +++ b/aoc2017-gleam/gleam.toml @@ -16,6 +16,8 @@ version = "1.0.0" gleam_stdlib = ">= 0.34.0 and < 2.0.0" gladvent = ">= 0.7.3 and < 1.0.0" gary = ">= 1.0.1 and < 2.0.0" +gleam_otp = ">= 0.10.0 and < 1.0.0" +gleam_erlang = ">= 0.25.0 and < 1.0.0" [dev-dependencies] gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/aoc2017-gleam/manifest.toml b/aoc2017-gleam/manifest.toml index e078678..cda0b5b 100644 --- a/aoc2017-gleam/manifest.toml +++ b/aoc2017-gleam/manifest.toml @@ -29,5 +29,7 @@ packages = [ [requirements] gary = { version = ">= 1.0.1 and < 2.0.0" } gladvent = { version = ">= 0.7.3 and < 1.0.0" } +gleam_erlang = { version = ">= 0.25.0 and < 1.0.0"} +gleam_otp = { version = ">= 0.10.0 and < 1.0.0" } gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } gleeunit = { version = ">= 1.0.0 and < 2.0.0" } diff --git a/aoc2017-gleam/src/aoc_2017/day_14.gleam b/aoc2017-gleam/src/aoc_2017/day_14.gleam index a0a1145..cd60a74 100644 --- a/aoc2017-gleam/src/aoc_2017/day_14.gleam +++ b/aoc2017-gleam/src/aoc_2017/day_14.gleam @@ -1,7 +1,82 @@ +import aoc_2017/day_10.{pt_2 as knot} +import gleam/int +import gleam/list +import gleam/result +import gleam/set +import gleam/string +import helpers/state + pub fn pt_1(input: String) { - todo as "part 1 not implemented" + use acc, row <- list.fold(make_rows(input), 0) + let count = row |> knot() |> popcount() + acc + count +} + +fn make_rows(input: String) { + use row <- list.map(list.range(0, 127)) + input <> "-" <> int.to_string(row) +} + +fn popcount(hex_number: String) -> Int { + let assert Ok(n) = int.base_parse(hex_number, 16) + let assert Ok(digits) = int.digits(n, 2) + + use acc, digit <- list.fold(digits, 0) + case digit { + 1 -> acc + 1 + _ -> acc + } } pub fn pt_2(input: String) { - todo as "part 2 not implemented" + let grid = state.start_actor(make_grid(input)) + + find_next_group(grid, 0) +} + +fn make_grid(input: String) { + let raw_grid = + list.map(make_rows(input), fn(row) { + row + |> knot() + |> int.base_parse(16) + |> result.map(int.to_base2) + |> result.map(string.pad_left(_, with: "0", to: 128)) + |> result.map(string.to_graphemes) + }) + |> result.values + + { + use total_acc, row, i <- list.index_fold(raw_grid, set.new()) + use acc, bit, j <- list.index_fold(row, total_acc) + case bit { + "1" -> set.insert(acc, #(i, j)) + _zero -> acc + } + } +} + +fn find_next_group(actor, count) { + case state.pop(actor) { + Ok(p) -> { + list.each(neighbors(p), remove_neighbor(actor, _)) + find_next_group(actor, count + 1) + } + Error(Nil) -> count + } +} + +fn neighbors(of: #(Int, Int)) { + let #(i, j) = of + [#(i + 1, j), #(i - 1, j), #(i, j + 1), #(i, j - 1)] +} + +fn remove_neighbor(actor, point) { + case state.check(actor, point) { + True -> { + state.drop(actor, point) + list.each(neighbors(point), remove_neighbor(actor, _)) + } + False -> Nil + } } diff --git a/aoc2017-gleam/src/helpers/state.gleam b/aoc2017-gleam/src/helpers/state.gleam new file mode 100644 index 0000000..cbbad81 --- /dev/null +++ b/aoc2017-gleam/src/helpers/state.gleam @@ -0,0 +1,55 @@ +import gleam/erlang/process.{type Subject, Normal} +import gleam/option.{None} +import gleam/otp/actor.{type Next, Continue, Stop} +import gleam/set.{type Set} + +const timeout = 1000 + +pub type Message(k) { + Shutdown + Check(key: k, client: Subject(Bool)) + Add(key: k) + Drop(key: k) + Pop(client: Subject(Result(k, Nil))) +} + +fn handle_message(message: Message(k), set: Set(k)) -> Next(Message(k), Set(k)) { + case message { + Shutdown -> Stop(Normal) + Check(key, client) -> { + process.send(client, set.contains(set, key)) + Continue(set, None) + } + Add(key) -> Continue(set.insert(set, key), None) + Drop(key) -> Continue(set.delete(set, key), None) + Pop(client) -> { + case set.to_list(set) { + [next, ..] -> { + process.send(client, Ok(next)) + Continue(set.delete(set, next), None) + } + [] -> { + process.send(client, Error(Nil)) + Stop(Normal) + } + } + } + } +} + +pub fn start_actor(with: Set(a)) { + let assert Ok(actor) = actor.start(with, handle_message) + actor +} + +pub fn pop(actor) { + process.call(actor, Pop, timeout) +} + +pub fn check(actor, value) { + process.call(actor, Check(value, _), timeout) +} + +pub fn drop(actor, value) { + process.send(actor, Drop(value)) +} |