Advent of Code 2021 day 13
Setup
Mix.install([
{:kino, "~> 0.4.1"},
{:vega_lite, "~> 0.1.1"}
])
input = Kino.Input.textarea("Paste inputs here:")
[dots, folds] =
input
|> Kino.Input.read()
|> String.split("\n\n")
|> Enum.map(&String.split(&1, "\n", trim: true))
dots =
dots
|> Enum.map(&String.split(&1, ","))
|> Enum.map(&Enum.map(&1, fn i -> String.to_integer(i) end))
|> Enum.map(fn [row, col] -> {row, col} end)
folds =
Enum.map(folds, fn "fold along " <> fold ->
[dir, line] = String.split(fold, "=")
{String.to_atom(dir), String.to_integer(line)}
end)
Part 1
defmodule Day13 do
def fold(:x, line), do: fn {x, y} -> {line - abs(x - line), y} end
def fold(:y, line), do: fn {x, y} -> {x, line - abs(y - line)} end
end
folds
|> Enum.take(1)
|> Enum.reduce(dots, fn {dir, line}, dots ->
Enum.map(dots, Day13.fold(dir, line))
end)
|> Enum.uniq()
|> Enum.count()
Part 2
defmodule Day13Part2 do
def draw(grid) do
{width, _} = Enum.max_by(grid, &elem(&1, 0))
{_, height} = Enum.max_by(grid, &elem(&1, 1))
for y <- 0..height do
for x <- 0..width do
if {x, y} in grid, do: "X", else: " "
end
|> Enum.join(" ")
|> IO.puts()
end
end
end
paper =
folds
|> Enum.reduce(dots, fn {dir, line}, dots ->
Enum.map(dots, Day13.fold(dir, line))
end)
|> Enum.uniq()
|> Day13Part2.draw()
Visualization
> source: https://github.com/miladamilli/Advent_of_Code_2021/blob/master/day13.livemd
alias VegaLite, as: Vl
dots_to_paper = fn dots ->
Enum.map(dots, fn {x, y} -> %{x: x, y: -y} end)
end
graph =
Vl.new(width: 800, height: 150)
|> Vl.config(view: [stroke: :transparent])
|> Vl.mark(:square, opacity: 0.4, size: 200)
|> Vl.data_from_values(dots_to_paper.(dots))
|> Vl.encode_field(:x, "x", type: :quantitative, axis: false)
|> Vl.encode_field(:y, "y", type: :quantitative, axis: false)
|> Vl.encode_field(:color, "x",
type: :quantitative,
scale: [range: ["#27e3c8", "#b25ae7"]],
legend: false
)
|> Kino.VegaLite.new()
|> Kino.render()
Enum.reduce(folds, dots, fn {dir, fold}, dots ->
dots = Enum.map(dots, Day13.fold(dir, fold))
Process.sleep(500)
Kino.VegaLite.clear(graph)
Kino.VegaLite.push_many(graph, dots_to_paper.(dots))
dots
end)
:ok