AoC - Day8
Mix.install([
{:kino_aoc, git: "https://github.com/ljgago/kino_aoc"}
])
Setup
{:ok, data} = KinoAOC.download_puzzle("2022", "8", System.fetch_env!("LB_AOC_SECRET"))
Solve
tdata = """
30373
25512
65332
33549
35390
"""
defmodule Day8 do
def solve(data) do
{dd, rows, cols} = format_inp(data)
dd_cw = rotate_cw(dd)
acc_r = task1(dd, cols, false)
acc_c = task1(dd_cw, rows, true)
MapSet.union(acc_r, acc_c)
end
def task1(dd, size, rot) do
dd
|> Enum.with_index()
|> Enum.reduce(MapSet.new(), fn {row, ind}, acc ->
{_, lacc} = visible_from_edge(row, ind, acc, size, &l2r_ind/2, false, rot)
{_, acc} = visible_from_edge(row, ind, lacc, size, &r2l_ind/2, true, rot)
acc
end)
end
# calculation for rotated indexes need to be simplified
def visible_from_edge(row, i, acc, size, ind_fun, reverse, rot) do
row
|> then(fn row ->
if reverse, do: Enum.reverse(row), else: row
end)
|> Enum.with_index(fn el, ind -> {el, ind_fun.(ind, size)} end)
|> Enum.reduce({-1, acc}, &count_visible(&1, &2, i, rot, size))
end
def l2r_ind(ind, _size), do: ind
def r2l_ind(ind, size), do: size - 1 - ind
def count_visible({num, j}, {prev, acc}, i, rot, size) when num > prev do
k = if rot, do: {size - 1 - j, i}, else: {i, j}
{num, MapSet.put(acc, k)}
end
def count_visible(_el, {prev, acc}, _i, _rot, _size), do: {prev, acc}
def rotate_cw(matrix) do
matrix |> Enum.zip_with(fn row -> Enum.reverse(row) end)
end
def format_inp(data) do
dd =
data
|> String.trim()
|> String.split("\n", trim: true)
|> Enum.map(&String.graphemes/1)
|> Enum.map(fn row ->
Enum.map(row, &String.to_integer/1)
end)
rows = length(dd)
cols = dd |> List.first() |> length()
{dd, rows, cols}
end
end
# 21, 1662
res = Day8.solve(tdata)
res |> MapSet.size()