the problem is as follows, we get a positive integer, we keep modifying it until we get 1, if the integer is pair we divide by 2, if impair we multiply by 3 and add 1, i was able to solve this using a while loop, but it seems i can't do it using recursion
here's the code:
def syracus(N):
s = [N]
if N==1:
return s
else:
if N%2==0:
s.append(syracus(N/2))
return s
return syracus(N/2)
elif N%2==1:
s.append(syracus(3*N+1))
return s
return syracus(3*N+1)
here's the output
[15, [46, [23, [70, [35, [106, [53, [160, [80, [40, [20, [10, [5, [16, [8, [4, [2, [1]]]]]]]]]]]]]]]]]]
The reason you get nested lists is that you append the result from recursion. But that recursive call returns a list, so you're appending a list to a list, which introduces the nesting. Instead, use extend
.
There are a few other issues:
/
anymore for integer division, but //
, otherwise you get results with float data type numbers instead of int data type.return s
will never get executed. Remove it (at both occurrences).N%2==1
will always evaluate to True when execution gets there. This is the only other possibility when the condition N%2==0
is False, so just use else
instead of that elif
.return s
at three places. It is easy to move that out of any condition, so that it always gets executed, no matter what the case is.s
is obscure. It suggests a string data type, but it actually is a list. I would suggest a different name, like lst
.n
instead of N
So, with those corrections we get:
def syracus(n):
lst = [n]
if n > 1:
if n % 2 == 0:
lst.extend(syracus(n // 2))
else:
lst.extend(syracus(3 * n + 1))
return lst
print(syracus(15))
This is however creating a new list for every call of syracus
. You could avoid this by first getting the list from the recursive call, and then appending N
to it. At the end you'll need to reverse that result:
def syracus(n):
def recur(n):
if n == 1:
lst = []
elif n % 2 == 0:
lst = syracus(n // 2)
else:
lst = syracus(3 * n + 1)
lst.append(n)
return lst
return recur(n)[::-1]
print(syracus(15))
It is however more pythonic to use a generator for this, and that way you avoid creating a list at all during the algorithm. It is then up to the caller to create the list, if that is desired.
def syracus(n):
yield n
if n > 1:
if n % 2 == 0:
yield from syracus(n // 2)
else:
yield from syracus(3 * n + 1)
print(list(syracus(15)))