diff options
Diffstat (limited to 'aoc2017-gleam/src/aoc_2017/day_14.gleam')
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_14.gleam | 79 |
1 files changed, 77 insertions, 2 deletions
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 + } } |