Repeatedly calling a function until the result falls within a tolerance - python-2.7

Write a function iterate with the following arguments:
f: a function
start: a numeric starting value
tol: a numerical tolerance (default value 1e-6)
itmax: a maximum number of iterations (default value 1000)
Starting from the initial value, your function should keep repeating calls to the function (e.g. y=f(y)) until the absolute value of f(y)-y is less than tol or the number of iterations is equal to itmax. For example, if start=1.01, f is math.sqrt, and tol=1e-4, the sequence would look like this:
On step 6, the absolute value of the difference is less than the tolerance (1e-4), so the function returns [6, 1.0000777399813863].
Tests (should all be True):
def approx_equal(x,y,tol=1e-8):
"""helper function: test whether all elements of
x and y are equal within tolerance
"""
if len(x) != len(y):
return(False)
for i in range(len(x)):
if (abs(x[i]-y[i])>tol):
return(False)
return(True)
def disc_logist(x):
"""discrete logistic function"""
return(1.5*x*(1-x))
print(approx_equal(iterate(disc_logist,0.5),[15, 0.33333433255312184]))
print(approx_equal(iterate(disc_logist,0.5,tol=1e-8),[22, 0.33333334113969143]))
def half(x):
"""just what it says"""
return(x/2)
print(approx_equal(iterate(half,1000),[29, 9.313225746154785e-07]))
import math
print(approx_equal(iterate(math.sqrt,1.01,tol=1e-4),[6, 1.0000777399813863]))
print(approx_equal(iterate(math.cos,0),[34, 0.7390855263619245]))
print(approx_equal(iterate(math.cos,0,tol=1e-8),[46, 0.7390851366465718]))
print(approx_equal(iterate(math.cos,0,itmax=5),[5, 0.7013687736227565]))
This is what i have so far:
def iterate(f,start,tol=1e-6,itmax=1000):
"""function should keep repeating calls to the function until the absolute
value of f(y)-y is less than tol or number of iterations is equal to itmax
:f: a function
:start: a numeric starting value
:tol: a numerical tolerance
:itmax: a maximum number of iterations"""
import math
y=start
for i in range(itmax):
y_2=f(y)
if abs(y_2 - y) <tol:
return y
else:
y=y_2

The answer for your immediate problem is to return not a single number, but a two element list containing first the number of iterations and second the answer - note that the instructions say (my emphasis):
On step 6, the absolute value of the difference is less than the tolerance (1e-4), so the function returns [6, 1.0000777399813863].
def iterate(f,start,tol=1e-6,itmax=1000):
"""function should keep repeating calls to the function until the absolute
value of f(y)-y is less than tol or number of iterations is equal to itmax
:f: a function
:start: a numeric starting value
:tol: a numerical tolerance
:itmax: a maximum number of iterations"""
import math
y=start
for i in range(itmax):
y_2=f(y)
if abs(y_2 - y) <tol:
# Return the successful value - the last result, not the last input
return [i, y_2]
else:
y=y_2
# Return the next answer
return [itmax, f(y)]
This will get approx_equal() working, but I haven't tested it completely to see if all the results match up.

Related

recursive binary search using python 2.7

Wrote this code in comp sci class and I cant get it to work, it always returns as false every time I run it. Its supposed to be a recursive binary search method... Any idea why it only returns false?
arr = [1,10,12,15,16,122,132,143,155]
def binarysearch(arr,num):
arr2 = []
if (len(arr) == 1):
if (arr[0] == num):
return 1
else:
return 0
for i in range (len(arr)/2):
arr2.append(0)
if (arr[len(arr)/2]>num):
for x in range (len(arr)/2,len(arr)):
arr2[x-(len(arr)/2)]=arr[x]
return binarysearch(arr2,num)
if(arr[len(arr)/2]<num):
for x in range(0, len(arr) / 2 ):
arr2[x] = arr[x]
return binarysearch(arr2, num)
num = raw_input("put number to check here please: ")
if(binarysearch(arr,num)==1):
print "true"
else:
print "false"
You're doing vastly more work than you need to on things that Python can handle for you, and the complexity is masking your problems.
After your base case, you have two if statements, that don't cover the full range—you've overlooked the possibility of equality. Use if/else and adjust the ranges being copied accordingly.
Don't create a new array and copy stuff, use Python's subranges.
Don't keep repeating the same division operation throughout your program, do it once and store the result.
If you want to print True/False, why not just return that rather than encoding the outcome as 0/1 and then decoding it to do the print?
Recall that raw_input returns a string, you'll need to convert it to int.
The end result of all those revisions would be:
def binary_search(arr,num):
if (len(arr) == 1):
return (arr[0] == num)
mid = len(arr) / 2
if (arr[mid] > num):
return binary_search(arr[:mid], num)
else:
return binary_search(arr[mid:], num)
num = int(raw_input("put number to check here please: "))
print binary_search(arr,num)

Write a function that calculates the sum of all values in a list of integers that are both positive and even

The function should accept a single list as a parameter. The function should return an integer value as the result of calculation. If there are no positive and even integer values in the list, your function should return 0.
My current code:
def main():
print (sum_positive_even([1,2,3,4,5]))
print (sum_positive_even([-1,-2,-3,-4,-5]))
print (sum_positive_even([1,3,5,7,9]))
def sum_positive_even(list):
for num in list:
if num < 0:
list.remove(num)
for num in list:
if num % 2 == 1:
list.remove(num)
result = sum(list)
return result
main()
The output should be like:
6
0
0
I'm confused where I should put the 'return 0'.
Thanks TA!
Deleting from a list while you iterate over it is a Bad Idea - it's very easy to get hard-to-track-down bugs that way. Much better would be to build a new list of the items you want to keep. You don't need a special case of returning 0; the general approach should be able to handle that.
Also, it's better not to use list as a variable name in Python, because that's the name of a built-in.
A modification of your approach:
def sum_positive_even(lst):
to_keep = []
for num in lst:
if num > 0 and num % 2 == 0:
to_keep.append(num)
return sum(to_keep)
Since the sum of an empty list is 0, this covers the case where there are no positive even numbers.

Having a generator expression as an input argument in Python

How can I interact with the values of a generator expression? For instance:
def sumValues(*args):
# compute the sum of values
sumValues(abs(x) for x in range(0,10))
When the range is known (e.g., we know the range is [0,10)), we can put a for loop, but what if the range is unknown?
it depend on how you want your function to be called, if you want to call it with list, generator, or more generally a iterable (anything that can be used in a for-loop) and imitate the behavior of the build-in sum then
def my_sum(iterable):
total = 0
for x in iterable:
total += x
return total
and use like
my_sum(range(10))
my_sum(abs(x) for x in range(0,10))
my_sum([1,2,3,4,5,6])
if you want to imitate the behavior of max and use it as above and also like my_sum(1,2), my_sum(1,2,3), my_sum(1,2,3,4,5,6,7), etc. then
def my_sum(*argv):
total = 0
values = None
if len(argv) == 1:
values = argv[0]
else:
values = argv
for x in values:
total += x
return total
I figured. Here's the answer:
def sumValues(*args):
# compute the sum of values
total = 0
for item in args[0]:
total += item
return total
print(sumValues(abs(x) for x in range(0,10)))
[output] => 45

No Error with my code, function returns no result

I've made this function for a HW but every time I run it python returns no result,
What am I doing wrong?.
mult
def mult( n, m ):
""" input two strings
output the product of those numbers
"""
if n==0 or m==0:
return
elif m<0:
m=abs(m)
m+m
mult(n-1,m)
return
else:
m+m
mult(n-1,m)
return
In Python return is a transtive verb. It is sort of like the verbs "say" or "go"
say what? go where? return what?
You seem to think of return as something which simply returns execution flow to the caller (perhaps returning the value of the last calculated expression) but it doesn't work that way.
def add(x,y):
return x+y
returns the sum of x and y
def add(x,y):
x+y
return
returns nothing (which is called None in Python). It computes the sum of x and y but then discards the result.
Think about return as "give to the guy who called me".
def four():
return 4
print("four is ", four()) # four is 4
So, if I need a four, I can call my handy new function: print("four is ", four()). print() calls four() to get a result. If I define four() with an empty return statement, it won't give me anything.
def four():
4
return
print("four is ", four()) # four is None
return with recursion is the same "giving to the caller" principle, only more complicated.
def add(n,m):
"""add two integers together. The second integer
cannot be negative"""
if m == 0:
return n
else:
return 1 + add(n, m-1)
For simplicity's sake, the second number cannot be less than 0. Now, think about the algorithm, and how the return <something> affects it. If m is zero, then n + 0 == n, so we only need to return n. Otherwise, we're adding one to our eventual answer and subtracting one from m.
add(2, 3) becomes
1 + add(2, 2)(the return means "give to the guy who called me" which is add(2, )), which becomes 1 + 1 + add(2, 1), which becomes 1 + 1 + 1 + add(2, 0), and when we see zero in that second spot, we just replace it with the first number, so it becomes 1 + 1 + 1 + 2 which is 5.

combination a of 6a +9b+20c =n when n is range (0, 100)

I want to write a program sort like solving Diophantine Equation:
That is able to identify any number from 0 to 100 that is exactly with combination of 6a+9b+20C, when a, b, c are all non-negative integer between 0 to 10.
And also I want to write a program that is able to identify any number from 0 to 100 that is not exactly with combination of 6a+9b+20C.
I try with following with problem 2:
for num in range(0, 100):
prime = True
for i in range(3, 20, 3):
if (num%i==0):
prime=False
if prime:
print 'Largest number that cannot be bought in exact quantity', num
I can only get as far as this.
This function will give you a dictionary output which will contain all the numbers that are not the combination and the number which is the combination of your equation :-
def inputNo( a, b, c ):
result = {"isComb":[], "notComb":[]}
for i in range(1,100):
if ((6*a)+(9*b)+(20*c) == i ):
result['isComb'].append(i)
else:
result['notComb'].append(i)
return result