add day 9 and 11
This commit is contained in:
parent
71cca82ce0
commit
0e7d2d7c6d
7 changed files with 492 additions and 32 deletions
74
23/elixir/lib/days/day11.ex
Normal file
74
23/elixir/lib/days/day11.ex
Normal file
|
@ -0,0 +1,74 @@
|
|||
defmodule AOC.Day11 do
|
||||
use AOC.Day, day: 11
|
||||
|
||||
def parse_input(lines) do
|
||||
Enum.map(lines, &String.to_charlist/1)
|
||||
end
|
||||
|
||||
def part1(image), do: calculate_distance_sum(image, 2)
|
||||
|
||||
def part2(image), do: calculate_distance_sum(image, 1_000_000)
|
||||
|
||||
def calculate_distance_sum(image, scaler) do
|
||||
empty_space = find_empty_space(image)
|
||||
|
||||
find_galaxy_positions(image)
|
||||
|> expand_galaxy_positions(empty_space, scaler)
|
||||
|> calculate_shortest_paths()
|
||||
|> Enum.sum()
|
||||
end
|
||||
|
||||
def find_empty_space(image) do
|
||||
empty_rows = find_empty_rows(image)
|
||||
|
||||
empty_columns =
|
||||
image
|
||||
|> List.zip()
|
||||
|> Enum.map(&Tuple.to_list/1)
|
||||
|> find_empty_rows()
|
||||
|
||||
{empty_rows, empty_columns}
|
||||
end
|
||||
|
||||
def find_empty_rows(image) do
|
||||
image
|
||||
|> Enum.with_index()
|
||||
|> Enum.filter(fn {row, _} -> Enum.all?(row, &(&1 == ?.)) end)
|
||||
|> Enum.map(&elem(&1, 1))
|
||||
end
|
||||
|
||||
def find_galaxy_positions(image) do
|
||||
image
|
||||
|> Enum.map(fn row ->
|
||||
row
|
||||
|> Enum.with_index()
|
||||
|> Enum.filter(fn {space, _} -> space == ?# end)
|
||||
|> Enum.map(&elem(&1, 1))
|
||||
end)
|
||||
|> Enum.with_index()
|
||||
|> Enum.flat_map(fn {xs, y} ->
|
||||
Enum.map(xs, &{y, &1})
|
||||
end)
|
||||
end
|
||||
|
||||
def expand_galaxy_positions(galaxy_positions, {empty_rows, empty_columns}, scaler) do
|
||||
Enum.map(galaxy_positions, fn {y, x} ->
|
||||
shift_y = Enum.count(empty_rows, &(&1 < y))
|
||||
shift_x = Enum.count(empty_columns, &(&1 < x))
|
||||
|
||||
{y + shift_y * (scaler - 1), x + shift_x * (scaler - 1)}
|
||||
end)
|
||||
end
|
||||
|
||||
def calculate_shortest_paths(galaxy_positions) do
|
||||
for g1 <- galaxy_positions, g2 <- galaxy_positions do
|
||||
[g1, g2]
|
||||
end
|
||||
|> Enum.reject(fn [g1, g2] -> g1 == g2 end)
|
||||
|> Enum.map(&Enum.sort/1)
|
||||
|> Enum.uniq()
|
||||
|> Enum.map(fn [{y1, x1}, {y2, x2}] ->
|
||||
abs(y1 - y2) + abs(x1 - x2)
|
||||
end)
|
||||
end
|
||||
end
|
|
@ -1,7 +1,4 @@
|
|||
defmodule AOC.Day8 do
|
||||
# use AOC.Day, day: 8, input: "example1"
|
||||
# use AOC.Day, day: 8, input: "example2"
|
||||
# use AOC.Day, day: 8, input: "example3"
|
||||
use AOC.Day, day: 8
|
||||
|
||||
@start "AAA"
|
||||
|
@ -25,6 +22,20 @@ defmodule AOC.Day8 do
|
|||
{instructions, nodes}
|
||||
end
|
||||
|
||||
def part1({instructions, nodes}) do
|
||||
reach_end(instructions, nodes)
|
||||
end
|
||||
|
||||
def part2({instructions, nodes}) do
|
||||
IO.puts("Use LCM calculator for the following numbers :)")
|
||||
|
||||
Enum.filter(nodes, fn {k, _v} -> String.ends_with?(k, "A") end)
|
||||
|> Enum.map(fn {k, _v} -> find_cycle(instructions, nodes, k) end)
|
||||
|> Enum.map(&elem(&1, 0))
|
||||
|> Enum.map(&Integer.to_string/1)
|
||||
|> Enum.join(" ")
|
||||
end
|
||||
|
||||
def reach_end(instructions, nodes) do
|
||||
Enum.reduce_while(instructions, {@start, 0}, fn instruction, {current_node, step_count} ->
|
||||
if current_node == @stop do
|
||||
|
@ -43,10 +54,6 @@ defmodule AOC.Day8 do
|
|||
end)
|
||||
end
|
||||
|
||||
def part1({instructions, nodes}) do
|
||||
reach_end(instructions, nodes)
|
||||
end
|
||||
|
||||
def find_cycle(instructions, nodes, start) do
|
||||
Enum.reduce_while(instructions, {start, 0, nil}, fn instruction,
|
||||
{current_node, step_count, last_end_count} ->
|
||||
|
@ -68,29 +75,4 @@ defmodule AOC.Day8 do
|
|||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def brute_force_find_cycle(cycles) do
|
||||
Stream.repeatedly(fn -> nil end)
|
||||
|> Enum.reduce_while(cycles, fn _, cycles ->
|
||||
all_ended = cycles |> Enum.map(&elem(&1, 0)) |> Enum.uniq() |> length() == 1
|
||||
|
||||
if all_ended do
|
||||
{:halt, cycles |> hd() |> elem(0)}
|
||||
else
|
||||
[{count, cycle_count} | tl] = Enum.sort(cycles)
|
||||
IO.inspect(count)
|
||||
{:cont, [{count + cycle_count, cycle_count} | tl]}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def part2({instructions, nodes}) do
|
||||
IO.puts("Use LCM for the following numbers :)")
|
||||
|
||||
Enum.filter(nodes, fn {k, _v} -> String.ends_with?(k, "A") end)
|
||||
|> Enum.map(fn {k, _v} -> find_cycle(instructions, nodes, k) end)
|
||||
|> Enum.map(&elem(&1, 0))
|
||||
|> Enum.map(&Integer.to_string/1)
|
||||
|> Enum.join(" ")
|
||||
end
|
||||
end
|
||||
|
|
51
23/elixir/lib/days/day9.ex
Normal file
51
23/elixir/lib/days/day9.ex
Normal file
|
@ -0,0 +1,51 @@
|
|||
defmodule AOC.Day9 do
|
||||
use AOC.Day, day: 9
|
||||
|
||||
def parse_input(lines) do
|
||||
Enum.map(lines, fn line ->
|
||||
line
|
||||
|> String.split(" ")
|
||||
|> Enum.map(&String.to_integer/1)
|
||||
end)
|
||||
end
|
||||
|
||||
def part1(histories) do
|
||||
histories
|
||||
|> Enum.map(&predict_next_value/1)
|
||||
|> Enum.sum()
|
||||
end
|
||||
|
||||
def part2(histories) do
|
||||
Enum.map(histories, &predict_previous_value/1)
|
||||
|> Enum.sum()
|
||||
end
|
||||
|
||||
def predict_next_value(history) do
|
||||
history
|
||||
|> generate_differences()
|
||||
|> Enum.map(&List.last/1)
|
||||
|> Enum.sum()
|
||||
end
|
||||
|
||||
def predict_previous_value(history) do
|
||||
history
|
||||
|> generate_differences()
|
||||
|> Enum.map(&List.first/1)
|
||||
|> Enum.reduce(&Kernel.-/2)
|
||||
end
|
||||
|
||||
def generate_differences(history), do: generate_differences(history, [history])
|
||||
|
||||
def generate_differences(numbers, acc) do
|
||||
if Enum.all?(numbers, &(&1 == 0)) do
|
||||
acc
|
||||
else
|
||||
differences =
|
||||
numbers
|
||||
|> Enum.chunk_every(2, 1, :discard)
|
||||
|> Enum.map(fn [val1, val2] -> val2 - val1 end)
|
||||
|
||||
generate_differences(differences, [differences | acc])
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue