# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1: Serious ages

From New Scientist #1143, 22nd February 1979 [link] “If they hadn’t invented the Closed University,” said Radiotimes of Ilea, “I shouldn’t have learned about the serious function. Every birthday now I work out how serious my new ages is. For instance, I am 27 today, and I calculate the seriousness of 27 as 4; or, as we say at the CU, S(27) = 4. That is because, as you see from the blackboard, there are 4 ways in which you can compose an arithmetical progression of one or more positive integers, in which each term is 1 greater than the previous one, with the sum of the terms totalling 27”.

“I see,” I said.

“Just to be sure you do see,” said Radiotimes, “tell me:

(a) if I live to be 100, what is/are the most serious birthday(s) I shall have had?

(b) How much over 100 should I have to live to reach a more serious birthday than that?”

This is the first Enigma puzzle ever published in New Scientist!

A £5 prize was offered for the solution (about 14.3 times the 35p cover price of the magazine).

An incomplete solution was published in New Scientist #1144, but that was followed up with a clarification in New Scientist #1145.

[enigma1]

### 6 responses to “Enigma 1: Serious ages”

1. Jim Randell 1 December 2011 at 4:29 pm

This Python program finds the solution in 30ms:

```from itertools import count

def S(n):
s = 1
for i in count(2):
t = (i * (i - 1)) // 2
if t > n:
break
(d, r) = divmod(n - t, i)
if d > 0 and r == 0:
s += 1
return s

# (a) if I live to be 100, what are the most serious birthdays I shall have had?
(mn, ms) = ([], 0)
for n in range(1, 101):
s = S(n)
if s > ms:
(mn, ms) = ([n], s)
elif s == ms:
mn.append(n)
print("max(S(n)) @ n={n}, S(n)={s}".format(n=mn, s=ms))

# (b) How much over 100 should I have to live to reach a more serious birthday than that?
for n in count(101):
s = S(n)
if s > ms:
print("S({n}) = {s}".format(n=n, s=s))
break
```

Solution: (a) The most serious birthdays are: 45, 63, 75, 90 and 99. All have seriousness of 6. (b) Birthday 105 exceeds these with seriousness 8.

2. Hugh Casement 29 June 2015 at 8:15 am

I think I’m right in saying that a number has seriousness 1 if and only if it’s a power of 2 (including 2^0 = 1).
The smallest numbers with these seriousnesses appear to be:
S(1) = 1, S(3) = 2, S(9) = 3, S(15) = 4, S(81) = 5, S(45) = 6, S(729) = 7, S(105) = 8, S(225) = 9, S(405) = 10, S(315) = 12, S(3645) = 14, S(2025) = 15, S(945) = 16.
For S = 11 or 13 one would have to go a lot higher.
Can’t see much of a pattern!

• Jim Randell 3 October 2016 at 8:35 am

The sequence appears in OEIS as A001227 [ @oeis ], where it is characterised as “a(n) = the number of odd divisors of n”. (See also: Polite number [ @wikipedia ]).

So we could shorten the computation of S(n) to:

```def S(n):
return sum(d % 2 for d in divisors(n))
```

So we can find lowest values of n for S(n) by multiplying together odd numbers:

n = 1, S(1) = 1
n = 3, S(3) = 2
n = 3^2 = 9, S(9) = 3
n = 3 × 5 = 15, S(15) = 4
n = 3^4 = 81, S(81) = 5
n = 3^2 × 5 = 45, S(45) = 6
n = 3^6 = 729, S(729) = 7
n = 3 × 5 × 7 = 105, S(105) = 8
n = 3^2 × 5^2 = 225, S(225) = 9
n = 3^4 × 5 = 405, S(405) = 10
n = 3^10 = 59049, S(59049) = 11
n = 3^2 × 5 × 7 = 315, S(315) = 12
n = 3^12 = 531441, S(531441) = 13
n = 3^6 × 5 = 3645, S(3645) = 14
n = 3^4 × 5^2 = 2025, S(2025) = 15
n= 3^5 × 5 × 7 = 945, S(945) = 16
n = 3^16 = 43046721, S(43046721) = 17
n = 3^2 × 5^2 × 7 = 1575, S(1575) = 18
n = 3^18 = 387420489, S(387420489) = 19
n = 3^4 × 5 × 7 = 2835, S(2835) = 20

OEIS sequence A038547 [ @oeis ] lists the smallest number with exactly n odd divisors. For prime p, n = 3^(p − 1) gives S(n) = p.

3. geoffrounce 1 October 2016 at 1:31 pm

To mark the occasion of publishing 1000 Enigmas with Enigma 364, I thought I would try the first Enigma, published in 1979 .Keep up the good work , Jim

Here is my programme for Enigma 1

```
from collections import defaultdict
d = defaultdict(list)   # for part(a) numbers 1-100
d2  = defaultdict(list) # for part(b) numbers 100-120

# to check seriousness of ages for ages between 1 and 100 and 100 and 120
def chk_index(index):
ser_age = 0
for cnt in range(1, index+1):
subtot = cnt
c = 0
next = 0
while subtot <= index + 1:
c += 1
next = cnt + c
subtot = subtot + next
if subtot == index:
ser_age += 1
if subtot > index:
continue
if cnt == index:
ser_age += 1
return index, ser_age

# Part (a)
# check seriousness of ages for ages between 1 and 100
for n in range(1,101):
i,sa = chk_index(n)
d[sa] += [i]

# print dictionary d
print('Part (a) - serious numbers in range 1 - 100')
print('-------------------------------------------')
print('Seriousness [ Ages ] No of Values')

for k,v in sorted(d.items()):
print(k,v, len(v))
print()

print('Max seriousness of ages 1 - 100 =', max(d))
print()

# PART (b)
# check seriousness of ages for ages between 100 and 120
for n in range(100,121):
i,sa = chk_index(n)
d2[sa] += [i]

# print dictionary d2
print('Part (b) - next highest serious number > 6')
print('------------------------------------------')

print('Seriousness [ Ages ] No of Values')

for k,v in sorted(d2.items()):
print(k,v, len(v))
print()

print('Max seriousness - numbers 101 to 120 =', max(d2))

```

The output of this programme confirms the previously results and shows the ‘seriousness of all ages between 1 and 100:

Part (a) – serious numbers in range 1 – 100
——————————————-
Seriousness [ Ages ] No of Values
1 [1, 2, 4, 8, 16, 32, 64] 7

2 [3, 5, 6, 7, 10, 11, 12, 13, 14, 17, 19, 20, 22, 23, 24, 26, 28, 29, 31, 34, 37, 38, 40, 41, 43, 44, 46, 47, 48, 52, 53, 56, 58, 59, 61, 62, 67, 68, 71, 73, 74, 76, 79, 80, 82, 83, 86, 88, 89, 92, 94, 96, 97] 53

3 [9, 18, 25, 36, 49, 50, 72, 98, 100] 9

4 [15, 21, 27, 30, 33, 35, 39, 42, 51, 54, 55, 57, 60, 65, 66, 69, 70, 77, 78, 84, 85, 87, 91, 93, 95] 25

5  1

6 [45, 63, 75, 90, 99] 5

Max seriousness of ages 1 – 100 = 6 ( for 45, 63, 75, 90, 99 )

Part (b) – next highest serious number > 6
———————————————–
Seriousness [ Ages ] No of Values
2 [101, 103, 104, 106, 107, 109, 112, 113, 116, 118] 10

3  1

4 [102, 108, 110, 111, 114, 115, 119, 120] 8

6  1

8  1

Max seriousness – numbers 101 to 120 = 8 (for 105)

4. geoffrounce 3 October 2016 at 3:04 pm

I amended my programme to find all the components of a serious number

```
# Generic solver for Enigma 1 - "Serious Ages'
# Finds the 'seriousness' of any number entered

def chk_index(index):
print('Components of serious age :',index)
print('---------------------------------')
ser_age = 0

for cnt in range(1, index+1):
subtot = cnt
c = 0; next = 0

while subtot <= index + 1:
c += 1
next = cnt + c
subtot = subtot + next

if subtot == index:
ser_age += 1
a = 1 - 2*cnt
b = ((2*cnt - 1)**2 + 8*index)**0.5

# find no. of terms in addition
nterms = int(1/2*(1- 2*cnt - ((2*(cnt-1)**2 + 8*index)**0.5)))
if b < a: nterms = int(1/2*(a-b))
if b > a: nterms = int(1/2*(a+b))

fs = 's ={0:3d}, 1st term ={1:6d}, no terms ={2:4d}'
print(fs.format(ser_age, cnt, nterms))
show_nums(cnt, nterms)

if subtot > index:
continue

if cnt == index:   # age on its own is a serious age component
ser_age += 1

return ser_age, index

def show_nums(cnt, nterms):
# show components of this number
print('Terms:')
for n in range(1,nterms+1):
nterm = cnt + n - 1
print(nterm, end = ' ')

# show total
lterm = cnt + nterms - 1
sumnt = (cnt + lterm) * n/2
sumnt = int(sumnt)
print('\nSum: ',sumnt, )
print()

# REPEATED USER INPUT
# repeated input of numbers for serious age components

while True:
print()
print('Enter 0 to finish...')

num = int(input("Enter a number: "))
print()
print(chk_index(num))
print('--------------')
if num == 0:
break

'''
Sample usage
------------

Enter 0 to finish...
Enter a number: 105  -   Part (b) of question

Components of serious age : 105
---------------------------------
s =  1, 1st term =     1, no terms =  14
Terms:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Sum:  105

s =  2, 1st term =     6, no terms =  10
Terms:
6 7 8 9 10 11 12 13 14 15
Sum:  105

s =  3, 1st term =    12, no terms =   7
Terms:
12 13 14 15 16 17 18
Sum:  105

s =  4, 1st term =    15, no terms =   6
Terms:
15 16 17 18 19 20
Sum:  105

s =  5, 1st term =    19, no terms =   5
Terms:
19 20 21 22 23
Sum:  105

s =  6, 1st term =    34, no terms =   3
Terms:
34 35 36
Sum:  105

s =  7, 1st term =    52, no terms =   2
Terms:
52 53
Sum:  105

(8, 105)

'''

```
5. geoffrounce 3 October 2016 at 3:30 pm

Hugh commented on powers of 2 having a seriousness of 1.

As powers of 2 can be expressed as 1 * 2 ^ n, they will only have 1 odd number as a divisor, so would have a seriousness of 1, according to Jim’s formula.

I then started looking into numbers with repeated digits with some interesting results.

The programme below looks at the numbers of odd and even divisors of the following numbers with repeated digits :(111111,222222,333333,444444,555555,666666,777777,888888,999999)

The first part of the programme confirms these are all serious numbers, both in terms of Jims’ function and my solver.

The second part of the programme then finds all the odd and even divisors of these numbers, the odd divisors being the ‘serious’ numbers

Where there are total odd or even divisors > 0, these divisors are all multiples of 16 – I guess there must be a reason

```
from enigma import divisors

# Jim's function
def S(n):
return sum(1 for d in divisors(n) if d % 2 == 1)

for nn in (111111,222222,333333,444444,555555,666666,777777,888888,999999):
print( (nn, S(nn)), end = ' ')

# Output
# (111111, 32) (222222, 32) (333333, 48) (444444, 32) (555555, 64)
# (666666, 48) (777777, 48) (888888, 32) (999999, 64)

print(); print()
for n in (111111,222222,333333,444444,555555,666666,777777,888888,999999):
l1 = [ d for d in divisors(n) if d % 2 == 1]  # odd divisors
len1 = len(l1)

l2 = [ d for d in divisors(n) if d % 2 == 0]  # even divisors
len2 = len(l2)

print(n, len1, len2)

# Output
#Number  No of odd   No. of even Seriouness
#        divisors    divisors
#111111     32           0          32
#222222     32           32         32
#333333     48           0          48
#444444     32           64         32
#555555     64           0          64
#666666     48           48         48
#777777     48           0          48
#888888     32           96         32
#999999     64           0          64

```

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