I don't know about those theorems. It's a prime factorisation problem (and evidently all bus numbers are prime numbers, so that makes it even easier). My Ruby solution is general purpose (so also non-prime busses) but 🤷
require'prime'require'benchmark'source='input.txt'timestamp,schedule_line=File.readlines(source)schedule=schedule_line.split(',').map{|x|x.chomp}busses=schedule.each_with_index.map{|bus,offset|bus!='x'?[bus.to_i,offset]:nil}.compactcurrent_timestamp=0# This is unnecessary because all bus numbers are prime numbers, but this more# general solution works for busses that are non-prime!## In this exercise, the result is an array with one element: the first bus number:# [7]timestamp_factors=busses.shift.first.prime_division.map(&:first)Benchmark.bmdo|x|x.reportdobusses.eachdo|(bus,offset)|# The first bus will depart at t + 0 every t = bus * i. In fact, for any bus it's# true that once you find a valid t where t + offset = bus * i, the next# valid t for that bus is (t + bus).## So you can skip all the ts inbetween.skip_factor=timestamp_factors.inject(&:*)# Find the next t for which [t + offset = bus * i].loopdominutes_to_departure=bus-(current_timestamp%bus)breakifminutes_to_departure==offset%buscurrent_timestamp+=skip_factorend# If all busses are prime numbers (they are in AoC), the prime-only# solution would be:## timestamp_factors.push(bus)## The general purpose solution looks like this:timestamp_factors.push(*bus.prime_division.map(&:first))timestamp_factors.uniq!endendendputscurrent_timestamp
Thanks for this. I was really stuck on this; came on here and saw folks mentioning a new theory (which bummed me out). I had been trying to figure something out with LCM, and your solution showed me what I'd been missing. Here's the core of mine:
current_timestamp=ids.first.firstids.each_with_indexdo|(bus_id,offset),index|nextifindex==0# At this point, we start off with a t that's valid for bus 1# Second iteration will add the period (bus 1's cycle) to t until it finds a valid t# Subsequent iterations will add the period (LCM of already found numbers)# Why does this work? Because the cycle repeats over the period.# So, if we've found a t that has b2 and b1 at certain positions,# Then using a period of lcm(b1, b2) will have them in the same positions again. (LCM == coinciding cycles)# So we just need to do this until we find where position(b3) = position(b2) + offset# Then update our period and go again for the next bus.period=ids[0..index-1].reduce(1){|acc,(id,_)|acc.lcm(id)}loopdodifference=bus_id-(current_timestamp%bus_id)breakifdifference==(offset%bus_id)current_timestamp+=periodendendpcurrent_timestamp
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
I don't know about those theorems. It's a prime factorisation problem (and evidently all bus numbers are prime numbers, so that makes it even easier). My Ruby solution is general purpose (so also non-prime busses) but 🤷
Thanks for this. I was really stuck on this; came on here and saw folks mentioning a new theory (which bummed me out). I had been trying to figure something out with LCM, and your solution showed me what I'd been missing. Here's the core of mine: