Skip to content

Instantly share code, notes, and snippets.

@carlwiedemann
Last active December 6, 2023 14:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlwiedemann/d7111102935b24a3199250a4e79da969 to your computer and use it in GitHub Desktop.
Save carlwiedemann/d7111102935b24a3199250a4e79da969 to your computer and use it in GitHub Desktop.
Advent of Code 2023 day005.rb
require_relative "main"
module Day005
INPUT = File.read('INPUT.txt')
lines = INPUT.to_lines
seeds = lines.shift.split(":").last.split_strip(" ").map(&:to_i)
lines.shift
categories = []
lines.each do |line|
matches = /([a-z]+)-to-([a-z]+)/.match(line)
if matches
categories.push([])
elsif line != ""
parts = line.split_strip(" ").map(&:to_i)
dest_start = parts[0]
source_start = parts[1]
size = parts[2]
dest_end = dest_start + size - 1
source_end = source_start + size - 1
categories.last.push({
source: (source_start..source_end),
dest: (dest_start..dest_end)
})
end
end
seed_to_location = ->(seed) do
cursor = seed
categories.each do |category|
found = false
category.each do |map|
if map[:source].include?(cursor)
found = true
source_i = cursor - map[:source].first
dest_v = map[:dest].first + source_i
cursor = dest_v
end
break if found
end
end
cursor
end
location_to_seed = ->(location) do
cursor = location
categories.reverse.each do |category|
found = false
category.each do |map|
if map[:dest].include?(cursor)
found = true
dest_i = cursor - map[:dest].first
source_v = map[:source].first + dest_i
cursor = source_v
end
break if found
end
end
cursor
end
##########
# Part 1 #
##########
min1 = nil
seeds.each do |seed|
cursor = seed_to_location.call(seed)
min1 = cursor if min1.nil? || cursor < min1
end
answer1 = min1
pp answer1
##########
# Part 2 #
##########
seed_ranges = seeds.each_slice(2).map do |pair|
first = pair[0]
last = pair[0] + pair[1]
(first..last)
end
# Let's try 100,000 values, spaced 100 apart
min2 = nil
100000.times do |i|
j = i * 100
seed = location_to_seed.call(j)
break_all = false
seed_ranges.filter.with_index do |range|
if range.include?(seed)
k = j
loop do
seed2 = location_to_seed.call(k)
if range.include?(seed2)
min2 = k if min2.nil? || k < min2
else
break_all = true
break
end
k -= 1
end
end
break if break_all
end
break if break_all
end
answer2 = min2
pp answer2
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment