aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J <thechairman@thechairman.info>2024-06-17 15:10:31 -0400
committerH.J <thechairman@thechairman.info>2024-06-17 15:10:31 -0400
commit413891726756aed407a2cfbceb4cf0e14bbcc982 (patch)
tree4b970eb97a54bcf84e01eea225a62f4ead7b621c
parent70fda8e4513d6de7d1a2cc6c701b7ae36cd83850 (diff)
downloadgleam_aoc-413891726756aed407a2cfbceb4cf0e14bbcc982.tar.gz
gleam_aoc-413891726756aed407a2cfbceb4cf0e14bbcc982.zip
gleam 2017 day 14 complete
-rw-r--r--aoc2017-gleam/gleam.toml2
-rw-r--r--aoc2017-gleam/manifest.toml2
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_14.gleam79
-rw-r--r--aoc2017-gleam/src/helpers/state.gleam55
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))
+}