The Leap Machine (Puzzle)

The Leap Machine (Puzzle)

Here’s a puzzle for you –

Like the TARDIS, your time machine has a fault.

Like the TARDIS, your time machine has a fault. The fault isn’t a failure of its chameleon circuit, but a quirk in its ability to jump to particular dates. Picture courtesy aussiegall (Flickr), licensed Creative Commons.

You own a time machine with an unusual property: it can only travel to 29th February. It can jump to any 29th February, anywhere at all, in any year (even back before we invented the Gregorian Calendar, and far into the future after we’ve stopped using it), but it can only finish its journey on a 29th of February, in a Gregorian leap year (for this reason, it can only jump to years which are leap years).

One day, you decide to take it for a spin. So you get into your time machine and press the “random” button. Moments later, you have arrived: it is now 29th February in a random year!

Without knowing what year it is: what is the probability that it is a Monday? (hint: the answer is not 1/7 – half of your challenge is to work out why!).

Dan Q is a software engineer, a director of a voluntary organisation, a trainee counsellor, a keen geocacher, and an amateur magician. He lives with his partner and her husband in a polyamorous triad, and occasionally finds time to blog.


  1. Gareth 5 years ago

    The chance is the same as it being a Wednesday or a Friday (which are the most probable) and it’s least likely to be Tuesday, but as you say, interesting to learn why (hence I’m not saying any more!)

    • Scatman Dan 5 years ago

      That’s interesting. I suspect we’re thinking in the same direction, but I didn’t quite get the same answer. What’s the probability you calculate for Monday?

      I’ll post my answer (and how I worked it out, in case I’m wrong!) later in the week.

      • Gareth 5 years ago

        Hm, so I made a “small” mistake in my calculations due to changing from using the Date class to Time in Ruby and it not throwing an exception I was expecting… Grr.

        Having fixed that (and done a sanity check!), I now get Monday and Wednesday having the same (highest) probability, of 15/97, or 0.15463917525773196. I’ll send you my code :-)

        • Scatman Dan 5 years ago

          Nicely done. That’s my answer, too. Here’s my code (also in Ruby):

          puts (0..400).
          collect{|k,v|"%s - %d"%[k,v]}.

          It’s a little sloppy: I could have taken some more-elegant shortcuts.

          • Gareth 5 years ago

            It’s also broken ;-)

            Your code is checking 401 years (between the year 0 and the year 400, inclusive)

            Changing 0..400 to 0…400 would do the right thing.

            • Scatman Dan 5 years ago

              Ah-hah! Right you are. I’m still correct for the ranges I tested (because the year after and the year before aren’t leap years anyway), but it’s a valid point. I had meant to use:


              • Gareth 5 years ago

                The year 0 and the year 400 are *both* leap years, so your code added an extra Leap-Tuesday into the mix.

                • Scatman Dan 5 years ago

                  You’re right that my code makes that mistake. However the fact that it comes up with the wrong answer as a result could be a fault of the interpreter and not my code…

                  The year “0” in ISO 8601 format, as (supposedly) used by Ruby’s Date format, corresponds to 1BCE (there was no “year 0” as zero hadn’t come to the West at the time of the creation of the Gregorian calendar). Should this be a leap year? It depends on how you calculate them. It’s four years from a leap year and not the 25th such leap year in a row (and not-not the 100th potential one), which would say yes. But on the other hand, it doesn’t divide by 4, which would say no.

                  …or rather, it’s the fact that there is no unambiguous definition in the Gregorian calendar about how to handle BCE leap years that means that different interpretations exist. It could be argued either way whether 1BCE was a leap year or not. Ruby says it was, but I’m not sure it’s right…

  2. iamapizza 5 years ago

    Also replied on Reddit:

    import collections

    def getDayFromNumber(n):
    if n == 0:
    return 'Tuesday'
    if n == 1:
    return 'Monday'
    if n == 2:
    return 'Sunday'
    if n == 3:
    return 'Saturday'
    if n == 4:
    return 'Friday'
    if n == 5:
    return 'Thursday'
    if n == 6:
    return 'Wednesday'

    yearDay = {}
    days = []
    centuryCounter = 0

    for y in range(1600,1999):
    if y > 1600 and y % 100 == 0:
    centuryCounter = centuryCounter + 1

    if y % 1600 == 0 or (y % 4 == 0 and not y % 100 == 0):
    d = (((y-1600) / 2) + centuryCounter) % 7
    yearDay[y] = getDayFromNumber(d)

    print yearDay
    print collections.Counter(days)

  3. Spencer 5 years ago

    This problem is fairly easy to solve if you know about Conway’s “Doomsday Rule” for converting dates to days of the week in your head.

    Following Conway’s Doomsday rule, the last day of Feb is always a doomsday. So then we have do calculate the distribution of doomsdays for the 400-year gregorian cycle. This is done nicely with the code above; I just counted from Wikipedia’s list of Doomsdays, which conveniently highlights leap-years.

    Mon 15
    Tue 13
    Wed 15
    Thu 13
    Fri 14
    Sat 14
    Sun 13

    Total 97

    • Scatman Dan 5 years ago

      What an excellent way to get to the answer!