Enigmatic Code

Programming Enigma Puzzles

Enigma 1547: Square dates

From New Scientist #2710, 30th May 2009 [link] [link]

Writing 30 May 2009 in the order day’s number.month.year, with just one digit for the month but the year in full, gives 30.5.2009. This is a perfect square date because 3052009 = 1747². If two digits are allocated for the month, then 3 May 2009 (3.05.2009) was a perfect square date.

If you maintain the order day’s number.month.year and write the year as a four-digit number, as in these examples, what is the next date that will be a perfect square

(a) if you allocate one digit for the month, and
(b) if you allocate two digits for the month?

Give your answers in the form of (a) 30.5.2009, (b) 3.05.2009.

[enigma1547]

2 responses to “Enigma 1547: Square dates

  1. Jim Randell 27 March 2012 at 1:09 pm

    Here’s my original Perl code. It runs in 25ms.

    use strict;
    
    use Enigma qw/square/;
    
    sub a {
      my ($D, $M, $Y, $N);
      $Y = 2009; $M = 5; $D = 31;
      for (;;) {
        $N = int sprintf "%d%d%04d", $D, $M, $Y;
        if (square($N)) {
          printf "[A] %d.%d.%04d\n", $D, $M, $Y;
          return;
        }
        if ($D == 31) {
          $D = 1;
          if ($M == 9) {
            $M = 1;
            $Y++;
          } else {
            $M++;
          }
        } else {
          $D++;
        }
      }
    }
    
    sub b {
      my ($D, $M, $Y, $N);
      $Y = 2009; $M = 5; $D = 4;
      for (;;) {
        $N = int sprintf "%d%02d%04d", $D, $M, $Y;
        if (square($N)) {
          printf "[B] %d.%02d.%04d\n", $D, $M, $Y;
          return;
        }
        if ($D == 31) {
          $D = 1;
          if ($M == 12) {
            $M = 1;
            $Y++;
          } else {
            $M++;
          }
        } else {
          $D++;
        }
      }
    }
    
    a();
    b();
    

    Solution: (a) 22.6.2016, (b) 16.03.2016.

    • Jim Randell 27 March 2012 at 2:52 pm

      Here’s how I would do it now in Python. This uses the [[ datetime ]] module to go through increasing dates, and checks both parts of the problem together. It runs in 67ms.

      import datetime
      from enigma import is_square, printf
      
      fmt = {
        'a': "{d}{s}{m}{s}{y:04d}",
        'b': "{d}{s}{m:02d}{s}{y:04d}",
      }
      
      i = datetime.date(2009, 5, 31).toordinal()
      while fmt:
        i += 1
        d = datetime.date.fromordinal(i)
      
        for (k, v) in fmt.items():
          n = int(v.format(d=d.day, m=d.month, y=d.year, s=''))
          r = is_square(n)
          if r is None: continue
          printf("[{k}] {d} ({n} = {r}^2)", d=v.format(d=d.day, m=d.month, y=d.year, s='.'))
          del fmt[k]
      

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.