@@ -19,8 +19,34 @@ def part1
19
19
end
20
20
21
21
# @example
22
- # day.part2 #=> 'how are you'
22
+ # day.part2 #=> 46
23
23
def part2
24
+ maps = parse
25
+
26
+ maps [ "seeds" ]
27
+ . each_slice ( 2 )
28
+ . map { |start , length |
29
+ min = Float ::INFINITY
30
+ i = 0
31
+ while i < length do
32
+ location , skip =
33
+ [ start + i ]
34
+ . map { maps [ "seed-to-soil" ] . convert_with_skip ( _1 ) } # no skip to start
35
+ . map { maps [ "soil-to-fertilizer" ] . convert_with_skip ( *_1 ) } # <- from here on _1
36
+ . map { maps [ "fertilizer-to-water" ] . convert_with_skip ( *_1 ) } # is [previous_conversion, skip]
37
+ . map { maps [ "water-to-light" ] . convert_with_skip ( *_1 ) }
38
+ . map { maps [ "light-to-temperature" ] . convert_with_skip ( *_1 ) }
39
+ . map { maps [ "temperature-to-humidity" ] . convert_with_skip ( *_1 ) }
40
+ . map { maps [ "humidity-to-location" ] . convert_with_skip ( *_1 ) }
41
+ . first
42
+
43
+ min = location if location < min
44
+ i = i + skip if 0 < skip
45
+ i = i + 1
46
+ end
47
+ min
48
+ }
49
+ . min
24
50
end
25
51
26
52
def parse
@@ -42,9 +68,7 @@ def parse
42
68
maps
43
69
end
44
70
45
- # @example
46
- # mapper = Day05::Mapper.new(["50 98 2", "52 50 48"])
47
- # mapper.convert(79) #=> 81
71
+
48
72
class Mapper
49
73
attr_reader :map_title , :maps
50
74
@@ -57,6 +81,9 @@ def initialize(map_title, maps)
57
81
}
58
82
end
59
83
84
+ # @example
85
+ # mapper = Day05::Mapper.new("test", ["50 98 2", "52 50 48"])
86
+ # mapper.convert(79) #=> 81
60
87
def convert ( input )
61
88
maps . each do |source_range , dest_start |
62
89
next unless source_range . cover? ( input )
@@ -65,6 +92,45 @@ def convert(input)
65
92
66
93
return input
67
94
end
95
+
96
+ # @example seed-to-soil
97
+ # maps = Day05.new(Day05::EXAMPLE_INPUT).parse
98
+ # maps["seed-to-soil"].convert_with_skip(82) #=> [84, 15]
99
+ # @example soil-to-fertilizer
100
+ # maps = Day05.new(Day05::EXAMPLE_INPUT).parse
101
+ # maps["soil-to-fertilizer"].convert_with_skip(84, 15) #=> [84, 15]
102
+ # @example fertilizer-to-water
103
+ # maps = Day05.new(Day05::EXAMPLE_INPUT).parse
104
+ # maps["fertilizer-to-water"].convert_with_skip(84, 15) #=> [84, 15]
105
+ # @example water-to-light
106
+ # maps = Day05.new(Day05::EXAMPLE_INPUT).parse
107
+ # maps["water-to-light"].convert_with_skip(84, 15) #=> [77, 10]
108
+ # @example light-to-temperature
109
+ # maps = Day05.new(Day05::EXAMPLE_INPUT).parse
110
+ # maps["light-to-temperature"].convert_with_skip(77, 10) #=> [45, 10]
111
+ # @example temperature-to-humidity
112
+ # maps = Day05.new(Day05::EXAMPLE_INPUT).parse
113
+ # maps["temperature-to-humidity"].convert_with_skip(45, 10) #=> [46, 10]
114
+ # @example humidity-to-location
115
+ # maps = Day05.new(Day05::EXAMPLE_INPUT).parse
116
+ # maps["humidity-to-location"].convert_with_skip(46, 10) #=> [46, 9]
117
+ #
118
+ # logic copied enthusiastically from Brandon Mitchell; I couldn't figure it out
119
+ def convert_with_skip ( input , skip = -1 )
120
+ maps . each do |source_range , dest_start |
121
+ if source_range . cover? ( input )
122
+ if skip && skip > source_range . size - ( input - source_range . min ) - 1
123
+ skip = source_range . size - ( input - source_range . min ) - 1
124
+ end
125
+ return [ dest_start + ( input - source_range . min ) , skip ]
126
+ end
127
+ if input < source_range . min && ( skip < 0 || skip > source_range . min - input -1 )
128
+ skip = source_range . min - input - 1
129
+ end
130
+ end
131
+
132
+ return [ input , skip ]
133
+ end
68
134
end
69
135
70
136
EXAMPLE_INPUT = <<~INPUT
0 commit comments