From da36d561b89141900a55c625cb537eee50242528 Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Thu, 15 Dec 2022 07:20:03 -0800 Subject: [PATCH] [2022][ruby][15.x] --- 2022/ruby/day_15.rb | 87 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 2022/ruby/day_15.rb diff --git a/2022/ruby/day_15.rb b/2022/ruby/day_15.rb new file mode 100644 index 0000000..23089ea --- /dev/null +++ b/2022/ruby/day_15.rb @@ -0,0 +1,87 @@ +require "set" + +sensors_and_beacons = ARGF.read + .scan(/Sensor at x=(-?\d+), y=(-?\d+): closest beacon is at x=(-?\d+), y=(-?\d+)/) + .map { _1.map(&:to_i) } + .flatten + .each_slice(2) + +# part one +row = 2_000_000 +# row = 10 + +no_beacons = [] +sensors_and_beacons.each_slice(2) do |sensor, beacon| + dist = sensor.zip(beacon).sum { (_1 - _2).abs } + + dy = (row - sensor[1]).abs + next if dy > dist + dx = dist - dy + + x_min, x_max = [sensor[0]-dx, sensor[0]+dx].sort + + no_beacons << (x_min..x_max) +end + +# remove covered ranges +no_beacons = no_beacons.reject {|x| (no_beacons - [x]).any? { _1.cover?(x) }} + +# merge ranges +no_beacons = no_beacons.inject([no_beacons.shift]) {|no_beacons, range| + next no_beacons if no_beacons.any? { _1.cover?(range) } + + if overlap = no_beacons.find { _1.cover?(range.begin) } + range = (overlap.end + 1..range.end) + end + + if overlap = no_beacons.find { _1.cover?(range.end) } + range = (range.begin..overlap.begin-1) + end + + no_beacons << range +} + +p no_beacons.sum(&:size) - sensors_and_beacons.to_a.select { _2 == row }.uniq.size + +# part two +find_sab = ->(x, y) { + sensors_and_beacons.each_slice(2).find {|sensor, beacon| + dist = sensor.zip(beacon).sum { (_1 - _2).abs } + dist >= sensor.zip([x, y]).sum { (_1 - _2).abs } + } +} + +max = 4_000_000 +# max = 20 +x = 0 +y = 0 +loop do + p y if (y % 10_000).zero? + + sensor, _ = find_sab.(x, y) + dx = sensor[0] - x + if dx >= max / 2 + dy = sensor[1] - y + y += dy.positive? ? 2 * dy + 1 : 1 + end + + loop do + sensor, beacon = find_sab.(x, y) + if sensor.nil? + p 4_000_000 * x + y + exit + end + + dist = sensor.zip(beacon).sum { (_1 - _2).abs } + dy = (sensor[1] - y).abs + dx = (dist - dy).abs + x = sensor[0] + dx + 1 + + if x > max + x = 0 + break + end + end + y += 1 + break if y > max +end