From 2a4842eb7760c5e9d58e3f1628d6eeced6bb0bd3 Mon Sep 17 00:00:00 2001 From: Greg Woods Date: Thu, 7 Dec 2023 19:42:03 -0500 Subject: [PATCH] Multi process solution for day 5 --- Rakefile | 1 + lib/days/05.rb | 45 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/Rakefile b/Rakefile index ff13b43..e24542d 100644 --- a/Rakefile +++ b/Rakefile @@ -5,6 +5,7 @@ require 'net/http' namespace :solve do task :all do + ENV['SKIP_LONG_RUNNING_SOLUTIONS'] = '1' runner = Aoc::Runner.new (1..25).each { |i| runner.call(i) } end diff --git a/lib/days/05.rb b/lib/days/05.rb index 044f74c..3790085 100644 --- a/lib/days/05.rb +++ b/lib/days/05.rb @@ -52,25 +52,48 @@ def part1(input) end def part2(input) + # Obviously forking is not the "correct" solution to this puzzle, but sometimes + # CPUs are faster than brains, and a star is a star. Maybe refactor later. 🙃 + + return -1 if ENV['SKIP_LONG_RUNNING_SOLUTIONS'] + seeds, mappings = parse(input) - results = {} - seeds.each_slice(2) do |index, stride| - stride.times do |n| - key = index + n - next if results.key?(key) + reads = [] + writes = [] - seed = index + n - mappings.each do |mapping| - seed = mapping.value(seed) + seeds.each_slice(2) do |index, stride| + read, write = IO.pipe + reads << read + writes << write + + fork do + # pid = Process.pid + # puts "BEGIN #{pid}: #{index} => #{stride}" + result = Float::INFINITY + + stride.times do |n| + # puts "#{pid}: #{n}/#{stride} (#{(n.to_f / stride * 100).round(1)}%)" if (n % 500_000).zero? + + seed = index + n + mappings.each do |mapping| + seed = mapping.value(seed) + end + result = [seed, result].min end - results[key] = seed + Marshal.dump(result, write) + write.close + + # puts "END #{pid}: #{index} => #{stride} (Result: #{result})" end end + Process.waitall + + writes.each(&:close) + results = reads.map { |p| Marshal.load(p.read) } # rubocop:disable Security/MarshalLoad - # Passes test but is too slow for real input - results.values.min + results.min end end