diff --git a/sample/day14-sample.txt b/sample/day14-sample.txt new file mode 100644 index 0000000..2455da4 --- /dev/null +++ b/sample/day14-sample.txt @@ -0,0 +1,12 @@ +p=0,4 v=3,-3 +p=6,3 v=-1,-3 +p=10,3 v=-1,2 +p=2,0 v=2,-1 +p=0,0 v=1,3 +p=3,0 v=-2,-2 +p=7,6 v=-1,-3 +p=3,0 v=-1,-2 +p=9,3 v=2,3 +p=7,3 v=-1,2 +p=2,4 v=2,-3 +p=9,5 v=-3,-3 diff --git a/src/day14_p1.gleam b/src/day14_p1.gleam new file mode 100644 index 0000000..b148ebf --- /dev/null +++ b/src/day14_p1.gleam @@ -0,0 +1,81 @@ +import gleam/int +import gleam/io +import gleam/iterator +import gleam/list.{filter, fold, map} +import gleam/string +import stdin.{stdin} + +const w = 101 + +const h = 103 + +pub fn main() { + stdin() + |> read_input + |> map(fn(r) { move(r, 100) }) + |> count_safety + |> io.debug +} + +fn count_safety(robots: List(#(Int, Int))) -> Int { + let assert Ok(mid_col) = int.floor_divide(w, 2) + let assert Ok(mid_row) = int.floor_divide(h, 2) + + let #(tl, tr, bl, br) = + robots + |> fold(#(0, 0, 0, 0), fn(acc, r) { + let #(tl, tr, bl, br) = acc + let #(x, y) = r + case x, y { + x, y if x < mid_col && y < mid_row -> #(tl + 1, tr, bl, br) + x, y if x > mid_col && y < mid_row -> #(tl, tr + 1, bl, br) + x, y if x < mid_col && y > mid_row -> #(tl, tr, bl + 1, br) + x, y if x > mid_col && y > mid_row -> #(tl, tr, bl, br + 1) + _, _ -> acc + } + }) + + tl * tr * bl * br +} + +fn move(robot: Robot, times: Int) -> #(Int, Int) { + let Robot(#(x, y), #(xs, ys)) = robot + let assert Ok(nx) = int.modulo(x + xs * times, w) + let assert Ok(ny) = int.modulo(y + ys * times, h) + #(nx, ny) +} + +type Robot { + Robot(pos: #(Int, Int), speed: #(Int, Int)) +} + +fn read_input(it: iterator.Iterator(String)) -> List(Robot) { + it + |> iterator.to_list + |> map(string.trim) + |> filter(not(string.is_empty)) + |> map(parse_line) +} + +fn parse_line(line: String) -> Robot { + let assert [coord, velocity] = + line + |> string.drop_start(2) + |> string.split(" v=") + |> map(parse_pair) + + Robot(coord, velocity) +} + +fn parse_pair(text: String) -> #(Int, Int) { + let assert [Ok(x), Ok(y)] = + text + |> string.split(",") + |> map(int.parse) + + #(x, y) +} + +fn not(a: fn(a) -> Bool) { + fn(param: a) -> Bool { !a(param) } +} diff --git a/src/day14_p2.gleam b/src/day14_p2.gleam new file mode 100644 index 0000000..aa42320 --- /dev/null +++ b/src/day14_p2.gleam @@ -0,0 +1,79 @@ +import gleam/int +import gleam/io +import gleam/iterator +import gleam/list.{filter, fold, map} +import gleam/result +import gleam/string +import stdin.{stdin} + +const w = 101 + +const h = 103 + +pub fn main() { + stdin() + |> read_input + |> find_easter_egg(0) + |> io.debug +} + +fn find_easter_egg(robots: List(Robot), index: Int) -> Int { + let coords = robots |> map(fn(r) { move(r, index) }) + case check_easter_egg(coords) { + True -> index + False -> find_easter_egg(robots, index + 1) + } +} + +fn check_easter_egg(coords: List(#(Int, Int))) -> Bool { + // Lil hack, just check for a long vertical line + coords + |> list.find(fn(c) { + let #(x, y) = c + list.range(0, 10) + |> list.all(fn(ny) { coords |> list.contains(#(x, y + ny)) }) + }) + |> result.is_ok +} + +fn move(robot: Robot, times: Int) -> #(Int, Int) { + let Robot(#(x, y), #(xs, ys)) = robot + let assert Ok(nx) = int.modulo(x + xs * times, w) + let assert Ok(ny) = int.modulo(y + ys * times, h) + #(nx, ny) +} + +type Robot { + Robot(pos: #(Int, Int), speed: #(Int, Int)) +} + +fn read_input(it: iterator.Iterator(String)) -> List(Robot) { + it + |> iterator.to_list + |> map(string.trim) + |> filter(not(string.is_empty)) + |> map(parse_line) +} + +fn parse_line(line: String) -> Robot { + let assert [coord, velocity] = + line + |> string.drop_start(2) + |> string.split(" v=") + |> map(parse_pair) + + Robot(coord, velocity) +} + +fn parse_pair(text: String) -> #(Int, Int) { + let assert [Ok(x), Ok(y)] = + text + |> string.split(",") + |> map(int.parse) + + #(x, y) +} + +fn not(a: fn(a) -> Bool) { + fn(param: a) -> Bool { !a(param) } +}