Enigmatic Code

Programming Enigma Puzzles

Enigma 1710: Carregio

From New Scientist #2877, 11th August 2012 [link]

Since the second world war, car registrations in my country have consisted of three parts: the first is the four-figure year of manufacture, the second is made up of two letters, and the third consists of a number which, in my case, has three digits. However, we are now switching to all-digit car registrations, consisting of three parts. Existing registrations such as mine will be adapted by changing the two letters to a number by replacing A by 1, B by 2, and so on, so that, for example, GL would become 712.

The three numbers making up the three parts of my car’s registration will then all be multiples of 18, but none will be a perfect square. And overall the registration will use each of the digits 0 to 9 exactly once.

What is my car’s registration before the changes?

[enigma1710]

Advertisements

3 responses to “Enigma 1710: Carregio

  1. Jim Randell 8 August 2012 at 5:37 pm

    The following Python code runs in 31ms.

    from itertools import product
    from enigma import is_square, irange
    
    # the registration is: YYYY-XX-NNN (where X is a letter and N is a number)
    # then XX is also converted  to a (3-digit) number
    # each part is then a multiple of 18, and a non-square
    
    # we need to find 3-digit non-square multiples of 18, with no repeated digits
    ns = []
    for n in irange(108, 999, step=18):
      if is_square(n): continue
      s = str(n)
      if len(set(s)) != 3: continue
      ns.append(s)
    
    # which are composed of the ordinal numbers of two letters
    # (NOTE: this is non-unique: e.g. both AZ and LF map to 126)
    xs = dict()
    for (i, j) in product(irange(1, 26), repeat=2):
      s = str(i) + str(j)
      if s not in ns: continue
      xs[chr(64 + i) + chr(64 + j)] = s
    
    # the year is a post war multiple of 18
    for y in irange(1944, 2012, step=18):
      if is_square(y): continue
      ds = set(str(y))
      if len(ds) != 4: continue
    
      # we need a disjoint 3-digit non-square multiple of 18 transcribed from letters
      for (s, x) in xs.items():
        ds2 = ds.union(set(x))
        if len(ds2) != 7: continue
    
        # and a 3-digit non-square made up of the remaining digits
        for n in ns:
          ds3 = ds2.union(set(n))
          if len(ds3) != 10: continue
    
          print(y, s, n)
    

    Solution: Before the changes the registration was 1980 WD 756.

    • Naim Uygun 8 August 2012 at 7:40 pm

      The candidate years: 1962, 1980
      The candidate numbers of two letters: GT=720, WD=234,GB=72, ED=54
      Hence, my car registration before the changes is 1980-WD-756

  2. Brian Gladman 9 August 2012 at 8:14 am

    Here is an alternative version:

    # check that a tuple partitioning the digits of a three digit
    # number either (1, 2) or (2, 1) gives valid two letter codes
    def nbr_to_str(x):
      
      def trans(t, i, j):
        return (chr(ord('A') + t[0] - 1) + chr(ord('A') + t[1] - 1)
                if 0 < t[i] < 10 and 10 <= t[j] <= 26 else '')
      
      c = trans(divmod(x, 100), 0, 1) + trans(divmod(x, 10), 1, 0)
      # only return unambiguous two letter codes
      return c if len(c) == 2 else None
    
    # a map of four digit squares 
    sq = {x*x:x for x in range(100)}
    
    # the middle three digits of the new number
    for mid in range(108, 1008, 18): 
      
      # check that these digits represent a valid two letter code 
      ltrs = nbr_to_str(mid)
      set_mid = set(str(mid))
      if mid not in sq and len(set_mid) == 3 and ltrs:
        
        # the first four digits for the year
        for year in range(1944, 2016, 18):
          set_year = set(str(year))
          if year not in sq and len(set_year) == 4:
            
            # the set of used digits so far
            used_set = set_mid | set_year 
            # the final three digits
            for final in range(108, 1008, 18):          
              # check that this potential solution uses all 10 digits
              if final not in sq and len(set(str(final)) | used_set) == 10:
                print('{:d}-{:s}-{:d}'.format(year, ltrs, final))
    

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: