aoc/23/elixir/lib/days/day12.ex

103 lines
2.9 KiB
Elixir

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...