Add solutions for 2022:8 "Treetop Tree House"
This commit is contained in:
parent
bb708a5e58
commit
c864b26770
2 changed files with 207 additions and 0 deletions
178
2022-elixir/lib/solutions/day_08.ex
Normal file
178
2022-elixir/lib/solutions/day_08.ex
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
defmodule Aoc.Solution.Day08 do
|
||||||
|
import Aoc.Utils
|
||||||
|
|
||||||
|
@name "Day 8: Treetop Tree House"
|
||||||
|
@behaviour Solution
|
||||||
|
|
||||||
|
@impl Solution
|
||||||
|
def get_name, do: @name
|
||||||
|
|
||||||
|
@impl Solution
|
||||||
|
def present(solution), do: "#{solution} trees are visible"
|
||||||
|
|
||||||
|
@impl Solution
|
||||||
|
def present_again(solution), do: "Highest scenic score possible is #{solution}"
|
||||||
|
|
||||||
|
@impl Solution
|
||||||
|
def parse!(raw) do
|
||||||
|
raw
|
||||||
|
|> split_lines()
|
||||||
|
|> Enum.map(fn line -> String.codepoints(line) |> Enum.map(&String.to_integer/1) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Solution
|
||||||
|
def solve(map) do
|
||||||
|
find_visible(map)
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Solution
|
||||||
|
def solve_again(map) do
|
||||||
|
scenic_scores(map)
|
||||||
|
|> MapSet.to_list()
|
||||||
|
|> Enum.max()
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_visible(map) do
|
||||||
|
{h, w} = _map_size(map)
|
||||||
|
count_visibles(map, 0, 0, h, w, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
def count_visibles(_map, y, _x, h, _w, count) when y == h do
|
||||||
|
count
|
||||||
|
end
|
||||||
|
|
||||||
|
def count_visibles(map, y, x, h, w, count) when x == w do
|
||||||
|
count_visibles(map, y + 1, 0, h, w, count)
|
||||||
|
end
|
||||||
|
|
||||||
|
def count_visibles(map, y, x, h, w, count) do
|
||||||
|
if visible?(map, y, x, h, w) do
|
||||||
|
count_visibles(map, y, x + 1, h, w, count + 1)
|
||||||
|
else
|
||||||
|
if Enum.zip(map) |> Enum.map(&Tuple.to_list/1) |> visible?(x, y, w, h) do
|
||||||
|
count_visibles(map, y, x + 1, h, w, count + 1)
|
||||||
|
else
|
||||||
|
count_visibles(map, y, x + 1, h, w, count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def visible?(_map, y, _x, _h, _w) when y == 0 do
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def visible?(_map, y, _x, h, _w) when y == h - 1 do
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def visible?(_map, _y, x, _h, _w) when x == 0 do
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def visible?(_map, _y, x, _h, w) when x == w - 1 do
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def visible?(map, y, x, _h, _w) do
|
||||||
|
value = Enum.at(map, y) |> Enum.at(x)
|
||||||
|
{l, r} = Enum.at(map, y) |> Enum.split(x)
|
||||||
|
r = Enum.drop(r, 1)
|
||||||
|
|
||||||
|
Enum.max(l) < value or Enum.max(r) < value
|
||||||
|
end
|
||||||
|
|
||||||
|
def scenic_scores(map) do
|
||||||
|
{h, w} = _map_size(map)
|
||||||
|
|
||||||
|
scenic_score(map, Enum.zip(map) |> Enum.map(&Tuple.to_list/1), 0, 0, h, w, MapSet.new())
|
||||||
|
end
|
||||||
|
|
||||||
|
def scenic_score(_lr_map, _tb_map, y, _x, h, _w, scores) when y == h do
|
||||||
|
scores
|
||||||
|
end
|
||||||
|
|
||||||
|
def scenic_score(lr_map, tb_map, y, x, h, w, scores) when x == w do
|
||||||
|
scenic_score(lr_map, tb_map, y + 1, 0, h, w, scores)
|
||||||
|
end
|
||||||
|
|
||||||
|
def scenic_score(lr_map, tb_map, y = 0, x, h, w, scores) do
|
||||||
|
zero_score(lr_map, tb_map, y, x, h, w, scores)
|
||||||
|
end
|
||||||
|
|
||||||
|
def scenic_score(lr_map, tb_map, y, x = 0, h, w, scores) do
|
||||||
|
zero_score(lr_map, tb_map, y, x, h, w, scores)
|
||||||
|
end
|
||||||
|
|
||||||
|
def scenic_score(lr_map, tb_map, y, x, h, w, scores) when x == w - 1 do
|
||||||
|
zero_score(lr_map, tb_map, y, x, h, w, scores)
|
||||||
|
end
|
||||||
|
|
||||||
|
def scenic_score(lr_map, tb_map, y, x, h, w, scores) when y == h - 1 do
|
||||||
|
zero_score(lr_map, tb_map, y, x, h, w, scores)
|
||||||
|
end
|
||||||
|
|
||||||
|
def scenic_score(lr_map, tb_map, y, x, h, w, scores) do
|
||||||
|
value = Enum.at(lr_map, y) |> Enum.at(x)
|
||||||
|
|
||||||
|
{l, r} = lr(lr_map, y, x)
|
||||||
|
{t, b} = lr(tb_map, x, y)
|
||||||
|
|
||||||
|
%{pos: {y, x}, value: value}
|
||||||
|
|
||||||
|
score =
|
||||||
|
[t, r, b, l]
|
||||||
|
|> Enum.map(fn trbl -> view_distance(trbl, value) end)
|
||||||
|
|> Enum.product()
|
||||||
|
|
||||||
|
scenic_score(lr_map, tb_map, y, x + 1, h, w, MapSet.put(scores, score))
|
||||||
|
end
|
||||||
|
|
||||||
|
def zero_score(lr_map, tb_map, y, x, h, w, scores) do
|
||||||
|
scenic_score(lr_map, tb_map, y, x + 1, h, w, MapSet.put(scores, 0))
|
||||||
|
end
|
||||||
|
|
||||||
|
def lr(map, y, x) do
|
||||||
|
{l, r} = Enum.at(map, y) |> Enum.split(x)
|
||||||
|
{Enum.reverse(l), Enum.drop(r, 1)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def _map_size(map) do
|
||||||
|
h = Enum.count(map)
|
||||||
|
w = List.first(map) |> Enum.count()
|
||||||
|
|
||||||
|
{h, w}
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Calculate the trees that can be seen in a given direction.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> Aoc.Solution.Day08.view_distance([3], 5)
|
||||||
|
1
|
||||||
|
iex> Aoc.Solution.Day08.view_distance([5, 2], 5)
|
||||||
|
1
|
||||||
|
iex> Aoc.Solution.Day08.view_distance([1, 2], 5)
|
||||||
|
2
|
||||||
|
iex> Aoc.Solution.Day08.view_distance([3, 5, 3], 5)
|
||||||
|
2
|
||||||
|
iex> Aoc.Solution.Day08.view_distance([3, 3], 5)
|
||||||
|
2
|
||||||
|
iex> Aoc.Solution.Day08.view_distance([4, 9], 5)
|
||||||
|
2
|
||||||
|
|
||||||
|
"""
|
||||||
|
def view_distance(list, value, count \\ 0)
|
||||||
|
|
||||||
|
def view_distance([], _value, count) do
|
||||||
|
count
|
||||||
|
end
|
||||||
|
|
||||||
|
def view_distance([nearest | _beyond], value, count) when value <= nearest do
|
||||||
|
count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def view_distance([_nearest | beyond], value, count) do
|
||||||
|
view_distance(beyond, value, count + 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
29
2022-elixir/test/solutions/day_08_test.exs
Normal file
29
2022-elixir/test/solutions/day_08_test.exs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
defmodule Day08Test do
|
||||||
|
use ExUnit.Case
|
||||||
|
doctest Aoc.Solution.Day08
|
||||||
|
import Aoc.Solution.Day08
|
||||||
|
|
||||||
|
@input ~s(
|
||||||
|
30373
|
||||||
|
25512
|
||||||
|
65332
|
||||||
|
33549
|
||||||
|
35390
|
||||||
|
)
|
||||||
|
|
||||||
|
test "08: Treetop Tree House, part 1" do
|
||||||
|
expected = 21
|
||||||
|
|
||||||
|
result = @input |> parse!() |> solve()
|
||||||
|
|
||||||
|
assert result == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
test "08: Treetop Tree House, part 2" do
|
||||||
|
expected = 8
|
||||||
|
|
||||||
|
result = @input |> parse!() |> solve_again()
|
||||||
|
|
||||||
|
assert result == expected
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Add table
Reference in a new issue