Hofstadter-Conway $10,000 sequence

From Rosetta Code
Revision as of 08:21, 9 March 2010 by rosettacode>Paddy3118 (New task and Python solution.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Task
Hofstadter-Conway $10,000 sequence
You are encouraged to solve this task according to the task description, using any language you may know.

The definition of the series is colloquially described as:

  • Starting with the list [1,1],
  • Take the last number in the list so far: 1, I'll call it x.
  • Count forward x places from the beginning of the list to find the first number to add (1)
  • Count backward x places from the end of the list to find the second number to add (1)
  • Add the two indexed numbers from the list and the result becomes the next number in the list (1+1)
  • This would then produce [1,1,2] where 2 is the third member of the series.

Note that indexing for the description above starts from alternately the left and right ends of the list and starts from an index of one.

A less wordy description of the series is:

   a(1)=a(2)=1
   a(n)=a(a(n-1))+a(n-a(n-1))

The sequence begins:

   1, 1, 2, 2, 3, 4, 4, 4, 5, ...

Interesting features of the sequence are that:

  • a(n)/n tends to 0.5 as n grows towards infinity.
  • a(n)/n where n is a power of 2 is 0.5
  • For n>4 the maximal value of a(n)/n between successive powers of 2 decreases.

The sequence is so named because John Conway offered a prize of $10,000 to the first person who could find the first position, p in the series where

   |a(n)/n| < 0.55 for all n >= p.

It was later found that Hofstadter had also done prior work on the series.

The 'prize' was won quite quickly by Dr. Colin L. Mallows who found that n = 3,173,375,556.

The task is to:

  1. Create a routine to generate members of the Hofstadter-Conway $10,000 sequence.
  2. Use it to show the maxima between successive powers of two up to 2**20

Python

Note how we allow for Pythons zero based indexing: <lang python>from __future__ import print_function, division

def hc10000(lst):

   Modifies lst in-place, adding successive terms of the sequence
   lst should start as [None, 1, 1] to allow for zero-based indexing
   Doctest:
       >>> lst = [None,1,1]
       >>> hc10000(lst); lst
       [None, 1, 1, 2]
       >>> hc10000(lst); lst
       [None, 1, 1, 2, 2]
       >>> hc10000(lst); lst
       [None, 1, 1, 2, 2, 3]
       >>> hc10000(lst); lst
       [None, 1, 1, 2, 2, 3, 4]
       >>> 
   
   last = lst[-1]
   lst.append(lst[last] + lst[-last])</lang>

Finding the maxima: <lang python>def maxbetweenpower2(nmax=2**20):

   power2, maxima, lst = 4, [0.5], [None,1,1]
   for n in range(2,nmax):
       last = lst[-1]
       m = last/n
       if maxima[-1] < m:
           maxima[-1] = m
       if n==power2:
           power2 *= 2
           maxima.append(0.5)
       hc10000(lst)  # Quicker: lst.append(lst[last] + lst[-last])
   return maxima

print (' '.join('%5.3f' % i for i in maxbetweenpower2(nmax=2**20)))<lang>

Sample output:

0.667 0.667 0.636 0.609 0.591 0.576 0.567 0.559 0.555 0.550 0.547 0.544 0.542 0.540 0.539 0.537 0.536 0.535 0.534