add day 12a and day 18a
This commit is contained in:
parent
092bb05312
commit
d20bb3f539
6 changed files with 1851 additions and 0 deletions
103
23/elixir/lib/days/day12.ex
Normal file
103
23/elixir/lib/days/day12.ex
Normal file
|
@ -0,0 +1,103 @@
|
|||
defmodule AOC.Day12 do
|
||||
use AOC.Day, day: 12, input: "example"
|
||||
# use AOC.Day, day: 12
|
||||
|
||||
def parse_input(lines) do
|
||||
Enum.map(lines, fn line ->
|
||||
[conditions, groups] = String.split(line, " ")
|
||||
conditions = String.to_charlist(conditions)
|
||||
|
||||
groups =
|
||||
groups
|
||||
|> String.split(",")
|
||||
|> Enum.map(&String.to_integer/1)
|
||||
|
||||
{conditions, groups}
|
||||
end)
|
||||
end
|
||||
|
||||
def possible_unknown_spring_conditions(unknown_spring_count) when unknown_spring_count == 0,
|
||||
do: [[]]
|
||||
|
||||
def possible_unknown_spring_conditions(unknown_spring_count) do
|
||||
next_list = possible_unknown_spring_conditions(unknown_spring_count - 1)
|
||||
Enum.map(next_list, &[true | &1]) ++ Enum.map(next_list, &[false | &1])
|
||||
end
|
||||
|
||||
def apply_spring_configuration([], []), do: []
|
||||
|
||||
def apply_spring_configuration([?. | conditions], spring_configuration) do
|
||||
[?. | apply_spring_configuration(conditions, spring_configuration)]
|
||||
end
|
||||
|
||||
def apply_spring_configuration([?# | conditions], spring_configuration) do
|
||||
[?# | apply_spring_configuration(conditions, spring_configuration)]
|
||||
end
|
||||
|
||||
def apply_spring_configuration([?? | conditions], [true | spring_configuration]) do
|
||||
[?. | apply_spring_configuration(conditions, spring_configuration)]
|
||||
end
|
||||
|
||||
def apply_spring_configuration([?? | conditions], [false | spring_configuration]) do
|
||||
[?# | apply_spring_configuration(conditions, spring_configuration)]
|
||||
end
|
||||
|
||||
def valid_spring_conditions?(conditions, []) do
|
||||
not Enum.member?(conditions, ?#)
|
||||
end
|
||||
|
||||
def valid_spring_conditions?([?. | conditions], groups) do
|
||||
valid_spring_conditions?(conditions, groups)
|
||||
end
|
||||
|
||||
def valid_spring_conditions?(conditions, [count | groups]) do
|
||||
{left, right} = Enum.split(conditions, count)
|
||||
|
||||
length(left) == count and Enum.all?(left, &(&1 == ?#)) and
|
||||
(length(right) == 0 or hd(right) == ?.) and valid_spring_conditions?(right, groups)
|
||||
end
|
||||
|
||||
def generate_arrangements(conditions, groups) do
|
||||
unknown_spring_count = Enum.count(conditions, &(&1 == ??))
|
||||
|
||||
possible_unknown_spring_conditions(unknown_spring_count)
|
||||
|> Stream.map(fn spring_configuration ->
|
||||
apply_spring_configuration(conditions, spring_configuration)
|
||||
end)
|
||||
|> Stream.filter(fn possible_conditions ->
|
||||
valid_spring_conditions?(possible_conditions, groups)
|
||||
end)
|
||||
|
||||
# |> Enum.to_list()
|
||||
end
|
||||
|
||||
def calculate_arrangement_counts(input, duplicates \\ 1) do
|
||||
input
|
||||
|> Enum.map(fn {conditions, groups} ->
|
||||
conditions =
|
||||
conditions
|
||||
|> List.duplicate(duplicates)
|
||||
|> Enum.intersperse(~c"?")
|
||||
|> List.flatten()
|
||||
|
||||
groups =
|
||||
groups
|
||||
|> List.duplicate(duplicates)
|
||||
|> List.flatten()
|
||||
|
||||
generate_arrangements(conditions, groups)
|
||||
end)
|
||||
|> Enum.map(&Enum.count/1)
|
||||
|> Enum.sum()
|
||||
end
|
||||
|
||||
def part1(input) do
|
||||
calculate_arrangement_counts(input)
|
||||
end
|
||||
|
||||
def part2(input) do
|
||||
calculate_arrangement_counts(input, 5)
|
||||
end
|
||||
end
|
||||
|
||||
# NOTE TO SELF: memoize the brute force...
|
110
23/elixir/lib/days/day18.ex
Normal file
110
23/elixir/lib/days/day18.ex
Normal file
|
@ -0,0 +1,110 @@
|
|||
defmodule AOC.Day18 do
|
||||
# use AOC.Day, day: 18, input: "example"
|
||||
use AOC.Day, day: 18
|
||||
|
||||
def parse_input(lines) do
|
||||
Enum.map(lines, fn line ->
|
||||
%{"direction" => direction, "length" => length, "color" => color} =
|
||||
Regex.named_captures(
|
||||
~r/^(?<direction>[UDLR]) (?<length>\d+) \(\#(?<color>[[:alnum:]]+)\)$/,
|
||||
line
|
||||
)
|
||||
|
||||
{String.to_atom(direction), String.to_integer(length), color}
|
||||
end)
|
||||
end
|
||||
|
||||
def dig_stretch({y, x}, direction, length) do
|
||||
Enum.map(1..length, fn n ->
|
||||
case direction do
|
||||
:U -> {y - n, x}
|
||||
:R -> {y, x + n}
|
||||
:D -> {y + n, x}
|
||||
:L -> {y, x - n}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def execute_dig_plan(dig_plan) do
|
||||
Enum.reduce(dig_plan, {%{{0, 0} => true}, {0, 0}}, fn {direction, length, _color},
|
||||
{terrain, position} ->
|
||||
stretch = dig_stretch(position, direction, length)
|
||||
|
||||
terrain =
|
||||
Enum.reduce(stretch, terrain, fn new_position, acc ->
|
||||
Map.put(acc, new_position, true)
|
||||
end)
|
||||
|
||||
new_position = stretch |> Enum.reverse() |> hd()
|
||||
|
||||
{terrain, new_position}
|
||||
end)
|
||||
end
|
||||
|
||||
def print_terrain(terrain) do
|
||||
max_y = terrain |> Enum.map(&elem(&1, 0)) |> Enum.map(&elem(&1, 0)) |> Enum.max()
|
||||
max_x = terrain |> Enum.map(&elem(&1, 0)) |> Enum.map(&elem(&1, 1)) |> Enum.max()
|
||||
min_y = terrain |> Enum.map(&elem(&1, 0)) |> Enum.map(&elem(&1, 0)) |> Enum.min()
|
||||
min_x = terrain |> Enum.map(&elem(&1, 0)) |> Enum.map(&elem(&1, 1)) |> Enum.min()
|
||||
|
||||
Enum.each(min_y..max_y, fn y ->
|
||||
Enum.map(min_x..max_x, fn x ->
|
||||
case Map.fetch(terrain, {y, x}) do
|
||||
:error -> "."
|
||||
_ -> "#"
|
||||
end
|
||||
end)
|
||||
|> Enum.join()
|
||||
|> IO.puts()
|
||||
end)
|
||||
end
|
||||
|
||||
def find_interior_space(terrain) do
|
||||
max_x = terrain |> Enum.map(&elem(&1, 0)) |> Enum.map(&elem(&1, 1)) |> Enum.max()
|
||||
min_x = terrain |> Enum.map(&elem(&1, 0)) |> Enum.map(&elem(&1, 1)) |> Enum.min()
|
||||
|
||||
edge_x =
|
||||
Enum.find(min_x..max_x, fn x ->
|
||||
case Map.fetch(terrain, {2, x}) do
|
||||
:error -> false
|
||||
_ -> true
|
||||
end
|
||||
end)
|
||||
|
||||
edge_x + 1
|
||||
end
|
||||
|
||||
def flood_fill_terrain(terrain) do
|
||||
interior_x = find_interior_space(terrain)
|
||||
|
||||
flood_fill_terrain(terrain, {1, interior_x})
|
||||
end
|
||||
|
||||
def flood_fill_terrain(terrain, {y, x}) do
|
||||
[{y - 1, x}, {y, x + 1}, {y + 1, x}, {y, x - 1}]
|
||||
|> Enum.reduce(terrain, fn next_position, acc ->
|
||||
case Map.fetch(acc, next_position) do
|
||||
:error ->
|
||||
acc
|
||||
|> Map.put(next_position, true)
|
||||
|> flood_fill_terrain(next_position)
|
||||
|
||||
_ ->
|
||||
acc
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def part1(dig_plan) do
|
||||
execute_dig_plan(dig_plan)
|
||||
|> elem(0)
|
||||
# |> tap(&print_terrain/1)
|
||||
|> flood_fill_terrain()
|
||||
# |> tap(&print_terrain/1)
|
||||
|> Enum.count()
|
||||
end
|
||||
|
||||
def part2(_input) do
|
||||
"TODO"
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue