Day 14
Mix.install([
{:tucan, "~> 0.4.1"},
{:kino_vega_lite, "~> 0.1.13"},
])
Setup
input =
System.fetch_env!("LB_AOC_DIR")
|> Path.join("data/day14.txt")
|> File.read!()
nil
nil
Solve
defmodule Day14 do
def parse(input) do
for row <- String.split(input, "\n"), row != "" do
[<<"p=", position::binary>>, <<"v=", velocity::binary>>] = String.split(row, " ")
[x, y] = String.split(position, ",")
[vx, vy] = String.split(velocity, ",")
{{String.to_integer(x), String.to_integer(y)},
{String.to_integer(vx), String.to_integer(vy)}}
end
end
def(teleport(position, _velocity, _width, _height, 0), do: position)
def teleport({x, y}, {dx, dy}, width, height, iter) do
x2 = x + dx
y2 = y + dy
x2 =
cond do
x2 < 0 ->
width + x2
x2 >= width ->
abs(width - x2)
true ->
x2
end
y2 =
cond do
y2 < 0 ->
height + y2
y2 >= height ->
abs(height - y2)
true ->
y2
end
teleport({x2, y2}, {dx, dy}, width, height, iter - 1)
end
defp quadrant({x, y}, width, height) do
mid_x = floor(width / 2)
mid_y = floor(height / 2)
cond do
x < mid_x and y < mid_y ->
1
x < mid_x and y > mid_y ->
2
x > mid_x and y < mid_y ->
3
x > mid_x and y > mid_y ->
4
true ->
nil
end
end
def run(input, width, height, iters) do
parse(input)
|> Task.async_stream(
fn {position, velocity} ->
teleport(position, velocity, width, height, iters)
end,
ordered: false
)
|> Enum.map(&elem(&1, 1))
end
@doc ~S"""
iex> Day14.part1("p=0,4 v=3,-3\np=6,3 v=-1,-3\np=10,3 v=-1,2\np=2,0 v=2,-1\np=0,0 v=1,3\np=3,0 v=-2,-2\np=7,6 v=-1,-3\np=3,0 v=-1,-2\np=9,3 v=2,3\np=7,3 v=-1,2\np=2,4 v=2,-3\np=9,5 v=-3,-3\n")
12
"""
def part1(input, sample \\ true) do
{width, height} = if sample, do: {11, 7}, else: {101, 103}
run(input, width, height, 100)
|> Enum.group_by(&quadrant(&1, width, height))
|> Enum.reduce(1, fn
{nil, _g}, acc -> acc
{_g, values}, acc -> acc * Enum.count(values)
end)
end
def part2(input) do
{width, height} = {101, 103}
Enum.find_value(0..15_000, fn i ->
soln = run(input, width, height, i)
limit = 33
group_by_row = Enum.group_by(soln, &elem(&1, 1))
group_by_col = Enum.group_by(soln, &elem(&1, 0))
if Enum.any?(group_by_row, fn {_row, group} -> Enum.count(group) >= limit end) and
Enum.any?(group_by_col, fn {_col, group} -> Enum.count(group) >= limit end) do
soln
end
end)
|> Enum.reduce(%{x: [], y: []}, fn {x, y}, acc ->
acc
|> Map.update!(:x, fn x1 -> [x * 10 | x1] end)
|> Map.update!(:y, fn y1 -> [y * 10 | y1] end)
end)
|> Tucan.scatter("x", "y", width: 101 * 10, height: 103 * 10)
end
end
{:module, Day14, <<70, 79, 82, 49, 0, 0, 30, ...>>, {:part2, 1}}
Day14.part2(input)
{"$schema":"https://vega.github.io/schema/vega-lite/v5.json","data":{"values":[{"x":320,"y":500},{"x":380,"y":440},{"x":440,"y":600},{"x":120,"y":390},{"x":360,"y":500},{"x":210,"y":610},{"x":380,"y":560},{"x":950,"y":0},{"x":110,"y":680},{"x":350,"y":450},{"x":410,"y":540},{"x":550,"y":250},{"x":710,"y":0},{"x":380,"y":510},{"x":360,"y":520},{"x":510,"y":490},{"x":150,"y":250},{"x":510,"y":690},{"x":360,"y":510},{"x":510,"y":550},{"x":130,"y":470},{"x":320,"y":690},{"x":470,"y":180},{"x":510,"y":410},{"x":210,"y":590},{"x":560,"y":960},{"x":210,"y":640},{"x":860,"y":560},{"x":360,"y":590},{"x":390,"y":480},{"x":330,"y":530},{"x":350,"y":180},{"x":350,"y":370},{"x":760,"y":690},{"x":560,"y":870},{"x":350,"y":690},{"x":310,"y":10},{"x":350,"y":510},{"x":830,"y":110},{"x":80,"y":320},{"x":370,"y":860},{"x":430,"y":560},{"x":570,"y":1020},{"x":430,"y":580},{"x":330,"y":590},{"x":510,"y":10},{"x":100,"y":720},{"x":370,"y":600},{"x":300,"y":580},{"x":830,"y":720},{"x":500,"y":370},{"x":510,"y":510},{"x":290,"y":580},{"x":40,"y":680},{"x":320,"y":610},{"x":340,"y":580},{"x":440,"y":370},{"x":310,"y":550},{"x":210,"y":630},{"x":280,"y":590},{"x":770,"y":410},{"x":420,"y":580},{"x":360,"y":530},{"x":370,"y":500},{"x":250,"y":370},{"x":340,"y":550},{"x":320,"y":580},{"x":490,"y":20},{"x":400,"y":540},{"x":510,"y":500},{"x":730,"y":520},{"x":800,"y":40},{"x":900,"y":580},{"x":450,"y":600},{"x":590,"y":990},{"x":400,"y":600},{"x":510,"y":540},{"x":410,"y":580},{"x":400,"y":510},{"x":400,"y":610},{"x":390,"y":500},{"x":400,"y":490},{"x":390,"y":550},{"x":300,"y":370},{"x":110,"y":410},{"x":250,"y":830},{"x":320,"y":490},{"x":390,"y":600},{"x":480,"y":690},{"x":80,"y":190},{"x":290,"y":120},{"x":330,"y":610},{"x":370,"y":590},{"x":420,"y":370},{"x":750,"y":170},{"x":460,"y":370},{"x":290,"y":600},{"x":510,"y":640},{"x":390,"y":510},{"x":750,"y":970},{"x":820,"y":320},{"x":330,"y":280},{"x":510,"y":650},{"x":360,"y":460},{"x":280,"y":610},{"x":350,"y":550},{"x":430,"y":370},{"x":340,"y":450},{"x":120,"y":550},{"x":330,"y":600},{"x":360,"y":580},{"x":370,"y":690},{"x":300,"y":550},{"x":300,"y":610},{"x":380,"y":690},{"x":360,"y":470},{"x":310,"y":560},{"x":330,"y":370},{"x":340,"y":460},{"x":360,"y":640},{"x":580,"y":580},{"x":360,"y":610},{"x":350,"y":600},{"x":410,"y":600},{"x":740,"y":50},{"x":680,"y":470},{"x":210,"y":620},{"x":540,"y":650},{"x":340,"y":370},{"x":510,"y":430},{"x":340,"y":690},{"x":450,"y":610},{"x":370,"y":480},{"x":390,"y":490},{"x":330,"y":500},{"x":510,"y":380},{"x":960,"y":920},{"x":210,"y":560},{"x":230,"y":370},{"x":40,"y":1000},{"x":310,"y":510},{"x":800,"y":60},{"x":510,"y":370},{"x":330,"y":690},{"x":940,"y":150},{"x":480,"y":370},{"x":900,"y":870},{"x":80,"y":980},{"x":340,"y":570},{"x":170,"y":290},{"x":390,"y":690},{"x":880,"y":300},{"x":390,"y":370},{"x":730,"y":210},{"x":170,"y":70},{"x":430,"y":610},{"x":390,"y":460},{"x":420,"y":790},{"x":760,"y":830},{"x":390,"y":540},{"x":210,"y":430},{"x":400,"y":550},{"x":210,"y":670},{"x":370,"y":570},{"x":330,"y":580},{"x":300,"y":590},{"x":380,"y":370},{"x":180,"y":780},{"x":410,"y":550},{"x":400,"y":370},{"x":340,"y":510},{"x":510,"y":590},{"x":350,"y":520},{"x":400,"y":590},{"x":210,"y":200},{"x":370,"y":460},{"x":360,"y":370},{"x":340,"y":500},{"x":340,"y":520},{"x":660,"y":890},{"x":220,"y":790},{"x":330,"y":490},{"x":740,"y":880},{"x":930,"y":420},{"x":210,"y":420},{"x":210,"y":450},{"x":190,"y":300},{"x":310,"y":500},{"x":0,"y":640},{"x":340,"y":530},{"x":210,"y":390},{"x":340,"y":540},{"x":390,"y":590},{"x":380,"y":450},{"x":320,"y":520},{"x":640,"y":440},{"x":370,"y":580},{"x":770,"y":670},{"x":280,"y":600},{"x":900,"y":750},{"x":460,"y":690},{"x":420,"y":550},{"x":210,"y":540},{"x":620,"y":0},{"x":270,"y":610},{"x":40,"y":730},{"x":320,"y":570},{"x":510,"y":910},{"x":400,"y":820},{"x":340,"y":590},{"x":210,"y":550},{"x":360,"y":420},{"x":160,"y":400},{"x":290,"y":560},{"x":400,"y":580},{"x":310,"y":370},{"x":370,"y":490},{"x":840,"y":390},{"x":210,"y":410},{"x":240,"y":690},{"x":320,"y":460},{"x":220,"y":120},{"x":200,"y":780},{"x":350,"y":580},{"x":410,"y":370},{"x":250,"y":0},{"x":380,"y":610},{"x":330,"y":460},{"x":330,"y":510},{"x":350,"y":630},{"x":510,"y":680},{"x":370,"y":130},{"x":360,"y":490},{"x":330,"y":570},{"x":210,"y":570},{"x":410,"y":500},{"x":600,"y":500},{"x":210,"y":500},{"x":400,"y":530},{"x":250,"y":690},{"x":210,"y":380},{"x":350,"y":430},{"x":510,"y":670},{"x":500,"y":690},{"x":300,"y":1020},{"x":210,"y":690},{"x":310,"y":590},{"x":520,"y":170},{"x":390,"y":580},{"x":370,"y":510},{"x":280,"y":560},{"x":320,"y":550},{"x":440,"y":690},{"x":410,"y":610},{"x":840,"y":830},{"x":260,"y":610},{"x":370,"y":530},{"x":380,"y":540},{"x":380,"y":490},{"x":400,"y":690},{"x":670,"y":230},{"x":510,"y":600},{"x":350,"y":570},{"x":510,"y":520},{"x":320,"y":510},{"x":600,"y":40},{"x":470,"y":370},{"x":310,"y":600},{"x":450,"y":690},{"x":370,"y":550},{"x":370,"y":610},{"x":0,"y":900},{"x":260,"y":1020},{"x":510,"y":460},{"x":40,"y":150},{"x":230,"y":690},{"x":510,"y":530},{"x":710,"y":190},{"x":210,"y":440},{"x":420,"y":510},{"x":290,"y":690},{"x":330,"y":480},{"x":380,"y":500},{"x":390,"y":530},{"x":430,"y":590},{"x":230,"y":310},{"x":150,"y":1020},{"x":420,"y":590},{"x":60,"y":860},{"x":940,"y":960},{"x":360,"y":600},{"x":420,"y":570},{"x":350,"y":560},{"x":380,"y":590},{"x":540,"y":420},{"x":920,"y":730},{"x":510,"y":580},{"x":490,"y":370},{"x":410,"y":690},{"x":350,"y":610},{"x":360,"y":570},{"x":680,"y":50},{"x":340,"y":600},{"x":290,"y":610},{"x":370,"y":620},{"x":850,"y":670},{"x":210,"y":520},{"x":210,"y":680},{"x":510,"y":620},{"x":120,"y":590},{"x":310,"y":540},{"x":330,"y":540},{"x":660,"y":560},{"x":540,"y":780},{"x":510,"y":470},{"x":420,"y":610},{"x":360,"y":440},{"x":490,"y":840},{"x":370,"y":540},{"x":370,"y":560},{"x":310,"y":530},{"x":960,"y":820},{"x":390,"y":450},{"x":340,"y":480},{"x":360,"y":630},{"x":730,"y":770},{"x":670,"y":520},{"x":210,"y":490},{"x":760,"y":960},{"x":220,"y":690},{"x":350,"y":440},{"x":350,"y":620},{"x":520,"y":910},{"x":440,"y":610},{"x":310,"y":690},{"x":290,"y":370},{"x":510,"y":390},{"x":360,"y":560},{"x":320,"y":370},{"x":370,"y":640},{"x":360,"y":450},{"x":320,"y":600},{"x":480,"y":940},{"x":220,"y":970},{"x":770,"y":560},{"x":370,"y":170},{"x":800,"y":320},{"x":360,"y":690},{"x":510,"y":570},{"x":410,"y":510},{"x":470,"y":690},{"x":510,"y":450},{"x":390,"y":610},{"x":300,"y":600},{"x":880,"y":0},{"x":310,"y":580},{"x":260,"y":370},{"x":350,"y":640},{"x":350,"y":500},{"x":220,"y":370},{"x":980,"y":510},{"x":380,"y":550},{"x":690,"y":210},{"x":350,"y":480},{"x":270,"y":370},{"x":380,"y":460},{"x":360,"y":550},{"x":510,"y":400},{"x":360,"y":540},{"x":160,"y":360},{"x":490,"y":690},{"x":240,"y":370},{"x":510,"y":480},{"x":310,"y":570},{"x":350,"y":490},{"x":310,"y":610},{"x":210,"y":660},{"x":350,"y":470},{"x":320,"y":540},{"x":370,"y":630},{"x":810,"y":660},{"x":300,"y":510},{"x":600,"y":690},{"x":370,"y":440},{"x":440,"y":10},{"x":640,"y":70},{"x":350,"y":590},{"x":210,"y":530},{"x":420,"y":690},{"x":180,"y":560},{"x":460,"y":610},{"x":400,"y":460},{"x":340,"y":440},{"x":390,"y":520},{"x":450,"y":370},{"x":910,"y":490},{"x":460,"y":900},{"x":130,"y":500},{"x":370,"y":370},{"x":330,"y":450},{"x":110,"y":310},{"x":430,"y":600},{"x":410,"y":590},{"x":320,"y":560},{"x":510,"y":420},{"x":400,"y":500},{"x":210,"y":480},{"x":20,"y":280},{"x":420,"y":540},{"x":550,"y":750},{"x":330,"y":550},{"x":510,"y":630},{"x":210,"y":600},{"x":320,"y":590},{"x":320,"y":220},{"x":380,"y":470},{"x":290,"y":550},{"x":120,"y":80},{"x":990,"y":560},{"x":30,"y":560},{"x":510,"y":660},{"x":280,"y":370},{"x":200,"y":260},{"x":100,"y":880},{"x":380,"y":580},{"x":260,"y":690},{"x":350,"y":110},{"x":190,"y":570},{"x":270,"y":600},{"x":500,"y":940},{"x":310,"y":1010},{"x":280,"y":690},{"x":210,"y":370},{"x":820,"y":210},{"x":390,"y":560},{"x":210,"y":510},{"x":340,"y":560},{"x":410,"y":530},{"x":510,"y":440},{"x":350,"y":460},{"x":370,"y":470},{"x":350,"y":530},{"x":410,"y":570},{"x":270,"y":690},{"x":380,"y":530},{"x":510,"y":610},{"x":380,"y":600},{"x":340,"y":610},{"x":360,"y":430},{"x":440,"y":590},{"x":310,"y":740},{"x":770,"y":530},{"x":370,"y":430},{"x":490,"y":950},{"x":300,"y":540},{"x":210,"y":470},{"x":380,"y":480},{"x":360,"y":480},{"x":470,"y":310},{"x":940,"y":140},{"x":40,"y":270},{"x":390,"y":570},{"x":440,"y":560},{"x":430,"y":1010},{"x":330,"y":520},{"x":400,"y":570},{"x":420,"y":560},{"x":290,"y":10},{"x":320,"y":530},{"x":370,"y":520},{"x":340,"y":490},{"x":380,"y":570},{"x":630,"y":520},{"x":400,"y":560},{"x":210,"y":580},{"x":470,"y":190},{"x":370,"y":450},{"x":400,"y":520},{"x":340,"y":470},{"x":890,"y":1000},{"x":510,"y":560},{"x":350,"y":540},{"x":290,"y":590},{"x":210,"y":460},{"x":310,"y":300},{"x":300,"y":560},{"x":300,"y":570},{"x":480,"y":270},{"x":330,"y":560},{"x":210,"y":400},{"x":210,"y":650},{"x":360,"y":620},{"x":430,"y":690},{"x":420,"y":600},{"x":40,"y":750},{"x":380,"y":520},{"x":300,"y":690},{"x":410,"y":560},{"x":610,"y":780},{"x":430,"y":550}]},"encoding":{"x":{"field":"x","scale":{"zero":false},"type":"quantitative"},"y":{"field":"y","scale":{"zero":false},"type":"quantitative"}},"height":1030,"mark":{"fillOpacity":1,"type":"point"},"width":1010}