Enigmatic Code

Programming Enigma Puzzles

Enigma 1092: A prime age

From New Scientist #2248, 22nd July 2000 [link]

Marge, April, May, June, Julia and Augusta have all celebrated their birthday today. They are all teenagers and with the exception of the one pair of twins their ages are all different.

Today, only Marge and April have ages which are prime numbers, but the sum of the ages of all the girls is also a prime number. On their birthday last year, only May and June had ages which were prime numbers, but again the sum of the ages of all the girls was a prime number. On their birthday two years before that, only May and Julia had ages which were prime numbers, but even then, the sum of the ages of all the girls was again a prime number.

How old is Augusta?

[enigma1092]

3 responses to “Enigma 1092: A prime age

  1. Jim Randell 16 October 2017 at 7:49 am

    I wrote a program that just considers all possible assignments of ages to the girls, and it ran in 435ms.

    The Python 3.6 program below, starts by looking for sequences of ages that sum to a prime number, and would also give a prime sum for the ages a year ago and three years ago. It runs in 98ms.

    Run: [ @repl.it ]

    from itertools import combinations, permutations
    from enigma import irange, is_prime, uniq, printf
    
    # indices for the girls
    girls = (Mar, Apr, May, Jun, Jul, Aug) = irange(0, 5)
    
    # possible ages (they are all teenagers)
    ages = (13, 14, 15, 16, 17, 18, 19)
    
    # generate possible ages
    def generate():
    
      # choose five of the ages
      for s in combinations(ages, 5):
    
        # and sum them
        t0 = sum(s)
    
        # then add in one of them again (for the twins)
        for x in s:
          t = t0 + x
    
          # check the sum of the ages is prime, and would be prime last year, and three years ago
          if not all(is_prime(t + d) for d in (0, -6, -18)): continue
    
          # return the ages
          yield s + (x,)
    
    # find girls with prime ages
    def check(age, ago=0):
      return tuple(x for x in girls if is_prime(age[x] - ago))
    
    # choose possible ages
    for s in generate():
    
      # and assign the ages to the girls
      for age in uniq(permutations(s)):
    
        # in the current year only Mar and Apr are prime
        if check(age) != (Mar, Apr): continue
    
        # last year only May and Jun were prime
        if check(age, 1) != (May, Jun): continue
        
        # three years ago only May and Jul were prime
        if check(age, 3) != (May, Jul): continue
    
        # output solutions
        printf("Mar={age[Mar]} Apr={age[Apr]} May={age[May]} Jun={age[Jun]} Jul={age[Jul]} Aug={age[Aug]}")
    

    Solution: Augusta is 15.

    There is only one assignment of ages that satisfies the conditions of the problems:

    Marge = 13, April = 13, May = 14, June = 18, Julia = 16, Augusta = 15

    In fact, there are only two sequences of ages that will allow the sums to be prime this year, last year and three years ago:

    (13, 14, 14, 15, 16, 17), sum = 89
    (13, 13, 14, 15, 16, 18), sum = 89

    For both sequences the sum last year would be 83, and three years ago it would be 71. But the first of these sequences would give three prime ages three years ago.

  2. Jim Randell 16 October 2017 at 7:59 am

    Here is the problem expressed as a set of MiniZinc constraints.

    I get an execution time of 195ms for the [[ mzn-gecode -a ]] solver.

    include "globals.mzn";
    
    % current ages (all teenagers)
    set of int: Ages = { 13, 14, 15, 16, 17, 18, 19 };
    var Ages: Mar;
    var Ages: Apr;
    var Ages: May;
    var Ages: Jun;
    var Ages: Jul;
    var Ages: Aug;
    
    % primes below 120
    set of int: Primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113 };
    
    % there are five different ages between them
    constraint nvalue([ Mar, Apr, May, Jun, Jul, Aug ]) = 5;
    
    % today only Mar and Apr have prime ages
    constraint forall (x in { Mar, Apr }) (x in Primes);
    constraint forall (x in { May, Jun, Jul, Aug }) (not(x in Primes));
    
    % and the sum of the six ages is prime
    constraint sum([ Mar, Apr, May, Jun, Jul, Aug ]) in Primes;
    
    % last year, only May and Jun had prime ages
    constraint forall (x in { May, Jun }) (x - 1 in Primes);
    constraint forall (x in { Mar, Apr, Jul, Aug }) (not(x - 1 in Primes));
    
    % and the sum of the six ages was prime
    constraint sum (x in [ Mar, Apr, May, Jun, Jul, Aug ]) (x - 1) in Primes;
    
    % three years ago, only May and Jul had prime ages
    constraint forall (x in { May, Jul }) (x - 3 in Primes);
    constraint forall (x in { Mar, Apr, Jun, Aug }) (not(x - 3 in Primes));
    
    % and the sum of the six ages was prime
    constraint sum (x in [ Mar, Apr, May, Jun, Jul, Aug ]) (x - 3) in Primes;
    
    solve satisfy;
    
  3. Brian Gladman 17 October 2017 at 9:22 am
    from itertools import product
    
    # test for primes below 121
    pr = (2, 3, 5, 7, 11)
    is_prime = lambda x: x in pr or all(x % p for p in pr)
    
    # teenage years
    teens = range(13, 20)
    
    # Marge and April's ages are primes now
    for Mar, Apr in product((x for x in teens if is_prime(x)), repeat=2):
      
      # May and June's ages were primes last year
      for May, Jun in product((x for x in teens if is_prime(x - 1)), repeat=2):
        
        # there is at most one duplicate and May's age three years ago was prime
        ls = len(set((Mar, Apr, May, Jun)))
        if ls < 3 or not is_prime(May - 3):
          continue
        
        # Julia and Augusta's ages are among the remaining non-primes
        rest = {x for x in teens if not is_prime(x)}.difference([May, Jun])
        for Jul, Aug in product(rest, repeat=2):
          t = (Mar, Apr, May, Jun, Jul, Aug)
          
          # there is exactly one duplicate and Julia's age 3 years ago was prime
          if len(set(t)) != 5 or not is_prime(Jul - 3):
            continue
             
          # this year, one year and three years ago the sum of their 
          # ages is/was prime and two of the six ages are/were prime
          st = sum(t)
          if all(is_prime(st - 6 * x) and 
                 len([1 for a in t if is_prime(a - x)]) == 2 for x in (0, 1, 3)):
            print(f'Marge .. Augusta: {t}')
    

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 )

Google photo

You are commenting using your Google 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

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

%d bloggers like this: