diff --git a/2022/src/days/day_8.gleam b/2022/src/days/day_8.gleam index 009472c..73c1841 100644 --- a/2022/src/days/day_8.gleam +++ b/2022/src/days/day_8.gleam @@ -1,9 +1,13 @@ +import gleam/io.{debug} import gleam/int import gleam/iterator.{zip} import gleam/string import gleam/list import gleam/option.{None, Some} +type Point = + #(Int, Int) + pub fn pt_1(input: String) -> Int { let trees_by_row = input @@ -47,7 +51,16 @@ pub fn pt_1(input: String) -> Int { } pub fn pt_2(input: String) -> Int { - todo + let trees = + input + |> string.split("\n") + |> list.map(parse_row) + + trees + |> list.index_map(fn(x, row) { + list.index_map(row, fn(y, tree) { scenic_score(trees, x, y, tree) }) + }) + |> best_score } fn parse_row(row: String) -> List(Int) { @@ -113,3 +126,57 @@ fn count_if_visible( False -> count } } + +fn scenic_score(trees: List(List(Int)), x: Int, y: Int, tree: Int) { + let up = visible(trees, #(x, y), #(0, -1), tree, 0) + let down = visible(trees, #(x, y), #(0, 1), tree, 0) + let left = visible(trees, #(x, y), #(-1, 0), tree, 0) + let right = visible(trees, #(x, y), #(1, 0), tree, 0) + up * down * left * right +} + +fn visible( + trees: List(List(Int)), + from: Point, + delta: Point, + tree: Int, + count: Int, +) -> Int { + let last = list.length(trees) - 1 + let coord = add(from, delta) + case coord { + #(-1, _) | #(_, -1) -> count + #(x, y) if x > last || y > last -> count + #(x, y) -> + case + trees + |> list.at(x) + |> unwrap + |> list.at(y) + |> unwrap + { + other if other < tree -> visible(trees, coord, delta, tree, count + 1) + otherwise -> count + 1 + } + } +} + +fn best_score(scores: List(List(Int))) -> Int { + scores + |> list.map(list_max) + |> list_max +} + +fn add(from: Point, delta: Point) -> Point { + #(from.0 + delta.0, from.1 + delta.1) +} + +fn unwrap(x: Result(a, Nil)) -> a { + assert Ok(ok) = x + ok +} + +fn list_max(l: List(Int)) -> Int { + list.reduce(l, int.max) + |> unwrap +} diff --git a/2022/test/day_8_test.gleam b/2022/test/day_8_test.gleam index a7ca0e3..99dd667 100644 --- a/2022/test/day_8_test.gleam +++ b/2022/test/day_8_test.gleam @@ -20,3 +20,8 @@ pub fn pt1_test() { day_8.pt_1("30373\n25512\n65332\n33549\n35390") |> should.equal(21) } + +pub fn pt2_test() { + day_8.pt_2("30373\n25512\n65332\n33549\n35390") + |> should.equal(8) +}