You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
advent-of-code/2023/ruby/day_12.rb

71 lines
2.3 KiB

input = ARGF.readlines(chomp: true).map {|row|
springs, groups = row.split(" ")
[springs, groups.scan(/\d+/).map(&:to_i)]
}
p input
# .map { [ _1.chars, _2 ] }
.map { [Array.new(5, _1).join(??).chars, _2 * 5] }
.map {|springs, groups|
arrangement_counts = Hash.new {|h,k|
count, springs, groups = k
first, *rest = springs
h[k] = case [count, first, groups]
in count, _, []
if count.nonzero?
0
elsif springs.include?(?#)
0
else
1
end
in count, _, groups if count > groups.fetch(0)
0 # early exit if the damaged group ever gets too large
in count, nil, groups # no more springs
if groups.size > 1
0
elsif count == groups.fetch(0)
1
else
0
end
in count, ?#, groups # continue a damaged group
h[[count + 1, rest, groups]]
in 0, ?., groups
h[[0, rest, groups]]
in count, ?., groups # finish a damaged group
if count == groups.fetch(0)
h[[0, rest, groups[1..]]]
else
0
end
in count, ??, g if count == g.fetch(0) # unknown spring, matched current group
h[[0, rest, g[1..]]]
in count, ??, g unless count.zero? # unknown spring, ongoing group
h[[count + 1, rest, g]]
in count, ??, g # unknown spring
[
h[[count, rest, g]], # undamaged
h[[count + 1, rest, g]], # damaged
].sum
else
fail "#{{first:, springs: springs.join, groups:}}"
end
}
arrangement_counts[[0, springs, groups]]
}.sum
# original part one
# p input.map {|springs, groups|
# unknowns = springs.count(??)
# (0...2**unknowns).map {|arrangement|
# arrangement = arrangement.to_s(2).rjust(unknowns, ?0).chars.map { _1 == ?0 ? ?. : ?# }
# candidate = springs.gsub(??) { arrangement.shift }
# candidate.chars
# .slice_when { _1 != _2 }
# .reject { _1[0] == ?. }
# .map(&:size) == groups
# }.count(&:itself)
# }.sum