This commit is contained in:
bluepython508
2023-12-14 09:38:23 +00:00
parent 03b92dd930
commit a7beb06a28
6 changed files with 113 additions and 7 deletions

View File

@@ -4,12 +4,11 @@ defmodule Aoc2023 do
import Aoc2023.Common
def main(input) do
{took, _} = :timer.tc fn ->
parsed = parse(input)
IO.puts("Part 1: #{part1(parsed)}")
IO.puts("Part 2: #{part2(parsed)}")
end
IO.puts("Took #{took / 1_000}ms")
{t_parse, parsed} = :timer.tc fn -> parse(input) end
{t_p1, _} = :timer.tc fn -> IO.puts("Part 1: #{part1(parsed)}") end
{t_p2, _} = :timer.tc fn -> IO.puts("Part 2: #{part2(parsed)}") end
IO.puts("Took #{(t_parse + t_p1 + t_p2) / 1_000}ms (parse: #{t_parse / 1_000}ms, part1: #{t_p1 / 1_000}ms, part2: #{t_p2 / 1_000}ms)")
end
end
end

77
lib/day14.ex Normal file
View File

@@ -0,0 +1,77 @@
defmodule Aoc2023.Day14 do
use Aoc2023
def parse(input) do
input
|> lines
|> Enum.map(&String.to_charlist/1)
end
defp replace_many_at(lst, idxs, val) do
idxs |> Enum.reduce(lst, &List.replace_at(&2, &1, val))
end
defp slide(grid) do
iter = fn recur, grid ->
case grid do
[last | [next | rest]] ->
idxs =
last
|> Enum.with_index()
|> Enum.filter(pipe(elem(0) |> Kernel.==(?O)))
|> Enum.map(pipe(elem(1)))
|> Enum.filter(&(Enum.at(next, &1) == ?.))
[
last |> replace_many_at(idxs, ?.)
| recur.(recur, [next |> replace_many_at(idxs, ?O) | rest])
]
[last] ->
[last]
end
end
loop = fn recur, grid ->
grid_ = iter.(iter, grid)
if grid_ == grid, do: grid, else: recur.(recur, grid_)
end
loop.(loop, grid |> Enum.reverse())
end
defp cycle(grid) do
for _ <- 1..4, reduce: grid do
# reverse |> transpose is rotation clockwise, but slide already reverses
grid -> grid |> slide |> transpose
end
end
defp cycles(grid, n \\ 1_000_000_000, {cache_to_n, cache_from_n} \\ {%{}, %{}}) when n > 0 do
rep_n = Map.get(cache_to_n, grid)
if rep_n do
n_ = rep_n - Integer.mod(n, rep_n - n)
cache_from_n |> Map.get(n_)
else
grid_ = cycle(grid)
cycles(grid_, n - 1, {Map.put(cache_to_n, grid, n), Map.put(cache_from_n, n, grid)})
end
end
def part1(input) do
input
|> slide
|> Enum.with_index(1)
|> Enum.map(fn {row, i} -> Enum.count(row, &(&1 == ?O)) * i end)
|> Enum.sum()
end
def part2(input) do
input
|> cycles()
|> Enum.reverse
|> Enum.with_index(1)
|> Enum.map(fn {row, i} -> Enum.count(row, &(&1 == ?O)) * i end)
|> Enum.sum()
end
end

View File

@@ -15,6 +15,7 @@ defmodule Mix.Tasks.Aoc do
defp module(11), do: Aoc2023.Day11
defp module(12), do: Aoc2023.Day12
defp module(13), do: Aoc2023.Day13
defp module(14), do: Aoc2023.Day14
# [MODULE INSERTION POINT]
defp base_dir(), do: System.get_env("AOC_BASE")
@@ -107,6 +108,10 @@ defmodule Mix.Tasks.Aoc do
create_file("#{tests_dir(day)}#{last + 1}", IO.read(:stdio, :eof))
end
defp run(day, ["test", "expected", test, part, value]) do
create_file("#{tests_dir(day)}#{test}.#{part}", value)
end
defp run(day, ["test", "expected", test, part]) do
create_file("#{tests_dir(day)}#{test}.#{part}", IO.read(:stdio, :eof))
end
@@ -162,6 +167,19 @@ defmodule Mix.Tasks.Aoc do
run_file(day, "#{base_dir()}/inputs/day#{day}")
end
defp run(day, ["run", "submit", part]) do
run(day, ["fetch"])
mod = module(day)
parsed = mod.parse(read("#{base_dir()}/inputs/day#{day}"))
val = case part do
"1" -> mod.part1(parsed)
"2" -> mod.part2(parsed)
end
HTTPoison.start()
resp = HTTPoison.post!("https://adventofcode.com/2023/day/#{day}/answer", {:form, [level: part, answer: stringify(val)]}, "user-agent": "aoc-ex by ben@soroos.net", cookie: "session=#{System.get_env("AOC_SESSION")}")
resp |> dbg
end
defp run(day, ["run", "-"]) do
run_file(day)
end
@@ -209,4 +227,4 @@ defmodule Mix.Tasks.Aoc do
{:noreply, state}
end
end
end
end