diff options
author | Tomasz Chojnacki <tomaszchojnacki2001@gmail.com> | 2023-12-23 13:33:34 +0100 |
---|---|---|
committer | Tomasz Chojnacki <tomaszchojnacki2001@gmail.com> | 2023-12-23 13:33:34 +0100 |
commit | 8bafdaf384fd144a61a7d23661a6cc8d56b5d810 (patch) | |
tree | fe8eb9c334c86056bebeb3c6cba6f9069a472f09 | |
parent | 5aa24ac572ab5451e187f9accfa6833634c58215 (diff) | |
download | gleam_aoc2020-8bafdaf384fd144a61a7d23661a6cc8d56b5d810.tar.gz gleam_aoc2020-8bafdaf384fd144a61a7d23661a6cc8d56b5d810.zip |
Finish day 24
-rw-r--r-- | aoc-2020-gleam/src/days/day24.gleam | 47 | ||||
-rw-r--r-- | aoc-2020-gleam/src/ext/setx.gleam | 7 | ||||
-rw-r--r-- | aoc-2020-gleam/src/util/hex.gleam | 27 | ||||
-rw-r--r-- | aoc-2020-gleam/src/util/pos2.gleam | 21 | ||||
-rw-r--r-- | aoc-2020-gleam/src/util/pos3.gleam | 23 | ||||
-rw-r--r-- | aoc-2020-gleam/src/util/pos4.gleam | 25 |
6 files changed, 106 insertions, 44 deletions
diff --git a/aoc-2020-gleam/src/days/day24.gleam b/aoc-2020-gleam/src/days/day24.gleam index 66bedb8..f380530 100644 --- a/aoc-2020-gleam/src/days/day24.gleam +++ b/aoc-2020-gleam/src/days/day24.gleam @@ -1,13 +1,14 @@ import gleam/io -import gleam/set +import gleam/bool import gleam/list +import gleam/set.{type Set} import ext/setx import ext/resultx as resx import util/input_util import util/parser as p import util/hex.{type Hex} -fn parse_tiles(lines: List(String)) -> List(Hex) { +fn parse_flips(lines: List(String)) -> List(Hex) { let tile_parser = [ p.replace(p.literal("e"), with: hex.e), @@ -28,20 +29,50 @@ fn parse_tiles(lines: List(String)) -> List(Hex) { }) } +fn get_black_tiles(flips: List(Hex)) -> Set(Hex) { + list.fold(over: flips, from: set.new(), with: setx.toggle) +} + +fn cycle(prev: Set(Hex), times: Int) -> Set(Hex) { + use <- bool.guard(when: times == 0, return: prev) + + prev + |> setx.flat_map(with: hex.neighbours7) + |> set.fold(from: set.new(), with: fn(acc, tile) { + let was_black = set.contains(in: prev, this: tile) + let adjacent = + tile + |> hex.neighbours6 + |> set.intersection(prev) + |> set.size + + case #(was_black, adjacent) { + #(True, 1) | #(_, 2) -> set.insert(into: acc, this: tile) + _ -> acc + } + }) + |> cycle(times - 1) +} + fn part1(lines: List(String)) -> Int { - let tiles = parse_tiles(lines) - let blacks = list.fold(over: tiles, from: set.new(), with: setx.toggle) - set.size(blacks) + lines + |> parse_flips + |> get_black_tiles + |> set.size } -fn part2(lines: List(String)) -> Nil { - Nil +fn part2(lines: List(String)) -> Int { + lines + |> parse_flips + |> get_black_tiles + |> cycle(100) + |> set.size } pub fn main() -> Nil { let testing = input_util.read_lines("test24") let assert 10 = part1(testing) - io.debug(part2(testing)) + let assert 2208 = part2(testing) let input = input_util.read_lines("day24") io.debug(part1(input)) diff --git a/aoc-2020-gleam/src/ext/setx.gleam b/aoc-2020-gleam/src/ext/setx.gleam index 6df9256..4a9c0c1 100644 --- a/aoc-2020-gleam/src/ext/setx.gleam +++ b/aoc-2020-gleam/src/ext/setx.gleam @@ -17,6 +17,13 @@ pub fn map(s: Set(a), with fun: fn(a) -> b) -> Set(b) { |> set.from_list } +pub fn flat_map(s: Set(a), with fun: fn(a) -> Set(b)) -> Set(b) { + s + |> set.to_list + |> list.map(with: fun) + |> list.fold(from: set.new(), with: set.union) +} + pub fn toggle(in s: Set(a), this value: a) -> Set(a) { s |> case set.contains(in: s, this: value) { diff --git a/aoc-2020-gleam/src/util/hex.gleam b/aoc-2020-gleam/src/util/hex.gleam index 21db192..070b6e4 100644 --- a/aoc-2020-gleam/src/util/hex.gleam +++ b/aoc-2020-gleam/src/util/hex.gleam @@ -1,3 +1,8 @@ +import gleam/bool +import gleam/list +import gleam/set.{type Set} +import ext/setx + pub opaque type Hex { Hex(q: Int, r: Int, s: Int) } @@ -19,3 +24,25 @@ pub const ne = Hex(q: 1, r: -1, s: 0) pub fn add(a: Hex, b: Hex) -> Hex { Hex(q: a.q + b.q, r: a.r + b.r, s: a.s + b.s) } + +fn directions7() -> Set(Hex) { + set.from_list({ + use q <- list.flat_map([-1, 0, 1]) + use r <- list.flat_map([-1, 0, 1]) + use s <- list.flat_map([-1, 0, 1]) + use <- bool.guard(when: q + r + s != 0, return: []) + [Hex(q, r, s)] + }) +} + +fn directions6() -> Set(Hex) { + set.delete(from: directions7(), this: zero) +} + +pub fn neighbours6(h: Hex) -> Set(Hex) { + setx.map(directions6(), with: add(h, _)) +} + +pub fn neighbours7(h: Hex) -> Set(Hex) { + setx.map(directions7(), with: add(h, _)) +} diff --git a/aoc-2020-gleam/src/util/pos2.gleam b/aoc-2020-gleam/src/util/pos2.gleam index 3f478ac..976088e 100644 --- a/aoc-2020-gleam/src/util/pos2.gleam +++ b/aoc-2020-gleam/src/util/pos2.gleam @@ -1,7 +1,7 @@ import gleam/int -import gleam/bool import gleam/list import gleam/set.{type Set} +import ext/setx pub type Pos2 = #(Int, Int) @@ -16,16 +16,18 @@ pub fn y(pos: Pos2) -> Int { pos.1 } -pub fn directions8() -> Set(Pos2) { +fn directions9() -> Set(Pos2) { set.from_list({ - use x <- list.flat_map(over: [-1, 0, 1]) - use y <- list.flat_map(over: [-1, 0, 1]) - let pos = #(x, y) - use <- bool.guard(when: pos == zero, return: []) - [pos] + use x <- list.flat_map([-1, 0, 1]) + use y <- list.map([-1, 0, 1]) + #(x, y) }) } +pub fn directions8() -> Set(Pos2) { + set.delete(from: directions9(), this: zero) +} + pub fn add(p1: Pos2, p2: Pos2) -> Pos2 { #(p1.0 + p2.0, p1.1 + p2.1) } @@ -39,10 +41,7 @@ pub fn mul(p: Pos2, by scalar: Int) -> Pos2 { } pub fn neighbours8(p: Pos2) -> Set(Pos2) { - directions8() - |> set.to_list - |> list.map(with: add(p, _)) - |> set.from_list + setx.map(directions8(), with: add(p, _)) } pub fn manhattan_dist(from p1: Pos2, to p2: Pos2) -> Int { diff --git a/aoc-2020-gleam/src/util/pos3.gleam b/aoc-2020-gleam/src/util/pos3.gleam index 3787c19..e493187 100644 --- a/aoc-2020-gleam/src/util/pos3.gleam +++ b/aoc-2020-gleam/src/util/pos3.gleam @@ -1,30 +1,29 @@ import gleam/list -import gleam/bool import gleam/set.{type Set} +import ext/setx pub type Pos3 = #(Int, Int, Int) pub const zero = #(0, 0, 0) -fn directions26() -> Set(Pos3) { +fn directions27() -> Set(Pos3) { set.from_list({ - use x <- list.flat_map(over: [-1, 0, 1]) - use y <- list.flat_map(over: [-1, 0, 1]) - use z <- list.flat_map(over: [-1, 0, 1]) - let pos = #(x, y, z) - use <- bool.guard(when: pos == zero, return: []) - [pos] + use x <- list.flat_map([-1, 0, 1]) + use y <- list.flat_map([-1, 0, 1]) + use z <- list.map([-1, 0, 1]) + #(x, y, z) }) } +fn directions26() -> Set(Pos3) { + set.delete(from: directions27(), this: zero) +} + pub fn add(p1: Pos3, p2: Pos3) -> Pos3 { #(p1.0 + p2.0, p1.1 + p2.1, p1.2 + p2.2) } pub fn neighbours26(p: Pos3) -> Set(Pos3) { - directions26() - |> set.to_list - |> list.map(with: add(p, _)) - |> set.from_list + setx.map(directions26(), with: add(p, _)) } diff --git a/aoc-2020-gleam/src/util/pos4.gleam b/aoc-2020-gleam/src/util/pos4.gleam index a96bcca..c2ab1c7 100644 --- a/aoc-2020-gleam/src/util/pos4.gleam +++ b/aoc-2020-gleam/src/util/pos4.gleam @@ -1,31 +1,30 @@ import gleam/list -import gleam/bool import gleam/set.{type Set} +import ext/setx pub type Pos4 = #(Int, Int, Int, Int) pub const zero = #(0, 0, 0, 0) -fn directions80() -> Set(Pos4) { +fn directions81() -> Set(Pos4) { set.from_list({ - use x <- list.flat_map(over: [-1, 0, 1]) - use y <- list.flat_map(over: [-1, 0, 1]) - use z <- list.flat_map(over: [-1, 0, 1]) - use w <- list.flat_map(over: [-1, 0, 1]) - let pos = #(x, y, z, w) - use <- bool.guard(when: pos == zero, return: []) - [pos] + use x <- list.flat_map([-1, 0, 1]) + use y <- list.flat_map([-1, 0, 1]) + use z <- list.flat_map([-1, 0, 1]) + use w <- list.map([-1, 0, 1]) + #(x, y, z, w) }) } +fn directions80() -> Set(Pos4) { + set.delete(from: directions81(), this: zero) +} + pub fn add(p1: Pos4, p2: Pos4) -> Pos4 { #(p1.0 + p2.0, p1.1 + p2.1, p1.2 + p2.2, p1.3 + p2.3) } pub fn neighbours80(p: Pos4) -> Set(Pos4) { - directions80() - |> set.to_list - |> list.map(with: add(p, _)) - |> set.from_list + setx.map(directions80(), with: add(p, _)) } |