Commit d3097465 authored by Andrew Fontaine's avatar Andrew Fontaine

Day 12 DONE

parent ea92af78
import AdventOfCode
aoc 2019, 12 do
@line_pattern ~r/<x=(?<x>.+), y=(?<y>.+), z=(?<z>.+)>/
def p1(), do: s1(input_stream(), 1000)
def s1(stream, x) do
moons = Enum.map(stream, &parse/1)
Range.new(1, x)
|> Enum.reduce(moons, fn _, moons -> run_step(moons) end)
|> Enum.map(fn %{p: {x1, y1, z1}, v: {xv, yv, zv}} ->
(abs(x1) + abs(y1) + abs(z1)) * (abs(xv) + abs(yv) + abs(zv))
end)
|> Enum.sum()
end
def p2(), do: s2(input_stream())
def s2(stream) do
moons = Enum.map(stream, &parse/1)
moons
|> Enum.map(fn %{p: {x, y, z}, v: {xv, yv, zv}} -> [{x, xv}, {y, yv}, {z, zv}] end)
|> Enum.reduce([[], [], []], fn [x, y, z], [xs, ys, zs] ->
[[x | xs], [y | ys], [z | zs]]
end)
|> Task.async_stream(fn ps ->
1
|> Stream.iterate(&(&1 + 1))
|> Enum.reduce_while(ps, fn c, moons ->
moons = run_step(moons)
if moons == ps do
{:halt, c}
else
{:cont, moons}
end
end)
end)
|> Stream.map(fn {:ok, x} -> x end)
|> Enum.reduce(1, fn x, y -> div(x * y, Integer.gcd(x, y)) end)
end
defp run_step(moons) do
moons
|> Enum.map(fn moon ->
Enum.reduce(moons -- [moon], moon, fn m1, m2 ->
set_velocity(m2, m1)
end)
end)
|> Enum.map(&apply_velocity/1)
end
defp apply_velocity({p, v}), do: {p + v, v}
defp apply_velocity(%{p: {x1, y1, z1}, v: {x2, y2, z2} = v}) do
%{p: {x1 + x2, y1 + y2, z1 + z2}, v: v}
end
defp set_velocity(%{p: p1, v: v1}, %{p: p2}) do
%{p: p1, v: apply_gravity(v1, gravity_diff(p1, p2))}
end
defp set_velocity({p1, v1}, {p2, _v2}) do
{p1, apply_gravity(v1, gravity_diff(p1, p2))}
end
defp apply_gravity({x1, y1, z1}, {x2, y2, z2}) do
{x1 + x2, y1 + y2, z1 + z2}
end
defp apply_gravity(p, v), do: p + v
defp gravity_diff({x1, y1, z1}, {x2, y2, z2}) do
{gravity_diff(x1, x2), gravity_diff(y1, y2), gravity_diff(z1, z2)}
end
defp gravity_diff(p1, p2) when p1 > p2, do: -1
defp gravity_diff(p1, p2) when p1 == p2, do: 0
defp gravity_diff(p1, p2) when p1 < p2, do: 1
defp parse(line) do
%{"x" => x, "y" => y, "z" => z} = Regex.named_captures(@line_pattern, line)
%{p: {String.to_integer(x), String.to_integer(y), String.to_integer(z)}, v: {0, 0, 0}}
end
end
<x=-8, y=-18, z=6>
<x=-11, y=-14, z=4>
<x=8, y=-3, z=-10>
<x=-2, y=-16, z=1>
defmodule AdventOfCode.Y2019.D12Test do
use ExUnit.Case, async: true
alias AdventOfCode.Y2019.D12
test "s1" do
moons = [
"<x=-1, y=0, z=2>",
"<x=2, y=-10, z=-7>",
"<x=4, y=-8, z=8>",
"<x=3, y=5, z=-1>"
]
assert 179 = D12.s1(moons, 10)
end
test "s2" do
moons = [
"<x=-1, y=0, z=2>",
"<x=2, y=-10, z=-7>",
"<x=4, y=-8, z=8>",
"<x=3, y=5, z=-1>"
]
assert 2772 = D12.s2(moons)
moons = [
"<x=-8, y=-10, z=0>",
"<x=5, y=5, z=10>",
"<x=2, y=-7, z=3>",
"<x=9, y=-8, z=-3>"
]
assert 4_686_774_924 = D12.s2(moons)
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment