Sisyphus sequence

Revision as of 12:30, 9 June 2023 by Jgrprior (talk | contribs) (Add Python)

The Sisyphus sequence is an infinite sequence of positive integers that was devised in 2022 by Eric Angelini and Carole Dubois.

Sisyphus sequence is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

The first term is 1. Subsequent terms are found by applying the following rule:

  • If the previous term was even, then halve it.
  • If the previous term was odd, then add the smallest prime number that has not yet been added.

1 is odd and so the second term is: 1 + 2 = 3, because 2 is the smallest prime not yet added.

3 is odd and so the third term is: 3 + 3 = 6, because 3 is the smallest prime not yet added.

6 is even and so the fourth term is : 6 ÷ 2 = 3, and so on.

Task

Find and show on this page (in 10 lines of 10 terms), the first 100 terms of the sequence.

What are the 1,000th, 10,000th, 100,000th and 1,000,000th terms of the sequence and, in each case, what is the highest prime needed to reach them?

If it is difficult or impossible for your language or output device to meet all of these requirements, then just do what you reasonably can.

Stretch

What are the 10 millionth and 100 millionth terms and the highest prime needed to reach each one?

By the time the 100 millionth term is reached, which number(s) under 250:

  • Have not yet occurred in the sequence.
  • Have occurred the most times and their number of occurrences.


Extreme stretch

What is the number of the first term to equal 36?

This was originally set as a challenge by Neil Sloane who was worried by its non-appearance and found by Russ Cox.

References


Python

Library: primesieve
from collections import Counter
from itertools import islice
from typing import Iterable
from typing import Iterator
from typing import Tuple
from typing import TypeVar

import primesieve


def primes() -> Iterator[int]:
    it = primesieve.Iterator()
    while True:
        yield it.next_prime()


def sisyphus() -> Iterator[Tuple[int, int]]:
    prime = primes()
    n = 1
    p = 0
    yield n, p

    while True:
        if n % 2:
            p = next(prime)
            n = n + p
        else:
            n = n // 2
        yield n, p


def consume(it: Iterator[Tuple[int, int]], n) -> Tuple[int, int]:
    next(islice(it, n - 1, n - 1), None)
    return next(it)


T = TypeVar("T")


def batched(it: Iterable[T], n: int) -> Iterable[Tuple[T, ...]]:
    _it = iter(it)
    batch = tuple(islice(_it, n))
    while batch:
        yield batch
        batch = tuple(islice(_it, n))


if __name__ == "__main__":
    it = sisyphus()
    first_100 = list(islice(it, 100))
    print("The first 100 members of the Sisyphus sequence are:")
    for row in batched(first_100, 10):
        print("  ".join(str(n).rjust(3) for n, _ in row))

    print("")

    for interval in [10**x for x in range(3, 9)]:
        n, prime = consume(it, interval - (interval // 10))
        print(f"{interval:11,}th number: {n:13,}   highest prime needed: {prime:11,}")

    print("")

    sisyphus_lt_250 = Counter(n for n, _ in islice(sisyphus(), 10**8) if n < 250)
    print("These numbers under 250 do not occur in the first 100,000,000 terms:")
    print(" ", [n for n in range(1, 250) if n not in sisyphus_lt_250])
    print("")

    most_common = sisyphus_lt_250.most_common(1)[0][1]
    print("These numbers under 250 occur the most in the first 100,000,000 terms:")
    print(
        f"  {[n for n, c in sisyphus_lt_250.items() if c == most_common]} "
        f"all occur {most_common} times."
    )
Output:
The first 100 members of the Sisyphus sequence are:
  1    3    6    3    8    4    2    1    8    4
  2    1   12    6    3   16    8    4    2    1
 18    9   28   14    7   30   15   44   22   11
 42   21   58   29   70   35   78   39   86   43
 96   48   24   12    6    3   62   31   92   46
 23   90   45  116   58   29  102   51  130   65
148   74   37  126   63  160   80   40   20   10
  5  106   53  156   78   39  146   73  182   91
204  102   51  178   89  220  110   55  192   96
 48   24   12    6    3  142   71  220  110   55

      1,000th number:           990   highest prime needed:       2,273
     10,000th number:        24,975   highest prime needed:      30,713
    100,000th number:       265,781   highest prime needed:     392,111
  1,000,000th number:     8,820,834   highest prime needed:   4,761,697
 10,000,000th number:    41,369,713   highest prime needed:  55,900,829
100,000,000th number: 1,179,614,168   highest prime needed: 640,692,323

These numbers under 250 do not occur in the first 100,000,000 terms:
  [36, 72, 97, 107, 115, 127, 144, 167, 194, 211, 214, 230, 232]

These numbers under 250 occur the most in the first 100,000,000 terms:
  [28, 14, 7] all occur 7 times.

RPL

This is a very slow version (15 minutes to get the 10,000th term on a HP-50g) , but I'm not sure to have enough memory to generate a large enough sieve to find the millionth term in a reasonable amount of time. Anyway, even the first requirement (displaying 10 lines of 10 items) is out of range with a 22-character screen.

≪ 1 CF
   IF DUP 0 < THEN 1 SF NEG END    @ A negative argument requires the sequence to be stored then displayed
   0 { 1 } → n cnt seq
   ≪ 2 1 
      WHILE 'cnt' INCR n < REPEAT
         IF DUP 2 MOD THEN OVER + SWAP NEXTPRIME SWAP ELSE 2 / END
         IF 1 FS? THEN 'seq' OVER STO+ END
      END
      IF 1 FS? THEN DROP2 seq ELSE SWAP PREVPRIME R→C END
≫ ≫ 'SISYPH' STO
-100 SISYPH
1000 SISYPH
10000 SISYPH
Output:
3: {1 3 6 3 8 4 2 1 8 4 2 1 12 6 3 16 8 4 2 1 18 9 28 14 7 30 15 44 22 11 42 21 58 29 70 35 78 39 86 43 96 48 24 12 6 3 62 31 92 46 23 90 45 116 58 29 102 51 130 65 148 74 37 126 63 160 80 40 20 10 5 106 53 156 78 39 146 73 182 91 204 102 51 178 89 220 110 55 192 96 48 24 12 6 3 142 71 220 110 55 }
2: (990.,2273.)
1: (24975.,30713.)

Wren

Library: Wren-math
Library: Wren-fmt

No option here but to use a sieve as relying on the 'nextPrime' method would be far too slow to achieve the stretch goal in a reasonable time using Wren. Sieve limit found by experimentation.

Extreme stretch not attempted and probably out of the question for Wren.

import "./math" for Int, Nums
import "./fmt" for Fmt

var limit = 1e8
var primes = Int.primeSieve(7 * limit)
var under250 = List.filled(250, 0)
var sisyphus = [1]
under250[1] = 1
var prev = 1
var nextPrimeIndex = 0
var specific = 1000
var count = 1
while (true) {
    var next
    if (prev % 2 == 0) {
        next = prev / 2
    } else {
        next = prev + primes[nextPrimeIndex]
        nextPrimeIndex = nextPrimeIndex + 1
    }
    count = count + 1
    if (count <= 100) sisyphus.add(next)
    if (next < 250) under250[next] = under250[next] + 1
    if (count == 100) {
        System.print("The first 100 members of the Sisyphus sequence are:")
        Fmt.tprint("$3d ", sisyphus, 10)
        System.print()
    } else if (count == specific) {
        var prime = primes[nextPrimeIndex-1]
        Fmt.print("$,13r member is: $,13d and highest prime needed: $,11d", count, next, prime)
        if (count == limit) {
            var notFound = (1..249).where { |i| under250[i] == 0 }.toList
            var max = Nums.max(under250)
            var maxFound = (1..249).where { |i| under250[i] == max }.toList
            Fmt.print("\nThese numbers under 250 do not occur in the first $,d terms:", count)
            Fmt.print("  $n", notFound)
            Fmt.print("\nThese numbers under 250 occur the most in the first $,d terms:", count)
            Fmt.print("  $n all occur $d times.", maxFound, max)         
            return
        }
        specific = 10 * specific
    }
    prev = next
}
Output:
The first 100 members of the Sisyphus sequence are:
  1    3    6    3    8    4    2    1    8    4 
  2    1   12    6    3   16    8    4    2    1 
 18    9   28   14    7   30   15   44   22   11 
 42   21   58   29   70   35   78   39   86   43 
 96   48   24   12    6    3   62   31   92   46 
 23   90   45  116   58   29  102   51  130   65 
148   74   37  126   63  160   80   40   20   10 
  5  106   53  156   78   39  146   73  182   91 
204  102   51  178   89  220  110   55  192   96 
 48   24   12    6    3  142   71  220  110   55 

      1,000th member is:           990 and highest prime needed:       2,273
     10,000th member is:        24,975 and highest prime needed:      30,713
    100,000th member is:       265,781 and highest prime needed:     392,111
  1,000,000th member is:     8,820,834 and highest prime needed:   4,761,697
 10,000,000th member is:    41,369,713 and highest prime needed:  55,900,829
100,000,000th member is: 1,179,614,168 and highest prime needed: 640,692,323

These numbers under 250 do not occur in the first 100,000,000 terms:
  [36, 72, 97, 107, 115, 127, 144, 167, 194, 211, 214, 230, 232]

These numbers under 250 occur the most in the first 100,000,000 terms:
  [7, 14, 28] all occur 7 times.