Skip to content

Commit 1f242ea

Browse files
author
Robb Kidd
committed
day 12, part 2 ... now with a cache
1 parent 9647e16 commit 1f242ea

File tree

1 file changed

+28
-23
lines changed

1 file changed

+28
-23
lines changed

2023/ruby/day12.rb

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class HotSprings
4444

4545
def initialize(input="")
4646
@input = input
47+
@scan_cache = Hash.new
4748
@rows =
4849
@input
4950
.split("\n")
@@ -84,50 +85,54 @@ def maybe_damaged?(spring)
8485

8586
# @example 1st row
8687
# new.scan("???.###", [1,1,3]) #=> 1
88+
# new("???.### 1,1,3").unfold.map{ new.scan(*_1)}.first #=> 1
8789
#
8890
# @example 2nd row
8991
# new.scan(".??..??...?##.", [1,1,3]) #=> 4
92+
# new(".??..??...?##. 1,1,3").unfold.map{ new.scan(*_1)}.first #=> 16384
9093
#
9194
# @example 3rd row
9295
# new.scan("?#?#?#?#?#?#?#?", [1,3,1,6]) #=> 1
96+
# new("?#?#?#?#?#?#?#? 1,3,1,6").unfold.map{ new.scan(*_1)}.first #=> 1
9397
#
9498
# @example 4th row
9599
# new.scan("????.#...#...", [4,1,1]) #=> 1
100+
# new("????.#...#... 4,1,1").unfold.map{ new.scan(*_1)}.first #=> 16
96101
#
97102
# @example 5th row
98103
# new.scan("????.######..#####.", [1,6,5]) #=> 4
104+
# new("????.######..#####. 1,6,5").unfold.map{ new.scan(*_1)}.first #=> 2500
99105
#
100106
# @example 6th row
101107
# new.scan("?###????????", [3,2,1]) #=> 10
108+
# new("?###???????? 3,2,1").unfold.map{ new.scan(*_1)}.first #=> 506250
102109
def scan(springs, counts, previous_maybe_damaged=false)
103-
# what's left shouldn't be damaged if the trusted counts say there are no more damaged springs
104-
return (springs.include?(DAMAGED) ? 0 : 1) if counts.empty?
110+
return @scan_cache.fetch([springs, counts, previous_maybe_damaged]) { |key|
111+
@scan_cache[key] =
112+
if counts.empty?
113+
# what's left shouldn't be damaged if the trusted counts say there are no more damaged springs
114+
springs.include?(DAMAGED) ? 0 : 1
105115

106-
# the trusted counts shouldn't say there are more damaged when we're out of springs to evaluate
107-
return (counts.reduce(&:+).positive? ? 0 : 1) if springs.empty?
116+
elsif springs.empty?
117+
# the trusted counts shouldn't say there are more damaged when we're out of springs to evaluate
118+
counts.reduce(&:+).positive? ? 0 : 1
108119

109-
# OK, we gotta compute stuff ...
120+
elsif counts[0] == 0
121+
maybe_working?(springs[0]) ? scan(springs[1..], counts[1..], false) : 0
110122

111-
current_spring, remaining_springs = springs[0], springs[1..]
112-
current_count, remaining_counts = counts[0], counts[1..]
113-
decremented_counts = ([current_count-1] + remaining_counts)
123+
elsif previous_maybe_damaged
124+
maybe_damaged?(springs[0]) ? scan(springs[1..], ([counts[0]-1] + counts[1..]), true) : 0
114125

115-
case
116-
when current_count == 0
117-
return maybe_working?(current_spring) ? scan(remaining_springs, remaining_counts, false) : 0
126+
elsif springs[0] == DAMAGED
127+
scan(springs[1..], ([counts[0]-1] + counts[1..]), true)
118128

119-
when previous_maybe_damaged
120-
return maybe_damaged?(current_spring) ? scan(remaining_springs, decremented_counts, true) : 0
129+
elsif springs[0] == WORKING
130+
scan(springs[1..], counts, false)
121131

122-
when current_spring == DAMAGED
123-
return scan(remaining_springs, decremented_counts, true)
124-
125-
when current_spring == WORKING
126-
return scan(remaining_springs, counts, false)
127-
128-
else
129-
return scan(remaining_springs, counts, false) + # run the scenarios where first spring is working
130-
scan(remaining_springs, decremented_counts, true) # and the scenarios where first is/might-be broken
131-
end
132+
else
133+
scan(springs[1..], counts, false) + # run the scenarios where first spring is working
134+
scan(springs[1..], ([counts[0]-1] + counts[1..]), true) # and the scenarios where first is/might-be broken
135+
end
136+
}
132137
end
133138
end

0 commit comments

Comments
 (0)