Home > Mobile >  PYTHON: I am a high school math and programming enthusiast attempting to solve the 3n 1 problem and
PYTHON: I am a high school math and programming enthusiast attempting to solve the 3n 1 problem and

Time:04-03

I've been trying to work on solving or at least understanding the 3n 1 problem. The program tries numbers 1 by 1 until they reach the infamous 4-->2-->1 loop. And then tries the next number. The goal of the program is to do this until I reach a number that does not find this inevitable loop. If possible.

I keep having the same error. When I reach number 996, I end up with the error:

"RecursionError: maximum recursion depth exceeded while calling a Python object"

on=True
import time
x=0
def loop():
    global x
    x=x 1
    time.sleep(0.01)
    print("new: " str(x))
    n=x
    while on==True:
        if (n%2==0):
            n=n/2
        else:
            n=3*n 1
        print(n)
        if n==1:
            loop()
loop()

This is my code. I have tried importing os and using the os.system('cls') command which should work since I'm on windows but it hasn't even functioned.

Even only printing the new numbers rather than all the numbers makes it stop at the same number. Which tells me it's not just a character limit.

CodePudding user response:

The problem is that the variable on remains True all the time; it never changes. So the while on==True: keeps going on forever, and your loop() function keeps calling itself forever. But since your computer has limited resources, the stack in which all these recursive function calls take place is exhausted at some stage (a veritable stack overflow!). To avoid that, you either introduce a break statement (which has the effect of ending the loop) or a line that flips the value of on to False. If you go for break, you don't need the on variable at all and can simply change the loop condition to the more conventional while True:.

CodePudding user response:

This sequence is known as the Collatz conjecture.

There is no termination condition for calling loop() recursively. Below is a refactoring with a termination condition and removal of the global variable. It will count the number of operations needed to reach 1 and print out the maximum number of operations so far.

import functools
import sys

# Increase recursion limit so code runs longer
sys.setrecursionlimit(2000)

# Least recently used cache tracks number of loops needed for common results.
# For example, once 4-2-1 is calculated with 2 recursions, loop(4) will just
# return 2 without the extra recursions.  Code runs faster.
@functools.lru_cache(maxsize=500)
def loop(n, loops=0):
    if n == 1:  # termination condition
        return loops
    if n % 2:
        return loop(3 * n   1, loops   1)
    else:
        return loop(n // 2, loops   1)

n = 1
max_loops = -1
while True:
    loops = loop(n)
    if loops > max_loops:  # only print deeper recursions
        print(f'{n=} {loops=}')
        max_loops = loops
    n  = 1

Output after running for a while:

n=1 loops=0
n=2 loops=1
n=3 loops=7
n=6 loops=8
n=7 loops=16
n=9 loops=19
n=18 loops=20
n=25 loops=23
n=27 loops=111
n=54 loops=112
n=73 loops=115
n=97 loops=118
n=129 loops=121
n=171 loops=124
n=231 loops=127
n=313 loops=130
n=327 loops=143
n=649 loops=144
n=703 loops=170
n=871 loops=178
n=1161 loops=181
n=2223 loops=182
n=2463 loops=208
n=2919 loops=216
n=3711 loops=237
n=6171 loops=261
n=10971 loops=267
n=13255 loops=275
n=17647 loops=278
n=23529 loops=281
n=26623 loops=307
n=34239 loops=310
n=35655 loops=323
n=52527 loops=339
n=77031 loops=350
n=106239 loops=353
n=142587 loops=374
n=156159 loops=382
n=216367 loops=385
n=230631 loops=442
n=410011 loops=448
n=511935 loops=469
n=626331 loops=508
n=837799 loops=524
n=1117065 loops=527
n=1501353 loops=530
n=1723519 loops=556
n=2298025 loops=559
n=3064033 loops=562
n=3542887 loops=583
n=3732423 loops=596
n=5649499 loops=612
n=6649279 loops=664
n=8400511 loops=685
n=11200681 loops=688
  • Related