Advent of Code 2017, Day 15: Dueling Generators

#ruby #advent of code 2017

Part A

On Day 15 we are working with number generators. We have two generators that start with given numbers as input. In each iteration, generator multiplies its value by fixed number and keeps the reminder of diving by 2147483647.

We need to count how many times lowest 16 bits matched for both generators after 40 million iterations.

Here is the solution:

a = 65
b = 8921
count = 0

40_000_000.times do
  a = (a * 16807) % 2147483647
  b = (b * 48271) % 2147483647

  if a & 0xffff == b & 0xffff
    count += 1
  end
end

puts count

a and b are the starting numbers given as input. The solution is trivial, we just iterate 40 million times and count how many times values matched (16 lowest bits). Maybe not optimal solution, but runs in 2-3 seconds so I think it is fine.

Part B

In the second part the rules are a bit different. Generators still generate numbers in the same way, but generator A only hands down numbers divisible by 4 and generator B numbers divisible by 8. This means that when one generator has valid number another one may not have anything to compare to.

We need to store results from both generators and only compare numbers when we have results from both. Here is the solution:

a = 65
b = 8921

count = 0
a_values = []
b_values = []

iterations = 0

while true
  a = (a * 16807) % 2147483647
  b = (b * 48271) % 2147483647

  a_values.push(a) if a % 4 == 0
  b_values.push(b) if b % 8 == 0

  while a_values.size > 0 && b_values.size > 0
    a_val = a_values.shift
    b_val = b_values.shift
    iterations += 1

    if a_val & 0xffff == b_val & 0xffff
      count += 1
    end

    if iterations >= 5_000_000
      break
    end
  end

  if iterations >= 5_000_000
    break
  end
end

puts count

We are storing results in two different arrays and only when both have values we compare them. This is again maybe not optimal solution, but 4 seconds seems fine to me. I think there are some arithmetic tricks you can do to get faster answers, but didn’t have time to figure it out. Yet.