Skip to content

Commit 25d4efa

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

File tree

1 file changed

+40
-30
lines changed

1 file changed

+40
-30
lines changed

2023/ruby/day12.rb

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
require_relative 'day'
2-
require_relative 'ugly_sweater'
32

43
class Day12 < Day # >
54

@@ -44,6 +43,7 @@ class HotSprings
4443

4544
def initialize(input="")
4645
@input = input
46+
@scan_cache = Hash.new
4747
@rows =
4848
@input
4949
.split("\n")
@@ -83,51 +83,61 @@ def maybe_damaged?(spring)
8383
end
8484

8585
# @example 1st row
86-
# new.scan("???.###", [1,1,3]) #=> 1
86+
# ♨️ = new("???.### 1,1,3")
87+
# ♨️.rows.map { ♨️.scan(*_1) }.first #=> 1
88+
# ♨️.unfold.map{ new.scan(*_1) }.first #=> 1
8789
#
8890
# @example 2nd row
89-
# new.scan(".??..??...?##.", [1,1,3]) #=> 4
91+
# ♨️ = new(".??..??...?##. 1,1,3")
92+
# ♨️.rows.map { ♨️.scan(*_1) }.first #=> 4
93+
# ♨️.unfold.map{ new.scan(*_1) }.first #=> 16384
9094
#
9195
# @example 3rd row
92-
# new.scan("?#?#?#?#?#?#?#?", [1,3,1,6]) #=> 1
96+
# ♨️ = new("?#?#?#?#?#?#?#? 1,3,1,6")
97+
# ♨️.rows.map { ♨️.scan(*_1) }.first #=> 1
98+
# ♨️.unfold.map{ new.scan(*_1) }.first #=> 1
9399
#
94100
# @example 4th row
95-
# new.scan("????.#...#...", [4,1,1]) #=> 1
101+
# ♨️ = new("????.#...#... 4,1,1")
102+
# ♨️.rows.map { ♨️.scan(*_1) }.first #=> 1
103+
# ♨️.unfold.map{ new.scan(*_1) }.first #=> 16
96104
#
97105
# @example 5th row
98-
# new.scan("????.######..#####.", [1,6,5]) #=> 4
106+
# ♨️ = new("????.######..#####. 1,6,5")
107+
# ♨️.rows.map { ♨️.scan(*_1) }.first #=> 4
108+
# ♨️.unfold.map{ new.scan(*_1) }.first #=> 2500
99109
#
100110
# @example 6th row
101-
# new.scan("?###????????", [3,2,1]) #=> 10
111+
# ♨️ = new("?###???????? 3,2,1")
112+
# ♨️.rows.map { ♨️.scan(*_1) }.first #=> 10
113+
# ♨️.unfold.map{ new.scan(*_1) }.first #=> 506250
102114
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?
115+
return @scan_cache.fetch([springs, counts, previous_maybe_damaged]) { |key|
116+
@scan_cache[key] =
117+
if counts.empty?
118+
# what's left shouldn't be damaged if the trusted counts say there are no more damaged springs
119+
springs.include?(DAMAGED) ? 0 : 1
105120

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?
121+
elsif springs.empty?
122+
# the trusted counts shouldn't say there are more damaged when we're out of springs to evaluate
123+
counts.reduce(&:+).positive? ? 0 : 1
108124

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

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)
128+
elsif previous_maybe_damaged
129+
maybe_damaged?(springs[0]) ? scan(springs[1..], ([counts[0]-1] + counts[1..]), true) : 0
114130

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

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

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
137+
else
138+
scan(springs[1..], counts, false) + # run the scenarios where first spring is working
139+
scan(springs[1..], ([counts[0]-1] + counts[1..]), true) # and the scenarios where first is/might-be broken
140+
end
141+
}
132142
end
133143
end

0 commit comments

Comments
 (0)