Day 5
This commit is contained in:
24
2023/day5/p1.rb
Normal file
24
2023/day5/p1.rb
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
f = File.open('./2023/day5/data')
|
||||||
|
seeds = f.first.strip.split(': ')[1].split(' ').map(&:to_i)
|
||||||
|
updated_seeds = seeds.clone
|
||||||
|
|
||||||
|
f.each_line do |line|
|
||||||
|
seeds = updated_seeds if line.include? 'map'
|
||||||
|
next if line.include?('seed') || line.strip.empty? || line.include?('map')
|
||||||
|
|
||||||
|
source_start = line.split(' ')[1].to_i
|
||||||
|
dest_start = line.split(' ')[0].to_i
|
||||||
|
range = line.split(' ')[2].to_i
|
||||||
|
|
||||||
|
updated_seeds = seeds.each_with_index.map do |seed, i|
|
||||||
|
if seed >= source_start && seed < source_start + range
|
||||||
|
dest_start + (seed - source_start)
|
||||||
|
else
|
||||||
|
updated_seeds[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts updated_seeds.min
|
||||||
93
2023/day5/p2.rb
Normal file
93
2023/day5/p2.rb
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# @brief Maps a range from one range to another
|
||||||
|
def map_range(source, map_to_range)
|
||||||
|
offset = source.first - map_to_range[:source_range].first
|
||||||
|
range = source.last - source.first
|
||||||
|
(map_to_range[:dest_range].first + offset)..(map_to_range[:dest_range].first + offset + range)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @brief Augments a list of ranges to include all values between the first and last range
|
||||||
|
def augment_ranges(ranges, min_val, max_val)
|
||||||
|
augmented_ranges = []
|
||||||
|
ranges.sort_by! { |range| range[:source_range].first }
|
||||||
|
|
||||||
|
# Add the first range if it doesn't start at min_val
|
||||||
|
if ranges[0][:source_range].first > min_val
|
||||||
|
augmented_ranges << {
|
||||||
|
source_range: (min_val..(ranges[0][:source_range].first - 1)),
|
||||||
|
dest_range: (min_val..(ranges[0][:source_range].first - 1))
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add all ranges between the ranges that are in the list and the ones already in the list
|
||||||
|
ranges.each do |range|
|
||||||
|
# Add the range that goes from the previous to the current range
|
||||||
|
if !augmented_ranges.empty? && (range[:source_range].first > augmented_ranges[-1][:source_range].last + 1)
|
||||||
|
augmented_ranges << {
|
||||||
|
source_range: ((augmented_ranges[-1][:source_range].last + 1)..(range[:source_range].first - 1)),
|
||||||
|
dest_range: ((augmented_ranges[-1][:source_range].last + 1)..(range[:source_range].first - 1))
|
||||||
|
}
|
||||||
|
end
|
||||||
|
augmented_ranges << range
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add the last range if it doesn't end at max_val
|
||||||
|
if ranges[-1][:source_range].last < max_val
|
||||||
|
augmented_ranges << {
|
||||||
|
source_range: ((ranges[-1][:source_range].last + 1)..max_val),
|
||||||
|
dest_range: ((ranges[-1][:source_range].last + 1)..max_val)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
augmented_ranges
|
||||||
|
end
|
||||||
|
|
||||||
|
# Start of main program
|
||||||
|
f = File.open('./2023/day5/data')
|
||||||
|
seeds_in = f.first.strip.split(': ')[1].split(' ').map(&:to_i)
|
||||||
|
seeds = []
|
||||||
|
|
||||||
|
# Convert the seeds into ranges
|
||||||
|
i = seeds_in.length - 1
|
||||||
|
while i.positive?
|
||||||
|
seeds << (seeds_in[i - 1]..(seeds_in[i - 1] + seeds_in[i]))
|
||||||
|
i -= 2
|
||||||
|
end
|
||||||
|
seeds.sort_by!(&:first)
|
||||||
|
|
||||||
|
ranges = []
|
||||||
|
f.each_line do |line|
|
||||||
|
next if line.include?('seed') || line.strip.empty?
|
||||||
|
|
||||||
|
# Map indicates end of previous given mapping, map all seeds to new ranges
|
||||||
|
if line.include?('map') || f.eof?
|
||||||
|
puts line
|
||||||
|
new_seeds = []
|
||||||
|
seeds.each do |seed_range|
|
||||||
|
last_pos = seed_range.first
|
||||||
|
ranges = augment_ranges ranges, seeds[0].first, seeds[-1].last
|
||||||
|
ranges.each do |range|
|
||||||
|
next if seed_range.first > range[:source_range].last || seed_range.last < range[:source_range].first
|
||||||
|
|
||||||
|
pos = [seed_range.last, range[:source_range].last].min
|
||||||
|
new_seeds << map_range((last_pos..pos), range)
|
||||||
|
puts "Mapped #{last_pos..pos} to #{map_range((last_pos..pos), range)}"
|
||||||
|
last_pos = pos + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ranges = []
|
||||||
|
seeds = new_seeds
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
source_start = line.split(' ')[1].to_i
|
||||||
|
dest_start = line.split(' ')[0].to_i
|
||||||
|
range = line.split(' ')[2].to_i
|
||||||
|
ranges << {
|
||||||
|
source_range: (source_start..(source_start + range - 1)),
|
||||||
|
dest_range: (dest_start..(dest_start + range - 1))
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
seeds.sort_by!(&:first)
|
||||||
|
puts seeds[0].first
|
||||||
Reference in New Issue
Block a user