Powered by AppSignal & Oban Pro

Day 8: Treetop Tree House

2022/day08.livemd

Day 8: Treetop Tree House

Mix.install([:kino, :nx])

Section

input = Kino.Input.textarea("input")
input2 = Kino.Input.textarea("example input")
grid =
  input
  |> Kino.Input.read()
  |> String.split("\n")
  |> Enum.map(fn line ->
    line
    |> String.graphemes()
    |> Enum.map(&String.to_integer/1)
  end)

defmodule Forest do
  def visible_trees(forest, height \\ -1)
  def visible_trees([], _), do: []

  def visible_trees([tree | forest], height) when tree > height do
    [true | visible_trees(forest, tree)]
  end

  def visible_trees([_tree | forest], height) do
    [false | visible_trees(forest, height)]
  end

  def scenic_score([_tree]), do: [0]

  def scenic_score([tree | forest]) do
    case Enum.split_while(forest, &(&1 < tree)) do
      {n, []} -> [length(n) | scenic_score(forest)]
      {n, _} -> [length(n) + 1 | scenic_score(forest)]
    end
  end
end

hvis =
  Enum.zip(
    Enum.map(grid, &Forest.visible_trees/1),
    Enum.map(grid, fn forest ->
      forest
      |> Enum.reverse()
      |> Forest.visible_trees()
      |> Enum.reverse()
    end)
  )
  |> Enum.map(fn {v1, v2} ->
    Enum.map(Enum.zip(v1, v2), fn {l, r} -> l or r end)
  end)

vgrid = Enum.zip_with(grid, & &1)

vvis =
  Enum.zip(
    Enum.map(vgrid, &Forest.visible_trees/1),
    Enum.map(vgrid, fn forest ->
      forest
      |> Enum.reverse()
      |> Forest.visible_trees()
      |> Enum.reverse()
    end)
  )
  |> Enum.map(fn {v1, v2} ->
    Enum.map(Enum.zip(v1, v2), fn {l, r} -> l or r end)
  end)
  |> Enum.zip_with(& &1)

Enum.zip(vvis, hvis)
|> Enum.map(fn {v1, v2} ->
  Enum.map(Enum.zip(v1, v2), fn {l, r} -> l or r end)
end)
|> List.flatten()
|> Enum.count(& &1)
# vscores = vgrid
# |> Enum.map(&Forest.scenic_score/1)
# |> Enum.zip_with(& &1)

l_scores = Enum.map(grid, &Forest.scenic_score/1)
r_scores = Enum.map(grid, fn forest ->
  forest
  |> Enum.reverse()
  |> Forest.scenic_score()
  |> Enum.reverse()
end) 
h_scores = 
  grid 
  |> Enum.zip_with(& &1) 
  |> Enum.map(&Forest.scenic_score/1) 
  |> Enum.zip_with(& &1)
 
b_scores = 
  grid 
  |> Enum.zip_with(& &1) 
  |> Enum.map(fn forest ->
    forest
    |> Enum.reverse()
    |> Forest.scenic_score()
    |> Enum.reverse()
  end)
  |> Enum.zip_with(& &1)

Nx.tensor(l_scores)
|> Nx.multiply(Nx.tensor(r_scores))
|> Nx.multiply(Nx.tensor(h_scores))
|> Nx.multiply(Nx.tensor(b_scores))
|> Nx.to_flat_list()
|> Enum.max()


Nx.LinAlg.