Compare commits
1 Commits
main
..
89ded18386
| Author | SHA1 | Date | |
|---|---|---|---|
| 89ded18386 |
+3
-5
@@ -4,11 +4,9 @@ defmodule Aoc2023 do
|
|||||||
import Aoc2023.Common
|
import Aoc2023.Common
|
||||||
|
|
||||||
def main(input) do
|
def main(input) do
|
||||||
{t_parse, parsed} = :timer.tc fn -> parse(input) end
|
parsed = parse(input)
|
||||||
{t_p1, _} = :timer.tc fn -> IO.puts("Part 1: #{part1(parsed)}") end
|
IO.puts("Part 1: #{part1(parsed)}")
|
||||||
|
IO.puts("Part 2: #{part2(parsed)}")
|
||||||
{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
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,66 +1,2 @@
|
|||||||
defmodule Aoc2023.Common do
|
defmodule Aoc2023.Common do
|
||||||
def stringify(s) when is_binary(s) do s end
|
|
||||||
def stringify(n) when is_integer(n) do inspect(n) end
|
|
||||||
def stringify(nil), do: "nil"
|
|
||||||
|
|
||||||
def map_nth(tup, n, fun) do
|
|
||||||
put_elem(tup, n, fun.(elem(tup, n)))
|
|
||||||
end
|
|
||||||
|
|
||||||
defmacro pipe(expr) do
|
|
||||||
quote do
|
|
||||||
fn (val) -> val |> unquote(expr) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defmacro l &&& r do
|
|
||||||
quote do
|
|
||||||
fn val ->
|
|
||||||
l = val |> unquote(l)
|
|
||||||
r = val |> unquote(r)
|
|
||||||
{l, r}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def runs(lst, f) do
|
|
||||||
lst
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.chunk_by(pipe(elem(0) |> f.()))
|
|
||||||
|> Enum.filter(pipe(Enum.at(0) |> elem(0) |> f.()))
|
|
||||||
|> Enum.map(Enum.at(0) |> elem(1) &&& length)
|
|
||||||
end
|
|
||||||
|
|
||||||
def id(x), do: x
|
|
||||||
def const(_, x), do: x
|
|
||||||
|
|
||||||
def lines(x), do: String.split(x, "\n")
|
|
||||||
|
|
||||||
def head([head | _]), do: head
|
|
||||||
def head([]), do: nil
|
|
||||||
def tail([_ | tail]), do: tail
|
|
||||||
def tail([]), do: nil
|
|
||||||
|
|
||||||
def lcm(a, b), do: div(abs(a*b), Integer.gcd(a,b))
|
|
||||||
def lcm(ls), do: ls |> Enum.reduce(&lcm/2)
|
|
||||||
|
|
||||||
def list_map_at(l, n, f) do
|
|
||||||
List.replace_at(l, n, f.(Enum.at(l, n)))
|
|
||||||
end
|
|
||||||
|
|
||||||
def transpose(l), do: l |> Enum.zip |> Enum.map(&Tuple.to_list/1)
|
|
||||||
|
|
||||||
def collapse(enum, v) do
|
|
||||||
enum
|
|
||||||
|> Stream.zip(enum |> Stream.drop(1) |> Stream.concat([nil]))
|
|
||||||
|> Stream.filter(fn {a, b} -> a != v || b != v end)
|
|
||||||
|> Stream.map(pipe(elem(0)))
|
|
||||||
end
|
|
||||||
|
|
||||||
def repeat(_, 0), do: []
|
|
||||||
def repeat(lst, n), do: Enum.concat(lst, repeat(lst, n - 1))
|
|
||||||
|
|
||||||
def add_vec({y, x}, {y_, x_}) do
|
|
||||||
{y + y_, x + x_}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
+2
-36
@@ -2,48 +2,14 @@ defmodule Aoc2023.Day1 do
|
|||||||
use Aoc2023
|
use Aoc2023
|
||||||
|
|
||||||
def parse(input) do
|
def parse(input) do
|
||||||
fn (replacement) ->
|
|
||||||
input
|
input
|
||||||
|> String.split("\n")
|
|
||||||
|> Enum.map(replacement)
|
|
||||||
|> Enum.map(fn (line) ->
|
|
||||||
line
|
|
||||||
|> String.to_charlist()
|
|
||||||
|> Enum.filter(&(?0 <= &1 && &1 <= ?9))
|
|
||||||
|> Enum.map(&(&1 - ?0))
|
|
||||||
end)
|
|
||||||
|> Enum.map(&[List.first(&1), List.last(&1)])
|
|
||||||
|> Enum.filter(fn (l) -> Enum.all?(l, &(&1 != nil)) end)
|
|
||||||
|> Enum.map(&Integer.undigits/1)
|
|
||||||
|> Enum.sum
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def part1(input) do
|
def part1(input) do
|
||||||
input.(fn line -> line end)
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@numbers [
|
|
||||||
"one",
|
|
||||||
"two",
|
|
||||||
"three",
|
|
||||||
"four",
|
|
||||||
"five",
|
|
||||||
"six",
|
|
||||||
"seven",
|
|
||||||
"eight",
|
|
||||||
"nine",
|
|
||||||
]
|
|
||||||
|
|
||||||
defp replacements(line) do
|
|
||||||
line
|
|
||||||
|> String.replace(@numbers, fn (n) -> Integer.to_string(Enum.find_index(@numbers, &(&1 == n)) + 1) <> String.slice(n, 1..String.length(n)) end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp replacements_rec(line) do
|
|
||||||
if replacements(line) == line, do: line, else: replacements_rec(replacements(line))
|
|
||||||
end
|
|
||||||
def part2(input) do
|
def part2(input) do
|
||||||
input.(&replacements_rec/1)
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
defmodule Aoc2023.Day10 do
|
|
||||||
use Aoc2023
|
|
||||||
require Integer
|
|
||||||
|
|
||||||
@connections %{
|
|
||||||
?| => [{-1, 0}, {1, 0}],
|
|
||||||
?- => [{0, -1}, {0, 1}],
|
|
||||||
?L => [{-1, 0}, {0, 1}],
|
|
||||||
?J => [{-1, 0}, {0, -1}],
|
|
||||||
?7 => [{1, 0}, {0, -1}],
|
|
||||||
?F => [{1, 0}, {0, 1}],
|
|
||||||
?. => [],
|
|
||||||
?S => []
|
|
||||||
}
|
|
||||||
|
|
||||||
defp path(s_conns, conns) do
|
|
||||||
loop = fn recur, checked, checking ->
|
|
||||||
checked_ = MapSet.union(checked, checking)
|
|
||||||
|
|
||||||
checking_ =
|
|
||||||
checking
|
|
||||||
|> Enum.flat_map(&Map.get(conns, &1, []))
|
|
||||||
|> MapSet.new()
|
|
||||||
|> MapSet.difference(checked_)
|
|
||||||
|
|
||||||
if MapSet.size(checking_) > 0, do: recur.(recur, checked_, checking_), else: checked_
|
|
||||||
end
|
|
||||||
|
|
||||||
loop.(loop, MapSet.new(), MapSet.new(s_conns))
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
grid =
|
|
||||||
input
|
|
||||||
|> lines
|
|
||||||
|> Enum.map(&String.to_charlist/1)
|
|
||||||
|> Enum.with_index()
|
|
||||||
|
|
||||||
s =
|
|
||||||
grid
|
|
||||||
|> Enum.find_value(fn {line, y} ->
|
|
||||||
x = line |> Enum.find_index(&(&1 == ?S))
|
|
||||||
if x, do: {y, x}
|
|
||||||
end)
|
|
||||||
|
|
||||||
conns =
|
|
||||||
grid
|
|
||||||
|> Enum.flat_map(fn {row, y} ->
|
|
||||||
row
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.map(fn {c, x} ->
|
|
||||||
{
|
|
||||||
{y, x},
|
|
||||||
Map.get(@connections, c) |> Enum.map(pipe(add_vec({y, x})))
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|> Enum.into(%{})
|
|
||||||
|
|
||||||
s_conns = conns |> Enum.filter(&(s in elem(&1, 1))) |> Enum.map(pipe(elem(0)))
|
|
||||||
{s, s_conns, grid, path(s_conns, conns)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1({_, _, _, path}) do
|
|
||||||
path
|
|
||||||
|> MapSet.size()
|
|
||||||
|> then(&(&1 / 2))
|
|
||||||
|> trunc()
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2({{sy, sx}, s_conns, grid, path}) do
|
|
||||||
s_dirs = s_conns |> Enum.map(pipe(add_vec({-sy, -sx}))) |> Enum.sort()
|
|
||||||
s_char = @connections |> Enum.find(fn {_, conns} -> Enum.sort(conns) == s_dirs end) |> elem(0)
|
|
||||||
grid_ = grid |> list_map_at(sy, pipe(map_nth(0, pipe(List.replace_at(sx, s_char)))))
|
|
||||||
|
|
||||||
grid_
|
|
||||||
|> Stream.map(fn {line, y} ->
|
|
||||||
for x <- 0..length(line) - 1, reduce: {false, 0} do
|
|
||||||
{within, area} ->
|
|
||||||
cond do
|
|
||||||
{y, x} in path and Enum.at(line, x) in [?L, ?J, ?|] -> {not within, area}
|
|
||||||
{y, x} in path -> {within, area}
|
|
||||||
within -> {within, area + 1}
|
|
||||||
true -> {within, area}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|> elem(1)
|
|
||||||
end)
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
defmodule Aoc2023.Day11 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
coords =
|
|
||||||
input
|
|
||||||
|> lines
|
|
||||||
|> Enum.map(pipe(String.to_charlist() |> Enum.map(&(&1 == ?#))))
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.flat_map(fn {row, y} ->
|
|
||||||
row
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.filter(pipe(elem(0)))
|
|
||||||
|> Enum.map(fn {_, x} -> {y, x} end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
ys = coords |> Enum.map(pipe(elem(0))) |> MapSet.new()
|
|
||||||
empty_rows = MapSet.difference(MapSet.new(0..(ys |> Enum.max())), ys)
|
|
||||||
xs = coords |> Enum.map(pipe(elem(1))) |> MapSet.new()
|
|
||||||
empty_cols = MapSet.difference(MapSet.new(0..(xs |> Enum.max())), xs)
|
|
||||||
fn expansion ->
|
|
||||||
coords_ =
|
|
||||||
coords
|
|
||||||
|> Enum.map(fn {y, x} ->
|
|
||||||
{y + Enum.count(empty_rows, &(&1 < y)) * (expansion - 1),
|
|
||||||
x + Enum.count(empty_cols, &(&1 < x)) * (expansion - 1)}
|
|
||||||
end)
|
|
||||||
|
|
||||||
coords_
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.flat_map(fn {c, i} -> coords_ |> Enum.drop(i + 1) |> Enum.map(&{c, &1}) end)
|
|
||||||
|> Enum.map(&dist/1)
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp dist({{y1, x1}, {y2, x2}}) do
|
|
||||||
abs(x1 - x2) + abs(y1 - y2)
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1(input) do
|
|
||||||
input.(2)
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
input.(1_000_000)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
defmodule Aoc2023.Day12 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
defmodule Cache do
|
|
||||||
use GenServer
|
|
||||||
|
|
||||||
def start do
|
|
||||||
{:ok, pid} = GenServer.start_link(Cache, nil)
|
|
||||||
pid
|
|
||||||
end
|
|
||||||
|
|
||||||
def memoize(cache, key, fun) do
|
|
||||||
got = GenServer.call(cache, {:get, key})
|
|
||||||
if got == nil do
|
|
||||||
val = fun.(key)
|
|
||||||
GenServer.call(cache, {:set, key, val})
|
|
||||||
val
|
|
||||||
else
|
|
||||||
got
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def init(_) do
|
|
||||||
{:ok, %{}}
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def handle_call({:get, key}, _, state) do
|
|
||||||
case state do
|
|
||||||
%{^key => value} ->
|
|
||||||
{:reply, value, state}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
{:reply, nil, state}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def handle_call({:set, key, value}, _, state) do
|
|
||||||
{:reply, nil, Map.put_new(state, key, value)}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
input
|
|
||||||
|> lines
|
|
||||||
|> Enum.map(
|
|
||||||
pipe(
|
|
||||||
String.split()
|
|
||||||
|> then(fn [rec, blocks] ->
|
|
||||||
{rec |> String.to_charlist(),
|
|
||||||
blocks |> String.split(",") |> Enum.map(&String.to_integer/1)}
|
|
||||||
end)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp possibilities({rec, blocks}) do
|
|
||||||
loop = fn recur, arg ->
|
|
||||||
case arg do
|
|
||||||
{rec, []} -> if Enum.all?(rec, &(&1 in [??, ?.])) do 1 else 0 end
|
|
||||||
{rec, [block | blocks]} ->
|
|
||||||
# Expect rec to start with any number of ./?s up to the max allowing all remaining groups
|
|
||||||
# i.e. their lengths + an undamaged seperator
|
|
||||||
0..(length(rec) - Enum.sum(blocks) - length(blocks) - block)
|
|
||||||
|> Enum.map(fn i -> repeat('.', i) ++ repeat('#', block) ++ '.' end)
|
|
||||||
|> Enum.filter(pipe(Enum.zip_with(rec, &(&1 == &2 || &2 == ??)) |> Enum.all?))
|
|
||||||
|> Enum.map(&(recur.(recur, {Enum.drop(rec, length(&1)), blocks})))
|
|
||||||
|> Enum.sum
|
|
||||||
end
|
|
||||||
end
|
|
||||||
cache = Cache.start()
|
|
||||||
memoized = fn recur, arg -> Cache.memoize(cache, arg, fn arg -> loop.(recur, arg) end) end
|
|
||||||
memoized.(memoized, {rec, blocks})
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1(input) do
|
|
||||||
input
|
|
||||||
|> Enum.map(pipe(possibilities()))
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
input
|
|
||||||
|> Enum.map(fn {rec, blocks} -> {
|
|
||||||
[rec] |> repeat(5) |> Enum.intersperse('?') |> Enum.flat_map(&id/1),
|
|
||||||
repeat(blocks, 5)
|
|
||||||
} end)
|
|
||||||
|> Enum.map(&possibilities/1)
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
defmodule Aoc2023.Day13 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
input
|
|
||||||
|> String.split("\n\n")
|
|
||||||
|> Enum.map(pipe(lines |> Enum.map(&String.to_charlist/1)))
|
|
||||||
end
|
|
||||||
|
|
||||||
defp reflected_row(block, smudges) do
|
|
||||||
0..(length(block) - 2)
|
|
||||||
|> Enum.filter(fn i ->
|
|
||||||
Enum.zip_with(
|
|
||||||
Enum.take(block, i + 1) |> Enum.reverse() |> Enum.concat(),
|
|
||||||
Enum.drop(block, i + 1) |> Enum.concat(),
|
|
||||||
&Kernel.==/2
|
|
||||||
)
|
|
||||||
|> Enum.count(&(not &1))
|
|
||||||
|> Kernel.==(smudges)
|
|
||||||
end)
|
|
||||||
|> head
|
|
||||||
end
|
|
||||||
|
|
||||||
defp reflected_column(block, smudges) do
|
|
||||||
block |> transpose() |> reflected_row(smudges)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp reflection(block, smudges \\ 0) do
|
|
||||||
row = reflected_row(block, smudges)
|
|
||||||
if row != nil, do: {:h, row + 1}, else: {:v, reflected_column(block, smudges) + 1}
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1(input) do
|
|
||||||
reflections = input |> Enum.map(&reflection/1)
|
|
||||||
|
|
||||||
(Keyword.get_values(reflections, :h) |> Enum.sum()) * 100 +
|
|
||||||
(Keyword.get_values(reflections, :v) |> Enum.sum())
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
reflections = input |> Enum.map(pipe(reflection(1)))
|
|
||||||
|
|
||||||
(Keyword.get_values(reflections, :h) |> Enum.sum()) * 100 +
|
|
||||||
(Keyword.get_values(reflections, :v) |> Enum.sum())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
defmodule Aoc2023.Day15 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
input |> String.split(",")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp hash(str) do
|
|
||||||
for <<char <- str>>, reduce: 0 do
|
|
||||||
acc -> Bitwise.band((acc + char) * 17, 255)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1(input) do
|
|
||||||
input |> Enum.map(&hash/1) |> Enum.sum
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
for instr <- input, reduce: 0..255 |> Enum.map(&{&1, []}) |> Enum.into(%{}) do
|
|
||||||
boxes ->
|
|
||||||
[_, label, op, lens] = Regex.run(~r/([a-z]+)([-=])(\d*)/, instr)
|
|
||||||
box = hash(label)
|
|
||||||
label = String.to_atom(label)
|
|
||||||
case op do
|
|
||||||
"=" -> boxes |> Map.update!(box, &Keyword.update(&1, label, String.to_integer(lens), fn _ -> String.to_integer(lens) end))
|
|
||||||
"-" -> boxes |> Map.update!(box, &Keyword.delete(&1, label))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|> Enum.flat_map(fn {box, lenses} -> lenses |> Enum.with_index(1) |> Enum.map(fn {{_, focus}, i} -> focus * (box + 1) * i end) end)
|
|
||||||
|> Enum.sum
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
defmodule Aoc2023.Day16 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
defp emissions(char, dir) do
|
|
||||||
case {char, dir} do
|
|
||||||
{?., dir} -> [dir]
|
|
||||||
{?-, {0, dir}} -> [{0, dir}]
|
|
||||||
{?-, {_, 0}} -> [{0, -1}, {0, 1}]
|
|
||||||
{?|, {dir, 0}} -> [{dir, 0}]
|
|
||||||
{?|, {0, _}} -> [{-1, 0}, {1, 0}]
|
|
||||||
{?/, {dir, 0}} -> [{0, -dir}]
|
|
||||||
{?/, {0, dir}} -> [{-dir, 0}]
|
|
||||||
{?\\, {dir, 0}} -> [{0, dir}]
|
|
||||||
{?\\, {0, dir}} -> [{dir, 0}]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
input
|
|
||||||
|> lines
|
|
||||||
|> Enum.map(&String.to_charlist/1)
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.flat_map(fn {row, y} ->
|
|
||||||
row |> Enum.with_index() |> Enum.map(fn {c, x} -> {{y, x}, c} end)
|
|
||||||
end)
|
|
||||||
|> Enum.into(%{})
|
|
||||||
end
|
|
||||||
|
|
||||||
defp run(input, heads) do
|
|
||||||
loop = fn recur, energized, heads ->
|
|
||||||
energized_ = MapSet.union(energized, heads |> MapSet.new())
|
|
||||||
|
|
||||||
heads_ =
|
|
||||||
heads
|
|
||||||
|> Enum.flat_map(fn {coord, dir} ->
|
|
||||||
char = Map.get(input, coord)
|
|
||||||
|
|
||||||
if char,
|
|
||||||
do:
|
|
||||||
emissions(char, dir)
|
|
||||||
|> Enum.map(&{add_vec(coord, &1), &1})
|
|
||||||
|> Enum.reject(&MapSet.member?(energized_, &1))
|
|
||||||
|> Enum.filter(&Map.has_key?(input, elem(&1, 0))),
|
|
||||||
else: []
|
|
||||||
end)
|
|
||||||
|
|
||||||
if length(heads_) > 0, do: recur.(recur, energized_, heads_), else: energized_
|
|
||||||
end
|
|
||||||
|
|
||||||
loop.(loop, MapSet.new(), heads) |> Enum.map(pipe(elem(0))) |> MapSet.new() |> MapSet.size()
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1(input) do
|
|
||||||
run(input, [{{0, 0}, {0, 1}}])
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
{my, mx} = input |> Enum.map(pipe(elem(0))) |> Enum.max()
|
|
||||||
|
|
||||||
[
|
|
||||||
0..my |> Enum.map(&{{&1, 0}, {0, 1}}),
|
|
||||||
0..my |> Enum.map(&{{&1, mx}, {0, -1}}),
|
|
||||||
0..mx |> Enum.map(&{{0, &1}, {1, 0}}),
|
|
||||||
0..mx |> Enum.map(&{{my, &1}, {-1, 0}})
|
|
||||||
] |> Enum.concat |> Enum.map(&run(input, [&1])) |> Enum.max
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-167
@@ -1,167 +0,0 @@
|
|||||||
defmodule Aoc2023.Day17 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
defmodule PriorityQueue do
|
|
||||||
defstruct [:set]
|
|
||||||
def new(contents \\ []), do: %__MODULE__{set: :gb_sets.from_list(contents)}
|
|
||||||
|
|
||||||
def add(%__MODULE__{set: set}, elem, prio) do
|
|
||||||
%__MODULE__{set: :gb_sets.add({prio, elem}, set)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def size(%__MODULE__{set: set}) do
|
|
||||||
:gb_sets.size(set)
|
|
||||||
end
|
|
||||||
|
|
||||||
def pop_min(%__MODULE__{set: set}) do
|
|
||||||
case :gb_sets.size(set) do
|
|
||||||
0 ->
|
|
||||||
{nil, new()}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
{res, set} = :gb_sets.take_smallest(set)
|
|
||||||
{res, %__MODULE__{set: set}}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defimpl Inspect do
|
|
||||||
import Inspect.Algebra
|
|
||||||
|
|
||||||
def inspect(%PriorityQueue{set: set}, opts) do
|
|
||||||
concat(["#PriorityQueue.new(", to_doc(:gb_sets.to_list(set), opts), ")"])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
lines = input |> lines
|
|
||||||
|
|
||||||
{
|
|
||||||
{lines |> length() |> Kernel.-(1), lines |> head |> String.length() |> Kernel.-(1)},
|
|
||||||
lines
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.flat_map(fn {row, y} ->
|
|
||||||
row
|
|
||||||
|> String.to_charlist()
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.map(fn {cost, x} -> {{y, x}, String.to_integer(<<cost>>)} end)
|
|
||||||
end)
|
|
||||||
|> Enum.into(%{})
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp a_star(starts, neighbors, heuristic, is_goal) do
|
|
||||||
loop = fn recur, explored, frontier ->
|
|
||||||
{explored, frontier}
|
|
||||||
{{_, current}, frontier} = PriorityQueue.pop_min(frontier)
|
|
||||||
|
|
||||||
if is_goal.(current) do
|
|
||||||
{explored, current}
|
|
||||||
else
|
|
||||||
cost_to_here = Map.get(explored, current) |> elem(1)
|
|
||||||
|
|
||||||
{explored, frontier} =
|
|
||||||
for {neighbor, cost} <- neighbors.(current), reduce: {explored, frontier} do
|
|
||||||
{explored, frontier} ->
|
|
||||||
cost_ = cost_to_here + cost
|
|
||||||
|
|
||||||
if Map.get(explored, neighbor, {nil, cost_}) |> elem(1) < cost_ do
|
|
||||||
{explored, frontier}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Map.put(explored, neighbor, {current, cost_}),
|
|
||||||
PriorityQueue.add(frontier, neighbor, cost_ + heuristic.(neighbor))
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
recur.(recur, explored, frontier)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
{explored, goal} =
|
|
||||||
loop.(
|
|
||||||
loop,
|
|
||||||
starts |> Enum.map(&{&1, {nil, 0}}) |> Enum.into(%{}),
|
|
||||||
starts |> Enum.map(&{0, &1}) |> PriorityQueue.new()
|
|
||||||
)
|
|
||||||
|
|
||||||
# This doesn't include the starting point
|
|
||||||
path_find = fn recur, point, path ->
|
|
||||||
case Map.get(explored, point) do
|
|
||||||
nil -> path
|
|
||||||
{nil, _} -> path
|
|
||||||
{prev, _} -> recur.(recur, prev, [point | path])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
path_find.(path_find, goal, [])
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1({{my, mx}, grid}) do
|
|
||||||
# Nodes are y, x, dir, straight length
|
|
||||||
a_star(
|
|
||||||
[{0, 0, :d, 0}, {0, 0, :r, 0}],
|
|
||||||
fn {y, x, dir, len} ->
|
|
||||||
case dir do
|
|
||||||
:u ->
|
|
||||||
[{y, x - 1, :l, 0}, {y, x + 1, :r, 0}] ++
|
|
||||||
if len < 2, do: [{y + 1, x, dir, len + 1}], else: []
|
|
||||||
|
|
||||||
:d ->
|
|
||||||
[{y, x - 1, :l, 0}, {y, x + 1, :r, 0}] ++
|
|
||||||
if len < 2, do: [{y - 1, x, dir, len + 1}], else: []
|
|
||||||
|
|
||||||
:l ->
|
|
||||||
[{y + 1, x, :u, 0}, {y - 1, x, :d, 0}] ++
|
|
||||||
if len < 2, do: [{y, x - 1, dir, len + 1}], else: []
|
|
||||||
|
|
||||||
:r ->
|
|
||||||
[{y + 1, x, :u, 0}, {y - 1, x, :d, 0}] ++
|
|
||||||
if len < 2, do: [{y, x + 1, dir, len + 1}], else: []
|
|
||||||
end
|
|
||||||
|> Enum.filter(fn {y, x, _, _} -> y in 0..my and x in 0..mx end)
|
|
||||||
|> Enum.map(fn {y, x, _, _} = pos -> {pos, Map.get(grid, {y, x})} end)
|
|
||||||
end,
|
|
||||||
fn {y, x, _, _} -> abs(y - my) + abs(x - mx) end,
|
|
||||||
fn {y, x, _, _} -> {y, x} == {my, mx} end
|
|
||||||
)
|
|
||||||
|> Enum.map(fn {y, x, _, _} -> Map.get(grid, {y, x}) end)
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2({{my, mx}, grid}) do
|
|
||||||
# Nodes are y, x, dir, straight length
|
|
||||||
a_star(
|
|
||||||
[{0, 0, :r, 0}, {0, 0, :d, 0}, {0, 0, :u, 0}, {0, 0, :l, 0}],
|
|
||||||
fn {y, x, dir, len} ->
|
|
||||||
(if(len < 9,
|
|
||||||
do:
|
|
||||||
case dir do
|
|
||||||
:u -> [{y + 1, x, :u, len + 1}]
|
|
||||||
:d -> [{y - 1, x, :d, len + 1}]
|
|
||||||
:l -> [{y, x - 1, :l, len + 1}]
|
|
||||||
:r -> [{y, x + 1, :r, len + 1}]
|
|
||||||
end,
|
|
||||||
else: []
|
|
||||||
) ++
|
|
||||||
if(len > 2,
|
|
||||||
do:
|
|
||||||
case dir do
|
|
||||||
:u -> [{y, x - 1, :l, 0}, {y, x + 1, :r, 0}]
|
|
||||||
:d -> [{y, x - 1, :l, 0}, {y, x + 1, :r, 0}]
|
|
||||||
:l -> [{y + 1, x, :u, 0}, {y - 1, x, :d, 0}]
|
|
||||||
:r -> [{y + 1, x, :u, 0}, {y - 1, x, :d, 0}]
|
|
||||||
end,
|
|
||||||
else: []
|
|
||||||
))
|
|
||||||
|> Enum.filter(fn {y, x, _, _} -> y in 0..my and x in 0..mx end)
|
|
||||||
|> Enum.map(fn {y, x, _, _} = pos -> {pos, Map.get(grid, {y, x})} end)
|
|
||||||
end,
|
|
||||||
fn {y, x, _, _} -> abs(y - my) + abs(x - mx) end,
|
|
||||||
fn {y, x, _, len} -> {y, x} == {my, mx} and len > 2 end
|
|
||||||
)
|
|
||||||
|> Enum.map(fn {y, x, _, _} -> Map.get(grid, {y, x}) end)
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
defmodule Aoc2023.Day18 do
|
|
||||||
require Integer
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
input
|
|
||||||
|> lines
|
|
||||||
|> Enum.map(fn line ->
|
|
||||||
[dir, n, color] =
|
|
||||||
Regex.run(~r/^([RDLU]) (\d+) \(#([0-9a-f]{6})\)$/, line, capture: :all_but_first)
|
|
||||||
|
|
||||||
{
|
|
||||||
dir |> String.to_charlist() |> head,
|
|
||||||
n |> String.to_integer(),
|
|
||||||
color
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp simulate({pos, dist, points}, {dir, n}) do
|
|
||||||
p =
|
|
||||||
case dir do
|
|
||||||
:u -> {-n, 0}
|
|
||||||
:d -> {n, 0}
|
|
||||||
:r -> {0, n}
|
|
||||||
:l -> {0, -n}
|
|
||||||
end
|
|
||||||
|> add_vec(pos)
|
|
||||||
|
|
||||||
{p, dist + n, [p | points]}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp area(perim, points),
|
|
||||||
# Shoelace formula
|
|
||||||
do:
|
|
||||||
Stream.zip(points, points |> Stream.cycle() |> Stream.drop(1))
|
|
||||||
|> Stream.map(fn {{y, x}, {y1, x1}} -> x * y1 - x1 * y end)
|
|
||||||
|> Enum.sum()
|
|
||||||
|> abs
|
|
||||||
|> then(&((&1 + perim) / 2))
|
|
||||||
|> trunc
|
|
||||||
|
|
||||||
defp run(instrs) do
|
|
||||||
{_, dist, points} = instrs |> Enum.reduce({{0, 0}, 2, [{0, 0}]}, &simulate(&2, &1))
|
|
||||||
area(dist, points)
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1(input) do
|
|
||||||
run(for {dir, n, _} <- input, do: {case dir do
|
|
||||||
?U -> :u
|
|
||||||
?D -> :d
|
|
||||||
?L -> :l
|
|
||||||
?R -> :r
|
|
||||||
end, n})
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
run(for {_, _, <<len::binary-size(5), dir::integer>>} <- input do
|
|
||||||
{case dir do
|
|
||||||
?0 -> :r
|
|
||||||
?1 -> :d
|
|
||||||
?2 -> :l
|
|
||||||
?3 -> :u
|
|
||||||
end, String.to_integer(len, 16)}
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-52
@@ -1,52 +0,0 @@
|
|||||||
defmodule Aoc2023.Day2 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
input
|
|
||||||
|> String.split("\n")
|
|
||||||
|> Enum.map(pipe(
|
|
||||||
String.split(": ")
|
|
||||||
|> then(fn ["Game " <> id, rounds] ->
|
|
||||||
{String.to_integer(id),
|
|
||||||
rounds
|
|
||||||
|> String.split("; ")
|
|
||||||
|> Enum.map(pipe(
|
|
||||||
String.split(", ")
|
|
||||||
|> Enum.map(pipe(
|
|
||||||
String.split(" ")
|
|
||||||
|> then(fn [n, color] ->
|
|
||||||
{String.to_existing_atom(color), String.to_integer(n)}
|
|
||||||
end)
|
|
||||||
))
|
|
||||||
))}
|
|
||||||
end)
|
|
||||||
))
|
|
||||||
|> Enum.into(%{})
|
|
||||||
end
|
|
||||||
|
|
||||||
@part1_available [
|
|
||||||
red: 12, green: 13, blue: 14
|
|
||||||
]
|
|
||||||
def part1(input) do
|
|
||||||
input
|
|
||||||
|> Enum.filter(pipe(
|
|
||||||
elem(1)
|
|
||||||
|> Enum.all?(pipe(
|
|
||||||
Enum.all?(fn {color, num} -> Keyword.get(@part1_available, color, 0) >= num end)
|
|
||||||
))
|
|
||||||
))
|
|
||||||
|> Enum.map(pipe(elem(0)))
|
|
||||||
|> Enum.sum
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
input
|
|
||||||
|> Enum.map(pipe(
|
|
||||||
elem(1)
|
|
||||||
|> Enum.reduce(&(Keyword.merge(&1, &2, fn _, m1, m2 -> max(m1, m2) end)))
|
|
||||||
|> Enum.map(pipe(elem(1)))
|
|
||||||
|> Enum.product
|
|
||||||
))
|
|
||||||
|> Enum.sum
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-110
@@ -1,110 +0,0 @@
|
|||||||
defmodule Aoc2023.Day3 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
@symbols [
|
|
||||||
?$,
|
|
||||||
?%,
|
|
||||||
?&,
|
|
||||||
?*,
|
|
||||||
?+,
|
|
||||||
?-,
|
|
||||||
?/,
|
|
||||||
?=,
|
|
||||||
?@,
|
|
||||||
?#
|
|
||||||
]
|
|
||||||
|
|
||||||
defp adjacents({y, x, len}, grid) do
|
|
||||||
[
|
|
||||||
{y, x - 1},
|
|
||||||
{y, x + len}
|
|
||||||
| for(y <- [y - 1, y + 1], x <- (x - 1)..(x + len), do: {y, x})
|
|
||||||
]
|
|
||||||
|> Enum.filter(fn {y, x} ->
|
|
||||||
0 <= y and y < length(grid) and 0 <= x and x < length(Enum.at(grid, y))
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp adjacents({y, x}, grid), do: adjacents({y, x, 1}, grid)
|
|
||||||
|
|
||||||
defp get({y, x}, grid) do
|
|
||||||
grid |> Enum.at(y) |> Enum.at(x)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get({y, x, len}, grid) do
|
|
||||||
x..(x + len - 1) |> Enum.map(&get({y, &1}, grid))
|
|
||||||
end
|
|
||||||
|
|
||||||
defp contains({y, x}, numbers) do
|
|
||||||
numbers
|
|
||||||
|> Enum.filter(fn {ny, nx, nlen} -> ny == y and nx <= x and x < nx + nlen end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp number(num, grid) do
|
|
||||||
num
|
|
||||||
|> get(grid)
|
|
||||||
|> Enum.map(&(&1 - ?0))
|
|
||||||
|> Integer.undigits()
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
grid =
|
|
||||||
input
|
|
||||||
|> String.split("\n")
|
|
||||||
|> Enum.map(&String.to_charlist/1)
|
|
||||||
|
|
||||||
{
|
|
||||||
grid,
|
|
||||||
grid
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.flat_map(fn {row, y} ->
|
|
||||||
row
|
|
||||||
|> runs(&(?0 <= &1 && &1 <= ?9))
|
|
||||||
|> Enum.map(fn {x, len} -> {y, x, len} end)
|
|
||||||
end)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1({grid, numbers}) do
|
|
||||||
numbers
|
|
||||||
|> Enum.map(id &&& adjacents(grid))
|
|
||||||
|> Enum.filter(
|
|
||||||
pipe(
|
|
||||||
elem(1)
|
|
||||||
|> Enum.any?(&(get(&1, grid) in @symbols))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|> Enum.map(
|
|
||||||
pipe(
|
|
||||||
elem(0)
|
|
||||||
|> number(grid)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2({grid, numbers}) do
|
|
||||||
grid
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.flat_map(fn {row, y} ->
|
|
||||||
row
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.filter(&(elem(&1, 0) == ?*))
|
|
||||||
|> Enum.map(&{y, elem(&1, 1)})
|
|
||||||
|> Enum.map(id &&& adjacents(grid))
|
|
||||||
|> Enum.map(pipe(
|
|
||||||
elem(1)
|
|
||||||
|> Enum.flat_map(pipe(contains(numbers)))
|
|
||||||
|> Enum.uniq()
|
|
||||||
))
|
|
||||||
|> Enum.filter(pipe(
|
|
||||||
length()
|
|
||||||
|> then(&(&1 == 2)))
|
|
||||||
)
|
|
||||||
|> Enum.map(pipe(
|
|
||||||
Enum.map(pipe(number(grid))) |> Enum.product
|
|
||||||
))
|
|
||||||
end)
|
|
||||||
|> Enum.sum
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-39
@@ -1,39 +0,0 @@
|
|||||||
defmodule Aoc2023.Day4 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
defp numbers(values) do
|
|
||||||
values |> String.split() |> Enum.map(&String.to_integer/1) |> MapSet.new()
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
input
|
|
||||||
|> lines
|
|
||||||
|> Enum.map(
|
|
||||||
&Regex.run(~r/Card\s+(?<id>\d+): (?<winning>(\s*\d+)+) \| (?<values>(\s*\d+)+)/, &1,
|
|
||||||
capture: ["id", "winning", "values"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|> Enum.map(fn [id, winning, values] ->
|
|
||||||
{String.to_integer(id),
|
|
||||||
MapSet.intersection(numbers(winning), numbers(values)) |> MapSet.size()}
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1(input) do
|
|
||||||
for {_, count} <- input,
|
|
||||||
count > 0 do
|
|
||||||
2 ** (count - 1)
|
|
||||||
end
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
for {id, count} <- input,
|
|
||||||
id_ <- (id + 1)..(id + count)//1,
|
|
||||||
reduce: input |> Enum.map(elem(0) &&& const(1)) |> Enum.into(%{}) do
|
|
||||||
acc -> Map.update!(acc, id_, &(&1 + Map.get(acc, id)))
|
|
||||||
end
|
|
||||||
|> Enum.map(pipe(elem(1)))
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-84
@@ -1,84 +0,0 @@
|
|||||||
defmodule Aoc2023.Day5 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
defp numbers(str), do: str |> String.split() |> Enum.map(&String.to_integer/1)
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
[seeds | maps] =
|
|
||||||
input
|
|
||||||
|> String.split("\n\n")
|
|
||||||
|
|
||||||
{
|
|
||||||
seeds |> String.split(": ") |> Enum.at(1) |> numbers,
|
|
||||||
maps
|
|
||||||
|> Enum.map(pipe(
|
|
||||||
String.split("\n")
|
|
||||||
|> tail
|
|
||||||
|> Enum.map(pipe(
|
|
||||||
numbers
|
|
||||||
|> List.to_tuple()
|
|
||||||
|> then(fn {dst, src, len} -> {src .. (src + len - 1), dst - src} end)
|
|
||||||
))
|
|
||||||
))
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp split_range_on(r1, r2) do
|
|
||||||
cond do
|
|
||||||
Range.disjoint?(r1, r2) -> {[r1], []}
|
|
||||||
r1.first < r2.first && r1.last < r2.last ->
|
|
||||||
{a, b} = Range.split(r1, r2.first - r1.first)
|
|
||||||
{[a], [b]}
|
|
||||||
r1.first > r2.first && r1.last > r2.last ->
|
|
||||||
{a, b} = Range.split(r1, r1.first - r2.first)
|
|
||||||
{[b], [a]}
|
|
||||||
r1.first >= r2.first && r1.last <= r2.last ->
|
|
||||||
{[], [r1]}
|
|
||||||
r1.first <= r2.first && r1.last >= r2.last ->
|
|
||||||
{pre, rest} = Range.split(r1, r2.first - r1.first)
|
|
||||||
{mid, last} = Range.split(rest, r2.last - rest.first)
|
|
||||||
{[pre, last], [mid]}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp map(loc, map) do
|
|
||||||
{unmapped, mapped} = for {src, offset} <- map,
|
|
||||||
reduce: {[loc], []} do
|
|
||||||
{unmapped, mapped} ->
|
|
||||||
for range <- unmapped,
|
|
||||||
reduce: {[], mapped} do
|
|
||||||
{unmapped_, mapped_} ->
|
|
||||||
{unmapped, mapped} = split_range_on(range, src)
|
|
||||||
{
|
|
||||||
unmapped_ ++ unmapped,
|
|
||||||
mapped_ ++ Enum.map(mapped, &(Range.shift(&1, offset)))
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
unmapped ++ mapped
|
|
||||||
end
|
|
||||||
|
|
||||||
defp run(seeds, maps) do
|
|
||||||
for seed <- seeds do
|
|
||||||
for map <- maps, reduce: [seed] do
|
|
||||||
loc ->
|
|
||||||
loc
|
|
||||||
|> Enum.flat_map(pipe(map(map)))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|> Enum.flat_map(&id/1)
|
|
||||||
|> Enum.min_by(&(&1.first))
|
|
||||||
|> then(&(&1.first))
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1({seeds, maps}) do
|
|
||||||
run(seeds |> Enum.map(&(&1..&1)), maps)
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2({seeds, maps}) do
|
|
||||||
run(
|
|
||||||
seeds |> Enum.chunk_every(2) |> Enum.map(fn [s, len] -> s..(s + len - 1) end),
|
|
||||||
maps
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-37
@@ -1,37 +0,0 @@
|
|||||||
defmodule Aoc2023.Day6 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
input
|
|
||||||
|> lines
|
|
||||||
|> Enum.map(pipe(
|
|
||||||
String.split(":")
|
|
||||||
|> Enum.at(1)
|
|
||||||
))
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1(input) do
|
|
||||||
input
|
|
||||||
|> Enum.map(pipe(
|
|
||||||
String.split()
|
|
||||||
|> Enum.map(&String.to_integer/1)
|
|
||||||
))
|
|
||||||
|> Enum.zip()
|
|
||||||
|> Enum.map(fn {time, dist} ->
|
|
||||||
1..time
|
|
||||||
|> Enum.map(&(&1 * (time - &1)))
|
|
||||||
|> Enum.filter(&(&1 > dist))
|
|
||||||
|> length
|
|
||||||
end)
|
|
||||||
|> Enum.product()
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
[time, dist] = input
|
|
||||||
|> Enum.map(pipe(String.replace(~r(\s+), "") |> String.to_integer()))
|
|
||||||
1..(time)
|
|
||||||
|> Stream.map(&(&1 * (time - &1)))
|
|
||||||
|> Stream.filter(&(&1 > dist))
|
|
||||||
|> Enum.count
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-66
@@ -1,66 +0,0 @@
|
|||||||
defmodule Aoc2023.Day7 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
def hand_type(values) do
|
|
||||||
values
|
|
||||||
|> Enum.frequencies()
|
|
||||||
|> then(fn freq ->
|
|
||||||
{jokers, freq_} = freq |> Map.pop(0, 0)
|
|
||||||
common = freq_ |> Enum.max_by(pipe(elem(1)), fn -> {1, nil} end) |> elem(0)
|
|
||||||
freq_ |> Map.update(common, jokers, &(&1 + jokers))
|
|
||||||
end)
|
|
||||||
|> Enum.map(pipe(elem(1)))
|
|
||||||
|> Enum.sort(:desc)
|
|
||||||
|> case do
|
|
||||||
[5] -> 6
|
|
||||||
[4, 1] -> 5
|
|
||||||
[3, 2] -> 4
|
|
||||||
[3, 1, 1] -> 3
|
|
||||||
[2, 2, 1] -> 2
|
|
||||||
[2, 1, 1, 1] -> 1
|
|
||||||
[1, 1, 1, 1, 1] -> 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
fn rankings ->
|
|
||||||
input
|
|
||||||
|> lines
|
|
||||||
|> Enum.map(&String.split/1)
|
|
||||||
|> Enum.map(fn [hand, bid] ->
|
|
||||||
{
|
|
||||||
hand |> String.to_charlist() |> Enum.map(&Map.get(rankings, &1)),
|
|
||||||
bid |> String.to_integer()
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
|> Enum.sort_by(elem(0) |> hand_type &&& elem(0), :asc)
|
|
||||||
|> Enum.with_index(1)
|
|
||||||
|> Enum.map(fn {{_, bid}, index} -> bid * index end)
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@ranking [
|
|
||||||
?2,
|
|
||||||
?3,
|
|
||||||
?4,
|
|
||||||
?5,
|
|
||||||
?6,
|
|
||||||
?7,
|
|
||||||
?8,
|
|
||||||
?9,
|
|
||||||
?T,
|
|
||||||
?J,
|
|
||||||
?Q,
|
|
||||||
?K,
|
|
||||||
?A,
|
|
||||||
] |> Enum.with_index(1) |> Map.new
|
|
||||||
|
|
||||||
def part1(input) do
|
|
||||||
input.(@ranking)
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
input.(@ranking |> Map.put(?J, 0))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-39
@@ -1,39 +0,0 @@
|
|||||||
defmodule Aoc2023.Day8 do
|
|
||||||
require Integer
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
input
|
|
||||||
|> String.split("\n\n")
|
|
||||||
|> then(fn [directions, map] ->
|
|
||||||
{
|
|
||||||
directions |> String.to_charlist() |> Enum.map(&%{?L => 0, ?R => 1}[&1]),
|
|
||||||
map
|
|
||||||
|> lines
|
|
||||||
|> Enum.map(&Regex.run(~r/(\w+) = \((\w+), (\w+)\)/, &1, capture: :all_but_first))
|
|
||||||
|> Enum.map(fn [src, dst1, dst2] -> {src, {dst1, dst2}} end)
|
|
||||||
|> Enum.into(%{})
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp run({directions, map}, node, filter) do
|
|
||||||
directions
|
|
||||||
|> Stream.cycle()
|
|
||||||
|> Stream.scan(node, fn dir, pos -> map[pos] |> elem(dir) end)
|
|
||||||
|> Enum.find_index(filter)
|
|
||||||
|> Kernel.+(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1({directions, map}) do
|
|
||||||
if map["AAA"], do: run({directions, map}, "AAA", &(&1 == "ZZZ"))
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2({directions, map}) do
|
|
||||||
map
|
|
||||||
|> Enum.map(pipe(elem(0)))
|
|
||||||
|> Enum.filter(pipe(String.ends_with?("A")))
|
|
||||||
|> Enum.map(&run({directions, map}, &1, pipe(String.ends_with?("Z"))))
|
|
||||||
|> lcm
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
defmodule Aoc2023.Day9 do
|
|
||||||
use Aoc2023
|
|
||||||
|
|
||||||
defp prediction(lst) do
|
|
||||||
case lst |> Enum.uniq() do
|
|
||||||
[val] -> val
|
|
||||||
_ -> List.last(lst) + prediction(Enum.zip_with(lst, Enum.drop(lst, 1), &(&2 - &1)))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse(input) do
|
|
||||||
input
|
|
||||||
|> lines
|
|
||||||
|> Enum.map(pipe(String.split() |> Enum.map(&String.to_integer/1)))
|
|
||||||
end
|
|
||||||
|
|
||||||
def part1(input) do
|
|
||||||
input
|
|
||||||
|> Enum.map(&prediction/1)
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
|
|
||||||
def part2(input) do
|
|
||||||
input
|
|
||||||
|> Enum.map(pipe(Enum.reverse() |> prediction))
|
|
||||||
|> Enum.sum()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
+26
-130
@@ -1,45 +1,20 @@
|
|||||||
defmodule Mix.Tasks.Aoc do
|
defmodule Mix.Tasks.Aoc do
|
||||||
use Mix.Task
|
use Mix.Task
|
||||||
import Aoc2023.Common
|
|
||||||
|
|
||||||
defp module(1), do: Aoc2023.Day1
|
defp module(1), do: Aoc2023.Day1
|
||||||
defp module(2), do: Aoc2023.Day2
|
|
||||||
defp module(3), do: Aoc2023.Day3
|
|
||||||
defp module(4), do: Aoc2023.Day4
|
|
||||||
defp module(5), do: Aoc2023.Day5
|
|
||||||
defp module(6), do: Aoc2023.Day6
|
|
||||||
defp module(7), do: Aoc2023.Day7
|
|
||||||
defp module(8), do: Aoc2023.Day8
|
|
||||||
defp module(9), do: Aoc2023.Day9
|
|
||||||
defp module(10), do: Aoc2023.Day10
|
|
||||||
defp module(11), do: Aoc2023.Day11
|
|
||||||
defp module(12), do: Aoc2023.Day12
|
|
||||||
defp module(13), do: Aoc2023.Day13
|
|
||||||
defp module(14), do: Aoc2023.Day14
|
|
||||||
defp module(15), do: Aoc2023.Day15
|
|
||||||
defp module(16), do: Aoc2023.Day16
|
|
||||||
defp module(17), do: Aoc2023.Day17
|
|
||||||
defp module(18), do: Aoc2023.Day18
|
|
||||||
# [MODULE INSERTION POINT]
|
# [MODULE INSERTION POINT]
|
||||||
|
|
||||||
defp base_dir(), do: System.get_env("AOC_BASE")
|
defp base_dir(), do: System.get_env("AOC_BASE")
|
||||||
|
|
||||||
defp tests(day) do
|
defp tests(day) do
|
||||||
case File.ls(tests_dir(day)) do
|
File.ls!(tests_dir(day)) |> Enum.filter(&(not String.contains?(&1, ".")))
|
||||||
{:ok, paths} ->
|
|
||||||
paths |> Enum.filter(&(not String.contains?(&1, "."))) |> Enum.sort()
|
|
||||||
|
|
||||||
{:error, e} ->
|
|
||||||
dbg(e)
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp read(path) do
|
defp read(path) do
|
||||||
f = File.open!(path, [:utf8])
|
f = File.open!(path, [:utf8])
|
||||||
contents = IO.read(f, :eof)
|
contents = IO.read(f, :eof)
|
||||||
:ok = File.close(f)
|
:ok = File.close(f)
|
||||||
String.trim(contents)
|
contents
|
||||||
end
|
end
|
||||||
|
|
||||||
defp test(day, test) do
|
defp test(day, test) do
|
||||||
@@ -80,15 +55,14 @@ defmodule Mix.Tasks.Aoc do
|
|||||||
create_file("#{base_dir()}/lib/day#{day}.ex", """
|
create_file("#{base_dir()}/lib/day#{day}.ex", """
|
||||||
defmodule Aoc2023.Day#{day} do
|
defmodule Aoc2023.Day#{day} do
|
||||||
use Aoc2023
|
use Aoc2023
|
||||||
|
|
||||||
def parse(input) do
|
def parse(input) do
|
||||||
input
|
input
|
||||||
end
|
end
|
||||||
|
def part1(input) do
|
||||||
def part1(_input) do
|
input
|
||||||
end
|
end
|
||||||
|
def part2(input) do
|
||||||
def part2(_input) do
|
input
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
""")
|
""")
|
||||||
@@ -108,44 +82,14 @@ defmodule Mix.Tasks.Aoc do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp run(day, ["test", "new"]) do
|
defp run(day, ["test", "new"]) do
|
||||||
last = tests(day) |> Enum.map(&String.to_integer(&1)) |> Enum.max(&>=/2, fn -> 0 end)
|
last = tests(day) |> Enum.map(&String.to_integer(&1)) |> Enum.max(empty_fallback: fn -> 1 end)
|
||||||
create_file("#{tests_dir(day)}#{last + 1}", IO.read(:stdio, :eof))
|
create_file("#{tests_dir(day)}#{last + 1}", IO.read(:stdio, :eof))
|
||||||
end
|
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
|
defp run(day, ["test", "expected", test, part]) do
|
||||||
create_file("#{tests_dir(day)}#{test}.#{part}", IO.read(:stdio, :eof))
|
create_file("#{tests_dir(day)}#{test}.#{part}", IO.read(:stdio, :eof))
|
||||||
end
|
end
|
||||||
|
|
||||||
defp run(day, ["test", "watch"]) do
|
|
||||||
{:ok, pid} = Mix.Tasks.Aoc.Watcher.start_link({[dirs: ["lib/", "tests/day#{day}/"]], self()})
|
|
||||||
Process.monitor(pid)
|
|
||||||
|
|
||||||
loop = fn loop ->
|
|
||||||
IO.puts(IO.ANSI.clear() <> IO.ANSI.cursor(0, 0))
|
|
||||||
IO.puts("At #{DateTime.utc_now(:second)}:")
|
|
||||||
System.shell("mix compile")
|
|
||||||
:code.purge(module(day))
|
|
||||||
:code.purge(Aoc2023.Common)
|
|
||||||
:code.load_file(module(day))
|
|
||||||
:code.load_file(Aoc2023.Common)
|
|
||||||
|
|
||||||
spawn(fn ->
|
|
||||||
run(day, ["test"])
|
|
||||||
end)
|
|
||||||
|
|
||||||
receive do
|
|
||||||
:update -> loop.(loop)
|
|
||||||
{:DOWN, _, :process, ^pid, _} -> nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
loop.(loop)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp run(day, ["test"]) do
|
defp run(day, ["test"]) do
|
||||||
mod = module(day)
|
mod = module(day)
|
||||||
tests = tests(day)
|
tests = tests(day)
|
||||||
@@ -154,27 +98,29 @@ defmodule Mix.Tasks.Aoc do
|
|||||||
|> Enum.map(&test(day, &1))
|
|> Enum.map(&test(day, &1))
|
||||||
|> Enum.map(fn {test, input, p1e, p2e} ->
|
|> Enum.map(fn {test, input, p1e, p2e} ->
|
||||||
parsed = mod.parse(input)
|
parsed = mod.parse(input)
|
||||||
|
p1 = mod.part1(parsed)
|
||||||
|
|
||||||
result = fn part, got, expected ->
|
if p1e do
|
||||||
cond do
|
if to_string(p1) != p1e do
|
||||||
stringify(got) == expected ->
|
IO.puts("Failed at #{test}.1: expected #{p1e}, got:")
|
||||||
IO.puts(IO.ANSI.format([:green, "Test #{test}.#{part} succeeded (#{expected})"]))
|
dbg(p1)
|
||||||
|
|
||||||
expected ->
|
|
||||||
IO.puts(
|
|
||||||
IO.ANSI.format([
|
|
||||||
:red,
|
|
||||||
"Test #{test}.#{part} failed: expected #{expected}, got #{stringify(got)}"
|
|
||||||
])
|
|
||||||
)
|
|
||||||
|
|
||||||
true ->
|
|
||||||
IO.puts("Test #{test}.#{part}: #{stringify(got)}")
|
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
IO.puts("Test #{test}.1")
|
||||||
|
dbg(p1)
|
||||||
end
|
end
|
||||||
|
|
||||||
result.(1, mod.part1(parsed), p1e)
|
p2 = mod.part2(parsed)
|
||||||
result.(2, mod.part2(parsed), p2e)
|
|
||||||
|
if p2e do
|
||||||
|
if to_string(p2) != p2e do
|
||||||
|
IO.puts("Failed at #{test}.2: expected #{p2e}, got:")
|
||||||
|
dbg(p2)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
IO.puts("Test #{test}.2")
|
||||||
|
dbg(p2)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -183,30 +129,6 @@ defmodule Mix.Tasks.Aoc do
|
|||||||
run_file(day, "#{base_dir()}/inputs/day#{day}")
|
run_file(day, "#{base_dir()}/inputs/day#{day}")
|
||||||
end
|
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",
|
|
||||||
"level=#{part}&answer=#{stringify(val)}",
|
|
||||||
"user-agent": "aoc-ex by ben@soroos.net",
|
|
||||||
cookie: "session=#{System.get_env("AOC_SESSION")}",
|
|
||||||
"content-type": "application/x-www-form-urlencoded"
|
|
||||||
).body
|
|
||||||
Regex.named_captures(~r[<main>(?<main>.*)</main>]is, resp)["main"] |> IO.puts
|
|
||||||
end
|
|
||||||
|
|
||||||
defp run(day, ["run", "-"]) do
|
defp run(day, ["run", "-"]) do
|
||||||
run_file(day)
|
run_file(day)
|
||||||
end
|
end
|
||||||
@@ -230,30 +152,4 @@ defmodule Mix.Tasks.Aoc do
|
|||||||
defp run_file(day, file \\ nil) do
|
defp run_file(day, file \\ nil) do
|
||||||
module(day).main(if file, do: read(file), else: IO.read(:stdio, :eof))
|
module(day).main(if file, do: read(file), else: IO.read(:stdio, :eof))
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule Watcher do
|
|
||||||
use GenServer
|
|
||||||
|
|
||||||
def start_link(args) do
|
|
||||||
GenServer.start_link(__MODULE__, args)
|
|
||||||
end
|
|
||||||
|
|
||||||
def init({args, callback}) do
|
|
||||||
{:ok, watcher_pid} = FileSystem.start_link(args)
|
|
||||||
FileSystem.subscribe(watcher_pid)
|
|
||||||
{:ok, %{watcher_pid: watcher_pid, callback: callback}}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_info(
|
|
||||||
{:file_event, watcher_pid, {_path, _events}},
|
|
||||||
%{watcher_pid: watcher_pid, callback: callback} = state
|
|
||||||
) do
|
|
||||||
send(callback, :update)
|
|
||||||
{:noreply, state}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_info({:file_event, _watcher_pid, :stop}, state) do
|
|
||||||
{:noreply, state}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -19,8 +19,7 @@ defmodule Aoc2023.MixProject do
|
|||||||
|
|
||||||
defp deps do
|
defp deps do
|
||||||
[
|
[
|
||||||
httpoison: "~> 2.0",
|
{:httpoison, "~> 2.0"}
|
||||||
file_system: "~> 1.0"
|
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
%{
|
%{
|
||||||
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
|
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
|
||||||
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
|
|
||||||
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
|
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
|
||||||
"httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"},
|
"httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"},
|
||||||
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||||
|
|||||||
@@ -5,11 +5,10 @@
|
|||||||
elixir,
|
elixir,
|
||||||
elixir-ls,
|
elixir-ls,
|
||||||
inotify-tools,
|
inotify-tools,
|
||||||
entr,
|
|
||||||
}:
|
}:
|
||||||
mkShell {
|
mkShell {
|
||||||
packages =
|
packages =
|
||||||
[elixir elixir-ls entr]
|
[elixir elixir-ls]
|
||||||
++ lib.lists.optional (pkgs.system == "x86_64-linux") inotify-tools
|
++ lib.lists.optional (pkgs.system == "x86_64-linux") inotify-tools
|
||||||
++ lib.lists.optionals (pkgs.system == "aarch64-darwin") (with pkgs.darwin.apple_sdk.frameworks; [
|
++ lib.lists.optionals (pkgs.system == "aarch64-darwin") (with pkgs.darwin.apple_sdk.frameworks; [
|
||||||
CoreFoundation
|
CoreFoundation
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
1abc2
|
|
||||||
pqr3stu8vwx
|
|
||||||
a1b2c3d4e5f
|
|
||||||
treb7uchet
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
142
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
142
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
two1nine
|
|
||||||
eightwothree
|
|
||||||
abcone2threexyz
|
|
||||||
xtwone3four
|
|
||||||
4nineeightseven2
|
|
||||||
zoneight234
|
|
||||||
7pqrstsixteen
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
209
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
281
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
-L|F7
|
|
||||||
7S-7|
|
|
||||||
L|7||
|
|
||||||
-L-J|
|
|
||||||
L|-JF
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
4
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
..F7.
|
|
||||||
.FJ|.
|
|
||||||
SJ.L7
|
|
||||||
|F--J
|
|
||||||
LJ...
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
8
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
...........
|
|
||||||
.S-------7.
|
|
||||||
.|F-----7|.
|
|
||||||
.||.....||.
|
|
||||||
.||.....||.
|
|
||||||
.|L-7.F-J|.
|
|
||||||
.|..|.|..|.
|
|
||||||
.L--J.L--J.
|
|
||||||
...........
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
4
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
.F----7F7F7F7F-7....
|
|
||||||
.|F--7||||||||FJ....
|
|
||||||
.||.FJ||||||||L7....
|
|
||||||
FJL7L7LJLJ||LJ.L-7..
|
|
||||||
L--J.L7...LJS7F-7L7.
|
|
||||||
....F-J..F7FJ|L7L7L7
|
|
||||||
....L7.F7||L7|.L7L7|
|
|
||||||
.....|FJLJ|FJ|F7|.LJ
|
|
||||||
....FJL-7.||.||||...
|
|
||||||
....L---J.LJ.LJLJ...
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
8
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
FF7FSF7F7F7F7F7F---7
|
|
||||||
L|LJ||||||||||||F--J
|
|
||||||
FL-7LJLJ||||||LJL-77
|
|
||||||
F--JF--7||LJLJ7F7FJ-
|
|
||||||
L---JF-JLJ.||-FJLJJ7
|
|
||||||
|F|F-JF---7F7-L7L|7|
|
|
||||||
|FFJF7L7F-JF7|JL---7
|
|
||||||
7-L-JL7||F7|L7F-7F7|
|
|
||||||
L.L7LFJ|||||FJL7||LJ
|
|
||||||
L7JLJL-JLJLJL--JLJ.L
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
10
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
...#......
|
|
||||||
.......#..
|
|
||||||
#.........
|
|
||||||
..........
|
|
||||||
......#...
|
|
||||||
.#........
|
|
||||||
.........#
|
|
||||||
..........
|
|
||||||
.......#..
|
|
||||||
#...#.....
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
374
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
???.### 1,1,3
|
|
||||||
.??..??...?##. 1,1,3
|
|
||||||
?#?#?#?#?#?#?#? 1,3,1,6
|
|
||||||
????.#...#... 4,1,1
|
|
||||||
????.######..#####. 1,6,5
|
|
||||||
?###???????? 3,2,1
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
21
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
525152
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#.##..##.
|
|
||||||
..#.##.#.
|
|
||||||
##......#
|
|
||||||
##......#
|
|
||||||
..#.##.#.
|
|
||||||
..##..##.
|
|
||||||
#.#.##.#.
|
|
||||||
|
|
||||||
#...##..#
|
|
||||||
#....#..#
|
|
||||||
..##..###
|
|
||||||
#####.##.
|
|
||||||
#####.##.
|
|
||||||
..##..###
|
|
||||||
#....#..#
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
405
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
400
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
O....#....
|
|
||||||
O.OO#....#
|
|
||||||
.....##...
|
|
||||||
OO.#O....O
|
|
||||||
.O.....O#.
|
|
||||||
O.#..O.#.#
|
|
||||||
..O..#O..O
|
|
||||||
.......O..
|
|
||||||
#....###..
|
|
||||||
#OO..#....
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
136
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
64
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
1320
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
145
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
.|...\....
|
|
||||||
|.-.\.....
|
|
||||||
.....|-...
|
|
||||||
........|.
|
|
||||||
..........
|
|
||||||
.........\
|
|
||||||
..../.\\..
|
|
||||||
.-.-/..|..
|
|
||||||
.|....-|.\
|
|
||||||
..//.|....
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
46
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
51
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
2413432311323
|
|
||||||
3215453535623
|
|
||||||
3255245654254
|
|
||||||
3446585845452
|
|
||||||
4546657867536
|
|
||||||
1438598798454
|
|
||||||
4457876987766
|
|
||||||
3637877979653
|
|
||||||
4654967986887
|
|
||||||
4564679986453
|
|
||||||
1224686865563
|
|
||||||
2546548887735
|
|
||||||
4322674655533
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
102
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
94
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
111111111111
|
|
||||||
999999999991
|
|
||||||
999999999991
|
|
||||||
999999999991
|
|
||||||
999999999991
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
71
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
R 6 (#70c710)
|
|
||||||
D 5 (#0dc571)
|
|
||||||
L 2 (#5713f0)
|
|
||||||
D 2 (#d2c081)
|
|
||||||
R 2 (#59c680)
|
|
||||||
D 2 (#411b91)
|
|
||||||
L 5 (#8ceee2)
|
|
||||||
U 2 (#caa173)
|
|
||||||
L 1 (#1b58a2)
|
|
||||||
U 2 (#caa171)
|
|
||||||
R 2 (#7807d2)
|
|
||||||
U 3 (#a77fa3)
|
|
||||||
L 2 (#015232)
|
|
||||||
U 2 (#7a21e3)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
62
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
952408144115
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
|
|
||||||
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
|
|
||||||
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
|
|
||||||
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
|
|
||||||
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
8
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
2286
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
467..114..
|
|
||||||
...*......
|
|
||||||
..35..633.
|
|
||||||
......#...
|
|
||||||
617*......
|
|
||||||
.....+.58.
|
|
||||||
..592.....
|
|
||||||
......755.
|
|
||||||
...$.*....
|
|
||||||
.664.598..
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
4361
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
467835
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
|
|
||||||
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
|
|
||||||
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
|
|
||||||
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
|
|
||||||
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
|
|
||||||
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
13
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
30
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
seeds: 79 14 55 13
|
|
||||||
|
|
||||||
seed-to-soil map:
|
|
||||||
50 98 2
|
|
||||||
52 50 48
|
|
||||||
|
|
||||||
soil-to-fertilizer map:
|
|
||||||
0 15 37
|
|
||||||
37 52 2
|
|
||||||
39 0 15
|
|
||||||
|
|
||||||
fertilizer-to-water map:
|
|
||||||
49 53 8
|
|
||||||
0 11 42
|
|
||||||
42 0 7
|
|
||||||
57 7 4
|
|
||||||
|
|
||||||
water-to-light map:
|
|
||||||
88 18 7
|
|
||||||
18 25 70
|
|
||||||
|
|
||||||
light-to-temperature map:
|
|
||||||
45 77 23
|
|
||||||
81 45 19
|
|
||||||
68 64 13
|
|
||||||
|
|
||||||
temperature-to-humidity map:
|
|
||||||
0 69 1
|
|
||||||
1 0 69
|
|
||||||
|
|
||||||
humidity-to-location map:
|
|
||||||
60 56 37
|
|
||||||
56 93 4
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
35
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
46
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Time: 7 15 30
|
|
||||||
Distance: 9 40 200
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
288
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
32T3K 765
|
|
||||||
T55J5 684
|
|
||||||
KK677 28
|
|
||||||
KTJJT 220
|
|
||||||
QQQJA 483
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
6440
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
5905
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
RL
|
|
||||||
|
|
||||||
AAA = (BBB, CCC)
|
|
||||||
BBB = (DDD, EEE)
|
|
||||||
CCC = (ZZZ, GGG)
|
|
||||||
DDD = (DDD, DDD)
|
|
||||||
EEE = (EEE, EEE)
|
|
||||||
GGG = (GGG, GGG)
|
|
||||||
ZZZ = (ZZZ, ZZZ)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
2
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
LLR
|
|
||||||
|
|
||||||
AAA = (BBB, BBB)
|
|
||||||
BBB = (AAA, ZZZ)
|
|
||||||
ZZZ = (ZZZ, ZZZ)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
6
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
LR
|
|
||||||
|
|
||||||
11A = (11B, XXX)
|
|
||||||
11B = (XXX, 11Z)
|
|
||||||
11Z = (11B, XXX)
|
|
||||||
22A = (22B, XXX)
|
|
||||||
22B = (22C, 22C)
|
|
||||||
22C = (22Z, 22Z)
|
|
||||||
22Z = (22B, 22B)
|
|
||||||
XXX = (XXX, XXX)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
6
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
0 3 6 9 12 15
|
|
||||||
1 3 6 10 15 21
|
|
||||||
10 13 16 21 30 45
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
114
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
2
|
|
||||||
Reference in New Issue
Block a user