Enigmatic Code

Programming Enigma Puzzles

Enigma 1540: On the run

From New Scientist #2703, 11th April 2009 [link]

On three days in each calendar week (Sunday to Saturday) I go for a run, but I never run on two consecutive days.

In the last 12 years there was

(a) a year when I went for two more runs in February than in March,
(b) a year when I went for four more runs in March than in February.

Which years were those?

[enigma1540]

Advertisements

One response to “Enigma 1540: On the run

  1. Jim Randell 16 April 2012 at 8:33 pm

    The following Python program runs in 100ms.

    from itertools import combinations
    from datetime import date, timedelta
    from enigma import irange, printf
    
    # weeks that are internal to the month always have 3 runs in them
    # and the runs can be Mon, Wed, Fri, so not interfere with adjacent weeks
    
    # generate runs such that there are three a week and no two are consecutive
    runs = []
    for r in combinations(irange(0, 6), 3):
      r = sorted(r)
      if r[2] - r[1] == 1 or r[1] - r[0] == 1: continue
      runs.append(r)
    
    # s = start date
    # feb = accumulated runs in Feb
    # mar = accumulated runs in Mar
    # sat = does the previous week end with a run on a Saturday?
    def solve(s, feb, mar, sat):
      # are we done?
      if s.month == 4:
        if feb == mar + 2:
          printf("[a] year={s.year} feb={feb} mar={mar}")
          return True
        elif mar == feb + 4:
          printf("[b] year={s.year} feb={feb} mar={mar}")
          return True
        return False
      # what's the date at the end of this week?
      e = s + timedelta(days=6)
      if s.month == e.month:
        # internal week, so add three runs to the current month    
        if s.month == 2:
          feb += 3
        else:
          mar += 3
        return solve(s + timedelta(days=7), feb, mar, False)
    
      # try one of the possible patterns of runs
      for p in runs:
        # can't run on a Sunday if we ran on a Saturday in the previous week
        if sat and p[0] == 0: continue
        (f, m) = (0, 0)
        for i in p:
          d = (s + timedelta(days=i)).month
          if d == 2:
            f += 1
          elif d == 3:
            m += 1
        if solve(s + timedelta(days=7), feb + f, mar + m, p[2] == 6): return True
    
    for year in irange(1997, 2009):
      # find the first Sunday on or before 1st February
      d = date(year, 2, 1)
      s = d - timedelta(days=d.isoweekday() % 7)
      solve(s, 0, 0, False)
    

    Solution: (a) 2000, (b) 2005.

Leave a Comment

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

%d bloggers like this: