This commit is contained in:
Caleb Webber 2023-12-14 03:09:18 -05:00
parent 1616abeb6a
commit 60436bc8f0
2 changed files with 108 additions and 0 deletions

105
lib/2023/day14.ex Normal file
View file

@ -0,0 +1,105 @@
defmodule RollingRocks do
def score_rows(rows) do
rows = rows |> String.split("\n")
len = rows |> Enum.count()
rows
|> Enum.with_index()
|> Enum.map(fn {l, i} -> {l, len - i} end)
|> Enum.map(fn {l, i} ->
{l |> String.to_charlist() |> Enum.filter(&(&1 === ?O)) |> Enum.count(), i}
end)
|> Enum.map(fn {c, i} -> c * i end)
|> Enum.sum()
end
def roll_rocks(tiles, direction) do
tiles
|> Enum.reject(fn tile -> tile |> Map.get(:tile) == "" end)
# |> Enum.each(fn tile -> IO.puts(inspect(tile)) end)
|> Enum.chunk_by(fn tile -> tile |> Map.get(:tile) !== "#" end)
|> Enum.flat_map(fn chunk ->
Enum.sort_by(
chunk,
fn m -> Map.get(m, :tile) end,
if(direction === :north or direction === :west, do: :desc, else: :asc)
)
end)
end
def line_to_tile_map({line, r_idx}) do
line
|> String.graphemes()
|> Enum.with_index()
|> Enum.map(fn {c, c_idx} -> %{idx: {r_idx, c_idx}, tile: c} end)
end
def solve_1(input) do
StringUtil.transpose(input)
|> String.split("\n")
|> Enum.with_index()
|> Enum.map(&line_to_tile_map(&1))
|> Enum.map(&roll_rocks(&1, :north))
|> EnumUtil.transpose()
|> Enum.map(fn tilemap ->
tilemap
|> Enum.map(fn tile -> Map.get(tile, :tile) end)
|> Enum.join("")
end)
|> Enum.join("\n")
|> score_rows()
end
def solve_2(input) do
u =
1..(10 ** 9)
|> Enum.reduce_while(
{%{input => 0}, input, nil},
fn i, {map, input, _} ->
rolled = cycle(input)
cont = if Map.has_key?(map, rolled), do: :halt, else: :cont
if cont == :halt do
# IO.puts("collision at #{Map.get(map, rolled)}")
{cont, {map, rolled, Map.get(map, rolled)}}
else
map = Map.put(map, rolled, i)
{cont, {map, rolled, nil}}
end
end
)
map = elem(u, 0)
cycle_start = elem(u, 2)
cycle_repeat = (elem(u, 0) |> Map.values() |> Enum.max()) + 1
offset = rem(10 ** 9 - cycle_start, cycle_repeat - cycle_start) + cycle_start
map
|> Stream.filter(&(elem(&1, 1) === offset))
|> Stream.map(fn {t, x} -> {score_rows(t), x} end)
|> Stream.map(&(elem(&1, 0)))
|> Enum.at(0)
end
def cycle(grid) do
StringUtil.transpose(grid)
|> String.split("\n")
|> Enum.with_index()
|> Enum.map(&line_to_tile_map(&1))
|> Enum.map(&roll_rocks(&1, :north))
|> EnumUtil.transpose()
|> Enum.map(&roll_rocks(&1, :west))
|> EnumUtil.transpose()
|> Enum.map(&roll_rocks(&1, :south))
|> EnumUtil.transpose()
|> Enum.map(&roll_rocks(&1, :east))
|> Enum.map(fn tilemap ->
tilemap
|> Enum.map(fn tile -> Map.get(tile, :tile) end)
|> Enum.join("")
end)
|> Enum.join("\n")
end
end

3
lib/2023/day14_run.ex Normal file
View file

@ -0,0 +1,3 @@
{_, content} = File.read("./input/2023_14.txt")
RollingRocks.solve_2(content) |> IO.puts()