104 lines
2.9 KiB
Elixir
104 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...
|