diff --git a/ruby/2017/15/bin/problem b/ruby/2017/15/bin/problem index 0cba6af..a4a9f45 100644 --- a/ruby/2017/15/bin/problem +++ b/ruby/2017/15/bin/problem @@ -1,38 +1,7 @@ #!/usr/bin/env ruby +require "dueling_generator" -def generate(value, factor) - (value * factor) % 2147483647 -end +gg = DuelingGenerator::GeneratorPair.for STDIN.read.chomp -line_1, line_2 = STDIN.read.chomp.split("\n").to_a -generator_a_start = line_1.gsub("Generator A starts with ", "").to_i -generator_b_start = line_2.gsub("Generator B starts with ", "").to_i - -a_factor = 16807 -b_factor = 48271 - -a = generator_a_start -b = generator_b_start -pairs = 0 - -40000000.times do - a = generate(a, a_factor) - b = generate(b, b_factor) - pairs += 1 if (a & 65535 == b & 65535) -end - -puts "Part 1: #{pairs}" - -a = generator_a_start -b = generator_b_start -pairs = 0 - -5000000.times do - a = generate(a, a_factor) - a = generate(a, a_factor) until (a % 4) == 0 - b = generate(b, b_factor) - b = generate(b, b_factor) until (b % 8) == 0 - pairs += 1 if (a & 65535 == b & 65535) -end - -puts "Part 2: #{pairs}" \ No newline at end of file +puts "Part 1: #{gg.loose_pair_count}" +puts "Part 2: #{gg.strict_pair_count}" diff --git a/ruby/2017/15/lib/dueling_generator.rb b/ruby/2017/15/lib/dueling_generator.rb new file mode 100644 index 0000000..700ea99 --- /dev/null +++ b/ruby/2017/15/lib/dueling_generator.rb @@ -0,0 +1,85 @@ +class DuelingGenerator + attr_reader :value, :start + def initialize(value) + @value = value + @start = value + end + + def self.for(string) + type, value = string.gsub("Generator ", "").split(" starts with ") + Object.const_get("DuelingGenerator::Generator#{type}").new value.to_i + end + + def reset! + @value = start + end + + def generate! + @value = (value * factor) % 2147483647 + end + + def strict_generate! + @value = (value * factor) % 2147483647 + generate! until meets_criterion? + end + + def meets_criterion? + value % criterion == 0 + end + + class GeneratorA < DuelingGenerator + def factor + 16807 + end + + def criterion + 4 + end + end + + class GeneratorB < DuelingGenerator + def factor + 48271 + end + + def criterion + 8 + end + end + + class GeneratorPair + attr_reader :g1, :g2 + def initialize(g1, g2) + @g1 = g1 + @g2 = g2 + end + + def self.for(input) + new *input.split("\n").map { |line| DuelingGenerator.for line } + end + + def loose_pair_count(comparisons = 40000000) + g1.reset! + g2.reset! + pairs = 0 + comparisons.times do + g1.generate! + g2.generate! + pairs += 1 if g1.value & 65535 == g2.value & 65535 + end + pairs + end + + def strict_pair_count(comparisons = 5000000) + g1.reset! + g2.reset! + pairs = 0 + comparisons.times do + g1.strict_generate! + g2.strict_generate! + pairs += 1 if g1.value & 65535 == g2.value & 65535 + end + pairs + end + end +end