Programming Challenge: Martian Calendar

This week, another programming challenge, but this time considerably tougher than the previous.

His Imperial Majesty, Xórgü of House Nand, decrees that the martian imperial court is in need of a new calendar. The current martian calendar counts 668 days, but it accumulates errors. The martian year, according to His Imperial Majesty’s most illustrious astronomers, is in fact 668.60 (martian) days long.

Martians really like prime numbers, so the emperor decrees that the new calendar must be such that:

  • It has a prime number of months, more than 10, less than 18,
  • Every month as a prime number of days,
  • Months must have about the same number of days,
  • Months must be at least 3 weeks long, that is, at least three martian weeks of 13 days (they have 13 fingers, you see), but at most five,
  • Months, in calendar order, must have non-decreasing number of days

The calendar is to start at year 1, corresponding to the birth year of Emperor Xórgü.

Your task is therefore:

  • To find a simple rule for leap years (those with leap days; also known as intercalar or epagomenal days),
  • To determine how to organize the year in months, with the rules decreed by the emperor,
  • To write a routine that converts a martian date (day, month, year) to an integer (days since Xórgü) and one that takes an integer and produces a martian date,

You can neglect year 0 and negative dates. Dates before year 1 are decreed to not exist.

You must also show that your code works correctly for all dates (say the first million (martian) years).

13 Responses to Programming Challenge: Martian Calendar

  1. gui13 says:

    Can leap years have more that 1 leap day?

  2. gui13 says:

    I’ll answer to myself here: it’s obligatory, since a month is required to have a prime number of days.

  3. gkusner says:

    This has a basic flaw: the prime numbers for months are 11,13, or 17
    the prime numbers for days per month are 41, 43, 47, 53, 59, 61 inclusive
    however since all the numbers are odd NO possibilities of an odd number of months made up of odd numbers of days can add to an even number 668

  4. gkusner says:

    Leap years must also be primes – but the original definition requires that the base months must be primes:

    – It has a prime number of months, more than 10, less than 18,
    – Every month as a prime number of days,

    • Steven Pigeon says:

      Years themselves do not have to have a prime number of days, only a prime number of months (which have a prime number of days)

  5. gkusner says:

    I understand but the year is defined as 668.6 days which means that non leap years have 668 days which is the problem of odd number of odd additions.

    I love this problem but the basic number requirements just don’t work.

    • Steven Pigeon says:

      Maybe that’s answer (i.e., the constraints make its impossible) or maybe you’re not seeing a detail (especially with respect to leap years ;) )

  6. Armand Cat says:

    can we have leap years having fewer days than normal years?

  7. […] readers came up with very creative solutions—far better than my own), and the problem of the Martian calendar was a bit more deductive (and still not solved, though some of the readers came close to a […]

  8. John Y. says:

    Given the responses so far, I would propose a Martian year of 11 months. The first month of “normal” years would have 59 days while the rest have 61, for a total of 669 days. You said negative leap days were allowed, so this makes for a very, very simple leap-year rule, which is that every 5 years, remove two days from the 2nd month. Thus even in leap-shortened form, all months have a prime number of days.

    My routines for date calculations are not at all elegant, but at least they are hopefully very easy to understand. Implemented in Python:

    def int_to_dmy(n):
        y = 5 * ((n - 1) // 3343) + 1
        d = (n - 1) % 3343 + 1
        while d > 669:
            d -= 669
            y += 1
        if y % 5:
            monthdays = (59, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61)
            monthdays = (59, 59, 61, 61, 61, 61, 61, 61, 61, 61, 61)
        m = 0
        while d > monthdays[m]:
            d -= monthdays[m]
            m += 1
        m += 1
        return d, m, y
    def dmy_to_int(d, m, y):
        if y % 5:
            monthdays = (59, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61)
            monthdays = (59, 59, 61, 61, 61, 61, 61, 61, 61, 61, 61)
        d += sum(monthdays[:m - 1])
        d += 3343 * ((y - 1) // 5)
        d += 669 * ((y - 1) % 5)
        return d
    • Steven Pigeon says:

      And we have a winner.

      Yes, the hardest part was to break of our concept of leap year and have years with fewer days.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: