Splitting a range of numbers up recursively with Python - python

I would like to write a recursive function in Python. I have written one but it doesn't work correctly.
I have a range of numbers from 1 to 1000 and I want cut it into two parts 1 to 500 and 501 to 1000. Then I want to do this recursively until there are only 20 numbers in each part.
Here is my attempt:
mw = range(1,1000)
def cuter(mw):
if len(mw)<20:
return False
else:
cut=int(len(mw)/2)
number.append(mw[0])
number.append(cut)
number.append(mw[-1])
return cuter(mw)
cuter(mw)

Try something like this, where seq is a list with the range of numbers:
def cutter(seq):
n = len(seq)
if n <= 20:
# here the recursion stops, do your stuff with the sequence
return
a = cutter(seq[:n/2])
b = cutter(seq[n/2:])
# combine the answer from both subsequences
return

Related

Breaking an iterative function in Python before a condition turns False

This is for a school assignment.
I have been tasked to define a function determining the largest square pyramidal number up to a given integer(argument). For some background, these are square pyramidal numbers:
1 = 1^2
5 = 1^2+2^2
14 = 1^2+2^2+3^2
So for a function and parameter largest_square_pyramidal_num(15), the function should return 14, because that's the largest number within the domain of the argument.
I get the idea. And here's my code:
def largest_square_pyramidal_num(n):
sum = 0
i = 0
while sum < n:
sum += i**2
i += 1
return sum
Logically to me, it seemed nice and rosy until I realised it doesn't stop when it's supposed to. When n = 15, sum = 14, sum < n, so the code adds one more round of i**2, and n is exceeded. I've been cracking my head over how to stop the iteration before the condition sum < n turns false, including an attempt at break and continue:
def largest_square_pyramidal_num(n):
sum = 0
for i in range(n+1):
sum += i**2
if sum >= n:
break
else:
continue
return sum
Only to realise it doesn't make any difference.
Can someone give me any advice? Where is my logical lapse? Greatly appreciated!
You can do the following:
def largest_pyr(x):
pyr=[sum([i**2 for i in range(1,k+1)]) for k in range(int(x**0.5)+1)]
pyr=[i for i in pyr if i<=x]
return pyr[-1]
>>>largest_pyr(15)
14
>>> largest_pyr(150)
140
>>> largest_pyr(1500)
1496
>>> largest_pyr(15000)
14910
>>> largest_pyr(150000)
149226
Let me start by saying that continue in the second code piece is redundant. This instruction is used for scenario when you don't want the code in for loop to continue but rather to start a new iteration (in your case there are not more instructions in the loop body).
For example, let's print every number from 1 to 100, but skip those ending with 0:
for i in range(1, 100 + 1):
if i % 10 != 0:
print(i)
for i in range(1, 100 + 1):
if i % 10 == 0:
# i don't want to continue executing the body of for loop,
# get me to the next iteration
continue
print(i)
The first example is to accept all "good" numbers while the second is rather to exclude the "bad" numbers. IMHO, continue is a good way to get rid of some "unnecessary" elements in the container rather than writing an if (your code inside if becomes extra-indented, which worsens readability for bigger functions).
As for your first piece, let's think about it for a while. You while loop terminates when the piramid number is greater or equal than n. And that is not what you really want (yes, you may end up with a piramid number which is equal to n, but it is not always the case).
What I like to suggest is to generate a pyramid number until in exceedes n and then take a step back by removing an extra term:
def largest_square_pyramidal_num(n):
result = 0
i = 0
while result <= n:
i += 1
result += i**2
result -= i ** 2
return result
2 things to note:
don't use sum as a name for the variable (it might confuse people with built-in sum() function)
I swapped increment and result updating in the loop body (such that i is up-to-date when the while loop terminates)
So the function reads like this: keep adding terms until we take too much and go 1 step back.
Hope that makes some sense.
Cheers :)

How to modify this Python function to use recursion

I have a simple function that breaks a number such as 54 and returns the sum of those two number (i.e. 9). I am also studying recursion, I am wondering if the code below meets the criteria. Why? or Why Not?. If not how can I solve this simple problem using the recursion paradigm?
def sumnum(n):
n = str(n)
a = []
for i in n:
a.append(i)
sum(int(n) for n in a)
sumnum(54)
9
The code you have used is not recursion. Recursion has two main characteristics: the base case, and the recursion.
Now, lets break down you your problem:
Base case:
Say we have the number smaller than 10. Then we would return the number. Let's keep it as our base case.
Recursion:
If we had a number ...xyz (x, y and z as digits), we would take the last digit, plus the last digit of the number left, until we have a number smaller than 10.
Code:
def sumnum (n):
if n < 10:
return n
return n % 10 + sumnum(n // 10)

What would be the best answer for this Fibonacci excercise in Python?

What's the best answer for this Fibonacci exercise in Python?
http://www.scipy-lectures.org/intro/language/functions.html#exercises
Exercise: Fibonacci sequence
Write a function that displays the n first terms of the Fibonacci
sequence, defined by:
u0 = 1; u1 = 1
u(n+2) = u(n+1) + un
If this were simply asking a Fibonacci code, I would write like this:
def fibo_R(n):
if n == 1 or n == 2:
return 1
return fibo_R(n-1) + fibo_R(n-2)
print(fibo_R(6))
... However, in this exercise, the initial conditions are both 1 and 1, and the calculation is going towards the positive direction (+). I don't know how to set the end condition. I've searched for an answer, but I couldn't find any. How would you answer this?
Note that u_(n+2) = u_(n+1) + u_n is equivalent to u_n = u_(n-1) + u_(n-2), i.e. your previous code will still apply. Fibonacci numbers are by definition defined in terms of their predecessors, no matter how you phrase the problem.
A good approach to solve this is to define a generator which produces the elements of the Fibonacci sequence on demand:
def fibonacci():
i = 1
j = 1
while True:
yield i
x = i + j
i = j
j = x
You can then take the first N items of the generator via e.g. itertools.islice, or you use enumerate to keep track of how many numbers you saw:
for i, x in enumerate(fibonacci()):
if i > n:
break
print x
Having a generator means that you can use the same code for solving many different problems (and quite efficiently though), such as:
getting the n'th fibonacci number
getting the first n fibonacci numbers
getting all fibonacci numbers satisfying some predicate (e.g. all fibonacci numbers lower than 100)
The best way to calculate a fibonacci sequence is by simply starting at the beginning and looping until you have calculated the n-th number. Recursion produces way too many method calls since you are calculating the same numbers over and over again.
This function calculates the first n fibonacci numbers, stores them in a list and then prints them out:
def fibonacci(n):
array = [1]
a = 1
b = 1
if n == 1:
print array
for i in range(n-1):
fib = a + b
a = b
b = fib
array.append(fib)
print array
If you want a super memory-efficient solution, use a generator that only produces the next number on demand:
def fib_generator():
e1, e2 = 0, 1
while True:
e1,e2 = e2, e1+e2
yield e1
f = fib_generator()
print(next(f))
print(next(f))
print(next(f))
## dump the rest with a for-loop
for i in range(3, 50):
print(next(f))
The recursive solution is the most elegant, but it is slow. Keiwan's loop is the fastest for a large number of elements.
Yes, definitely no globals as correctly observed by DSM. Thanks!
An alternative recursive just to show that things can be done in slightly different ways:
def fib2(n): return n if n < 2 else fib2( n - 1 ) + fib2( n - 2 )

How to convert a collection of numbers into other base

Again firstly I am sorry because keep asking the same question.I am new to python programming. I am now trying to build a program which convert every element in a list of numbers of base 10 into its base 4. For example here, say i have numbers from 0 to 20 or more, I want to convert every number starting from 0 to numbers of base 4. The result should be like this
[[0,0],[0,1],...[1,1,0]
for numbers starting from 0 to 20. For the code,here is what I wrote so far
for n in range(21):
def base(n,b):
result = []
while n > 0:
result.insert(0, n % b)
n = n // b
return result
print(base(n, 4))
For the result I got only for number 20 which is
[1,1,0]
Did I missed something here or there is another option to make it work?
Thank you for the answer
The issue is that you are defining the function inside the loop body, and only call it once. The structure you actually need is
<define the function>
for n in range(21):
print(base(n, 4))
The results will print out, but each one on a separate line. To create a list of the results you should replace the two lines of the loop with a single line that prints a list of all results, like
print([base(n, 4) for n in range(21)])
The problem is that you're defining the function inside the loop. What you want to do is define the function first, then construct your desired list:
def base(n,b):
result = []
while n > 0:
result.insert(0, n % b)
n = n // b
return result
print [base(n, 4) for n in range(21)]
(See this article if you're new to list comprehensions.)
If you want all the numbers, then indent your print statement, so that it's part of the loop.
If you want these as strings, then convert the digits to characters and concatenate them.
I've done both here:
def base(n, b):
result = []
while n > 0:
result.insert(0, n % b)
n = n / b
return result
for decimal in range(21):
print(''.join(str(digit) for digit in base(decimal, 4)))
You can manually compute the base of a number by doing something like this:
from math import log
from math import floor
def n_to_base(n, b):
num = n
lead_idx = floor(log(num, b))
b_rep = int(10**lead_idx)
b_rep = str(b_rep)
rep = 0
for i in range(len(b_rep)-1, -1, -1):
coeff = floor(num/(b**i))
rep += int(coeff*(10**i))
num -= int(coeff*(b**i))
return rep

How can I Improve this Code, using While Loop?

Create a function addNumbers(x) that takes a number as an argument and adds all the integers between 1 and the number (inclusive) and returns the total number.
Examples :
addNumbers(10)
55
addNumbers(1)
1
So this is a question, I have done using while loop , and it worked fine. But I am not satisfied with my code, I also did this problem using for loop and that's okay for me, but I want to know what could be the best way to improve dis code using while loop.
def addNumbers(num):
total = 1
i = 1
while i < num:
i += 1
total += i
return total
print addNumbers(10)
And here is my for loop answer :
def addNumbers(num):
my_list = list(range(num+1) )
for i in my_list:
my_list.append(i)
return sum(my_list)
If you want an O(1) algorithm that isn't brute-force, you can use Gauss's method:
def sum_numbers(n):
return (n+1)*n//2
Usually SO isn't the place for such questions, but anyway..
You can use sum() and range(). range() will return a list of numbers from 0 to n and sum will, well, sum it.
def sumNumbers(n):
return sum(range(n+1))
EDIT: And using while loop:
def sumNumbers(n):
i = 0
sum = 0
while i <= n:
sum += i
i += 1
return sum
Make use of numpy's sum routine and a generator like so,
import numpy as np
maxNumber = 10
sumOfNumbers = np.sum([(x) for x in xrange(1, maxNumber+1)])
print sumOfNumbers
The generator gives you the list of numbers & the routine adds them for you.

Categories

Resources