Finished day 8
This commit is contained in:
parent
495024e66d
commit
3e2e3eb9d4
4 changed files with 289 additions and 6 deletions
|
@ -18,4 +18,5 @@ Day 6: [[https://livebook.dev/run?url=https%3A%2F%2Fgit.datarift.nl%2Ferwin%2Fao
|
||||||
|
|
||||||
Day 7: [[https://livebook.dev/run?url=https%3A%2F%2Fgit.datarift.nl%2Ferwin%2Faoc2022%2Fraw%2Fbranch%2Fmain%2Fday7.livemd][Run in Livebook]]
|
Day 7: [[https://livebook.dev/run?url=https%3A%2F%2Fgit.datarift.nl%2Ferwin%2Faoc2022%2Fraw%2Fbranch%2Fmain%2Fday7.livemd][Run in Livebook]]
|
||||||
|
|
||||||
|
Day 8: [[https://livebook.dev/run?url=https%3A%2F%2Fgit.datarift.nl%2Ferwin%2Faoc2022%2Fraw%2Fbranch%2Fmain%2Fday8.livemd][Run in Livebook]]
|
||||||
|
|
||||||
|
|
276
day8.livemd
Normal file
276
day8.livemd
Normal file
|
@ -0,0 +1,276 @@
|
||||||
|
# AOC 2022 - Day 8
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
Mix.install(
|
||||||
|
[
|
||||||
|
{:req, "~> 0.3.3"},
|
||||||
|
{:nx, "~> 0.4.1"},
|
||||||
|
{:exla, "~> 0.4.1"}
|
||||||
|
],
|
||||||
|
config: [nx: [default_backend: EXLA.Backend]]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Puzzle description
|
||||||
|
|
||||||
|
[Day 8: Treetop Tree House](https://adventofcode.com/2022/day/8).
|
||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
defmodule Load do
|
||||||
|
def input do
|
||||||
|
aoc_session = System.fetch_env!("LB_AOC_SESSION")
|
||||||
|
input_url = "https://adventofcode.com/2022/day/8/input"
|
||||||
|
Req.get!(input_url, headers: [cookie: "session=#{aoc_session}"]).body
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
defmodule Util do
|
||||||
|
def process(input) do
|
||||||
|
input
|
||||||
|
|> String.split("\n", trim: true)
|
||||||
|
|> Enum.map(fn row ->
|
||||||
|
row
|
||||||
|
|> String.split("", trim: true)
|
||||||
|
|> Enum.map(&String.to_integer/1)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def process2(input) do
|
||||||
|
input
|
||||||
|
|> String.split()
|
||||||
|
|> Enum.with_index()
|
||||||
|
|> Enum.flat_map(&parse_line/1)
|
||||||
|
|> Map.new(fn {v, k} -> {k, v} end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_line({string, row}) do
|
||||||
|
string
|
||||||
|
|> String.graphemes()
|
||||||
|
|> Enum.with_index()
|
||||||
|
|> Enum.map(fn {char, column} ->
|
||||||
|
{String.to_integer(char), {row + 1, column + 1}}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def count_visible(line) do
|
||||||
|
line
|
||||||
|
|> Enum.with_index()
|
||||||
|
|> Enum.map_reduce(0, fn {h, n}, max ->
|
||||||
|
cond do
|
||||||
|
n == 0 ->
|
||||||
|
{true, h}
|
||||||
|
|
||||||
|
h <= max ->
|
||||||
|
{false, max}
|
||||||
|
|
||||||
|
true ->
|
||||||
|
{true, h}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|> elem(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
def transpose(v) do
|
||||||
|
v
|
||||||
|
|> List.zip()
|
||||||
|
|> Enum.map(&Tuple.to_list/1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def score(trees, row, column, rows, columns) do
|
||||||
|
left_score(trees, row, column, rows, columns) *
|
||||||
|
right_score(trees, row, column, rows, columns) *
|
||||||
|
up_score(trees, row, column, rows, columns) *
|
||||||
|
down_score(trees, row, column, rows, columns)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp left_score(trees, row, column, _rows, _columns) do
|
||||||
|
list =
|
||||||
|
for c <- (column - 1)..1 do
|
||||||
|
trees[{row, c}]
|
||||||
|
end
|
||||||
|
|> Enum.with_index()
|
||||||
|
|
||||||
|
len = length(list)
|
||||||
|
|
||||||
|
list
|
||||||
|
|> Enum.reduce_while(1, fn {height, position}, score ->
|
||||||
|
if trees[{row, column}] > height and position + 1 != len,
|
||||||
|
do: {:cont, score + 1},
|
||||||
|
else: {:halt, score}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp right_score(trees, row, column, _rows, columns) do
|
||||||
|
list =
|
||||||
|
for c <- (column + 1)..columns do
|
||||||
|
trees[{row, c}]
|
||||||
|
end
|
||||||
|
|> Enum.with_index()
|
||||||
|
|
||||||
|
len = length(list)
|
||||||
|
|
||||||
|
list
|
||||||
|
|> Enum.reduce_while(1, fn {height, position}, score ->
|
||||||
|
if trees[{row, column}] > height and position + 1 != len,
|
||||||
|
do: {:cont, score + 1},
|
||||||
|
else: {:halt, score}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp up_score(trees, row, column, _rows, _columns) do
|
||||||
|
list =
|
||||||
|
for r <- (row - 1)..1 do
|
||||||
|
trees[{r, column}]
|
||||||
|
end
|
||||||
|
|> Enum.with_index()
|
||||||
|
|
||||||
|
len = length(list)
|
||||||
|
|
||||||
|
list
|
||||||
|
|> Enum.reduce_while(1, fn {height, position}, score ->
|
||||||
|
if trees[{row, column}] > height and position + 1 != len,
|
||||||
|
do: {:cont, score + 1},
|
||||||
|
else: {:halt, score}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp down_score(trees, row, column, rows, _columns) do
|
||||||
|
list =
|
||||||
|
for r <- (row + 1)..rows do
|
||||||
|
trees[{r, column}]
|
||||||
|
end
|
||||||
|
|> Enum.with_index()
|
||||||
|
|
||||||
|
len = length(list)
|
||||||
|
|
||||||
|
list
|
||||||
|
|> Enum.reduce_while(1, fn {height, position}, score ->
|
||||||
|
if trees[{row, column}] > height and position + 1 != len,
|
||||||
|
do: {:cont, score + 1},
|
||||||
|
else: {:halt, score}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
defmodule Part1 do
|
||||||
|
def run(input) do
|
||||||
|
trees =
|
||||||
|
input
|
||||||
|
|> Util.process()
|
||||||
|
|
||||||
|
{trees, horizontal} =
|
||||||
|
trees
|
||||||
|
|> Enum.map_reduce([], fn line, acc ->
|
||||||
|
visible =
|
||||||
|
[
|
||||||
|
Util.count_visible(line),
|
||||||
|
line |> Enum.reverse() |> Util.count_visible() |> Enum.reverse()
|
||||||
|
]
|
||||||
|
|> Enum.zip()
|
||||||
|
|> Enum.map(&(elem(&1, 0) or elem(&1, 1)))
|
||||||
|
|
||||||
|
{line, [visible | acc]}
|
||||||
|
end)
|
||||||
|
|> then(fn {trees, horizontal} ->
|
||||||
|
{trees, Enum.reverse(horizontal)}
|
||||||
|
end)
|
||||||
|
|
||||||
|
{_, vertical} =
|
||||||
|
trees
|
||||||
|
|> Util.transpose()
|
||||||
|
|> Enum.map_reduce([], fn col, acc ->
|
||||||
|
visible =
|
||||||
|
[
|
||||||
|
Util.count_visible(col),
|
||||||
|
col |> Enum.reverse() |> Util.count_visible() |> Enum.reverse()
|
||||||
|
]
|
||||||
|
|> Enum.zip()
|
||||||
|
|> Enum.map(&(elem(&1, 0) or elem(&1, 1)))
|
||||||
|
|
||||||
|
{col, [visible | acc]}
|
||||||
|
end)
|
||||||
|
|> then(fn {trees, vertical} ->
|
||||||
|
{trees, Enum.reverse(vertical) |> Util.transpose()}
|
||||||
|
end)
|
||||||
|
|
||||||
|
horizontal
|
||||||
|
|> Enum.zip(vertical)
|
||||||
|
|> Enum.map(fn {h, v} ->
|
||||||
|
h
|
||||||
|
|> Enum.zip(v)
|
||||||
|
|> Enum.map(&(elem(&1, 0) or elem(&1, 1)))
|
||||||
|
end)
|
||||||
|
|> Enum.map(fn line ->
|
||||||
|
Enum.count(line, & &1)
|
||||||
|
end)
|
||||||
|
|> Enum.sum()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Part2 do
|
||||||
|
def run(input) do
|
||||||
|
trees = Util.process2(input)
|
||||||
|
|
||||||
|
{rows, columns} =
|
||||||
|
trees
|
||||||
|
|> Map.keys()
|
||||||
|
|> Enum.max()
|
||||||
|
|
||||||
|
for i <- 2..(rows - 1), j <- 2..(columns - 1) do
|
||||||
|
{i, j, Util.score(trees, i, j, rows, columns)}
|
||||||
|
end
|
||||||
|
|> Enum.max_by(fn {_, _, x} -> x end)
|
||||||
|
|> elem(2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start(autorun: false)
|
||||||
|
|
||||||
|
defmodule Test do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
@example_input ~s(30373
|
||||||
|
25512
|
||||||
|
65332
|
||||||
|
33549
|
||||||
|
35390)
|
||||||
|
@input Load.input()
|
||||||
|
|
||||||
|
test "it loads the input" do
|
||||||
|
assert String.length(@input) > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
test "part 1 example" do
|
||||||
|
assert Part1.run(@example_input) === 21
|
||||||
|
end
|
||||||
|
|
||||||
|
test "part 1" do
|
||||||
|
assert Part1.run(@input) === 1816
|
||||||
|
end
|
||||||
|
|
||||||
|
test "part 2 example" do
|
||||||
|
assert Part2.run(@example_input) === 8
|
||||||
|
end
|
||||||
|
|
||||||
|
test "part 2" do
|
||||||
|
assert Part2.run(@input) === 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.run()
|
||||||
|
|
||||||
|
# [
|
||||||
|
# [1, 1, 1, 1, 1],
|
||||||
|
# [1, 1, 1, 0, 1],
|
||||||
|
# [1, 1, 0, 1, 1],
|
||||||
|
# [1, 0, 1, 0, 1],
|
||||||
|
# [1, 1, 1, 1, 1]
|
||||||
|
# ]
|
||||||
|
```
|
|
@ -4,6 +4,7 @@ packages = [
|
||||||
"libnotify",
|
"libnotify",
|
||||||
"inotify-tools",
|
"inotify-tools",
|
||||||
"gnumake",
|
"gnumake",
|
||||||
|
"gcc",
|
||||||
"taplo",
|
"taplo",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -55,3 +56,8 @@ value = "9091"
|
||||||
name = "mix"
|
name = "mix"
|
||||||
package = "elixir_1_14"
|
package = "elixir_1_14"
|
||||||
help = "mix"
|
help = "mix"
|
||||||
|
|
||||||
|
[[commands]]
|
||||||
|
name = "livebook"
|
||||||
|
command = "livebook $@"
|
||||||
|
help = "livebook"
|
||||||
|
|
12
flake.lock
12
flake.lock
|
@ -10,11 +10,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1667210711,
|
"lastModified": 1671489820,
|
||||||
"narHash": "sha256-IoErjXZAkzYWHEpQqwu/DeRNJGFdR7X2OGbkhMqMrpw=",
|
"narHash": "sha256-qoei5HDJ8psd1YUPD7DhbHdhLIT9L2nadscp4Qk37uk=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "devshell",
|
"repo": "devshell",
|
||||||
"rev": "96a9dd12b8a447840cc246e17a47b81a4268bba7",
|
"rev": "5aa3a8039c68b4bf869327446590f4cdf90bb634",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -56,11 +56,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1670597555,
|
"lastModified": 1672350804,
|
||||||
"narHash": "sha256-/k939P2S2246G6K5fyvC0U2IWvULhb4ZJg9K7ZxsX+k=",
|
"narHash": "sha256-jo6zkiCabUBn3ObuKXHGqqORUMH27gYDIFFfLq5P4wg=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "2dea0f4c2d6e4603f54b2c56c22367e77869490c",
|
"rev": "677ed08a50931e38382dbef01cba08a8f7eac8f6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
Loading…
Reference in a new issue