day 2024 day 14

This commit is contained in:
Caleb Webber 2024-12-15 00:32:14 -05:00
parent 7dfc62354d
commit e4de674377

View file

@ -0,0 +1,123 @@
# AOC 2024 Day 14
## Section
```elixir
input = """
"""
```
positive `rem` that only returns positive number
```elixir
rrem = fn a, b ->
t = rem(a, b)
if t < 0 do
t + b
else
t
end
end
```
```elixir
quadrant = fn {x, y}, {w, h} ->
{cx, cy} = {div(w, 2), div(h, 2)}
{
(if x < cx, do: -1, else: (if cx < x, do: 1, else: nil)),
(if y < cy, do: -1, else: (if cy < y, do: 1, else: nil))
}
end
```
```elixir
w = 101
h = 103
```
```elixir
pos = for line <- input |> String.trim() |> String.split("\n", trim: true),
[p, v] = String.split(line, " "),
{x,y} = p |> String.split("=") |> Enum.at(1) |> String.split(",") |> Enum.map(&String.to_integer/1) |> List.to_tuple(),
{px, py} = v |> String.split("=") |> Enum.at(1) |> String.split(",") |> Enum.map(&String.to_integer/1) |> List.to_tuple(),
reduce: %{}
do
acc ->
{fx, fy} = {rrem.(x + 100*px, w), rrem.(y + 100*py, h)}
if (fx != div(w, 2) and fy != div(h, 2)) do
acc |> Map.update(quadrant.({fx, fy}, {w, h}), 1, &(&1 + 1))
else
acc
end
end
```
```elixir
pos |> Map.values() |> Enum.product()
```
```elixir
points = for line <- input |> String.trim() |> String.split("\n", trim: true),
[p, v] = String.split(line, " "),
{x,y} = p |> String.split("=") |> Enum.at(1) |> String.split(",") |> Enum.map(&String.to_integer/1) |> List.to_tuple(),
{px, py} = v |> String.split("=") |> Enum.at(1) |> String.split(",") |> Enum.map(&String.to_integer/1) |> List.to_tuple(),
reduce: MapSet.new
do
acc ->
MapSet.put(acc, {{x, y}, {px, py}})
end
```
```elixir
draw = fn points ->
for y <- 0..(h-1) do
for x <- 0..(w-1) do
File.write("buffer.txt", (if MapSet.member?(points, {x, y}), do: "*", else: "."), [:write, :append])
if x == (w-1) do
File.write("buffer.txt", "\n", [:write, :append])
end
end
end
end
```
```elixir
q = Stream.iterate(0, &(&1 + 1))
|> Enum.take(10_000)
|> Enum.reduce(%{}, fn i, seen ->
safety = for {{x, y}, {px, py}} <- points,
reduce: %{} do
acc ->
f = quadrant.({rrem.(x + i*px, w), rrem.(y + i*py, h)}, {w, h})
case f do
{nil, _ } -> acc
{_, nil} -> acc
x -> Map.update(acc, x, 1, &(&1 + 1))
end
end |> Map.values() |> Enum.product()
Map.put(seen, i, safety)
end
)
```
```elixir
q |> Enum.min_by(&elem(&1, 1))
```
I solved part two by a mix of searching frames around the min safety factor. The below cell renders the frames in a range near the min.
```elixir
for i <- 6200..6300 do
for {{x, y}, {px, py}} <- points,
reduce: MapSet.new do
acc ->
f = {rem(x + i*px, w), rem(y + i*py, h)}
MapSet.put(acc, f)
end |> draw.()
end
```
```elixir
```