While Loop true and false for approximation of roots - python

I'm a bit new to programming, and I'm trying to create a root-approximating code. Namely, I'm doing something similar to Newton's method in calculus. The idea is, I'm going to input in a big value, subtract until I know I've passed the root, and then add a smaller quantity until I've passed the root, and iterate until I'm in some comfortable error region.
Here's some pseudo code:
def approx(a,b,i):
while ((1/2)**i) >= (1/2)**10:
while (another function is true):
modify values, record root = r
while (the same function above is false):
modify values, record root = r
return approx(a,b,i+1)
return(a,b,r)
This does not seem to work in Python, so I was wondering if anyone could point me in the correct direction.
Edit: included my actual code:
from fractions import *
from math import sqrt
from math import fabs
def pweight(c,d):
if d > c:
return pweight(d,c)
else:
return [c+d,c,d]
def eweight(a,b):
if a == b:
return [a]
elif b > a:
return eweight(b,a)
else:
return [b] + eweight(a-b,b)
def weight(a,b,c,d):
if a*b/2 > c*d:
print("No Embedding Exists")
return (False)
else:
return (True, [c+d]+sorted((pweight(c,d) + eweight(a,b))[1:], reverse=True))
def wgt(a,b,c,d):
return ([c+d]+sorted((pweight(c,d) + eweight(a,b))[1:], reverse=True))
def red(a,i,k):
d=a[0]-a[1]-a[2]-a[3]
if any(item < 0 for item in a[1:]):
# print ("No Embedding Exists")
return (False, i)
elif d >= 0:
# print ("Embedding Exists! How many iterations?")
# print(i)
return (True, i)
elif d<0:
a=[a[0]+d,a[1]+d,a[2]+d,a[3]+d]+a[4:]
a=[a[0]]+sorted(a[1:],reverse=True)
k.append(a)
i=i+1
return red(a,i,k)
def works(a,b):
L = sqrt(a/(2*b))
w = weight(1,a,L,L*b)
return w[0] and red(w[1],0,[])
def inf(a,b,i):
while ((1/2)**(i+1)) >= (1/2)**(10)):
while works(a,b):
a = a - (1/2)**i
L = sqrt(a/(2*b))
while not works(a,b):
a = a + (1/2)**(i+1)
L = sqrt(a/(2*b))
return inf(a,b,i+1)
return (a,b,L)
I want to input in "inf(9,1,0)" and have this code return something close to (255/32,1,sqrt(255/64)). The main problem is the "while works(a,b):" and "while not works(a,b):" in the function "inf(a,b,i)." I want the function to alternate between the "while works" and "while not works" until i=9.
Any sort of general idea would be appreciated (namely, how do you do some sort of alternating function within a while loop).

If you want to alternate between them, don't put them each in their own while loops, put
while i < 9:
if works(a, b):
do something
if not works(a, b):
do something else
And whatever you test in your while conditions needs to be something that changes somewhere in the loop. Otherwise you'll get an infinite loop.

Related

Return immediately for recursive calls

Problem Statement:
You are given an integer array nums. You are initially positioned at the array's first index, and each element in the array represents your maximum jump length at that position. Return true if you can reach the last index, or false otherwise.
How can I change my code so that it returns immediately when I have found a path that works for this problem instead of going through all the recursive calls that I have made previously
def canJump(self, nums: List[int]) -> bool:
solve = [False]
def backtrack(i):
if solve[0] == True:
return
if i == len(nums)-1:
solve[0] = True
return
if i >= len(nums) or nums[i] == 0:
return
for x in range(1, nums[i]+1):
backtrack(i+x)
backtrack(0)
return solve[0]
General Form of a Recursive Function
The general form of a recursive function has two mutually exclusive types of conditions that can be met on each iteration of the recursion. These are either:
terminal conditions, or
non-terminal conditions.
Both types of condition contain a return statement.
Terminal Conditions
The return statement in terminal conditions typically takes the form return <value>.
The solution to the problem you are trying to solve requires two possible terminal conditions:
The case where you know you can reach the last index. return True
The case where you know you can NOT reach the last index. return False
Non-Terminal Conditions
The non-terminal condition will occur on iterations where neither of the terminal cases are met. In this situation, you will call the recursive function and return what it returns.
This answer covers terminal and non-terminal conditions in more detail.
Example
Consider a recursive function that sums the numbers of an array.
def sum(position, array, end):
if(position == end): # terminal condition
return 0
else: # non-terminal condition
return array[position] + sum(position+1, array, end)
Another Example
Depending on any constraints to your problem that I might have missed, a solution might be the following:
def jump(current_position, nums, finish_line):
"""
greedy algorithm:
choose the next position with the largest sum of (jump_range + index)
"""
jump_range = nums[current_position]
choice = current_position + jump_range
if(jump_range == 0): # terminal condition
return False
if(choice >= finish_line): # terminal condition
return True
else: # non-terminal condition
utility = 0
for next_position in range(current_position+1, jump_range+1):
next_jump_range = nums[next_position]
if(utility <= next_position + next_jump_range):
utility = next_position + next_jump_range
choice = next_position
return jump(choice, nums, finish_line)
input1 = [2,0,0,10,3]
input2 = [2,3,0,10,3]
current_position = 0
finish_line = len(input1)
print(jump(0, input1, finish_line)) # False
finish_line = len(input2)
print(jump(0, input2, finish_line)) # True
The most noteworthy difference from your solution is that return statements always return a value.
How can I change my code so that it returns immediately when I have found a path that works for this problem instead of going through all the recursive calls that I have made previously
One particularly straightforward way is to throw an exception, which will immediately unwind the stack.
def can_jump(nums: list[int]) -> bool:
if not nums:
return False
class _Success(Exception):
pass
def backtrack(i):
if i >= len(nums):
return
if i == len(nums) - 1:
raise _Success()
for x in range(1, nums[i] + 1):
backtrack(i + x)
try:
backtrack(0)
return False
except _Success:
return True
We create a local exception type called _Success that the backtracking search can throw to indicate that it found a solution.
If it never finds a solution, the backtrack function will simply return and the return False line will run. Otherwise, it will raise _Success() and then the return True line will run.

Function would not return value, instead it returns "None"

Please help me look at this piece of code which was supposed to calculate the greatest common division between two numbers (a, b). The problem I'm having is that the program would not return c as expected, instead it return None. But when I use a print statement, it prints out the value of c.
This is my code:
def gcd(a, b):
if a == 0:
return b
elif b == 0:
return a
elif a > b:
big, small = a, b
else:
big, small = b, a
c = big % small
if c == 0:
print(small)
return small
gcd(small, c)
print(gcd(1071, 462))
Thanks guys.
Python implicitly returns None when no explicit return is encountered and the function body ends.
In your case if it passes through all other cases it just hits:
gcd(small, c)
return None # you haven't put that in explicitly but that's how Python processes it
So you probably just need to change the last line to:
return gcd(small, c)

Count the number of opertations inside a recursive algorithm in python

I'm implementing the dichotomic search algorithm in python, in a second version of the function I have to (in addition of returning true or false according to the presence or not of the element) count the number of operations (comparisons) done by the algorithm depending on the length of the list I'm working with and return it.
However, my function is recursive and naturally I'll have to initialize a counter variable (which will be incremented at every operation) to zero. the issue is that this variable will take the zero value at every recursive call and thus, it will not give me the correct value. I thought of a global variable but I don't know how to use it.
Here is the code of my function :
def trouve(T, x) :
if len(T) == 0 :
return False
mid = len(T) // 2
if T[mid] == x :
return True
if len(T) == 1 and T[0] != x :
return False
else :
if x > T[mid] :
return trouve(T[mid:], x)
else :
return trouve(T[:mid], x)
Normally, you would count the comparisons of data only, so not the conditions where you compare the length of the input list.
You could use a third argument to accumulate the count, and then let the function return a tuple of both the success and the count:
def trouve(T, x, c = 0):
if len(T) == 0:
return (False, c) # len() comparisons do not count
mid = len(T) // 2
if T[mid] == x:
return (True, c+1)
if len(T) == 1: # you don't need to compare x again here!
return (False, c+1)
# you don't need `else` here
if x > T[mid]:
return trouve(T[mid:], x, c+2)
# you don't need `else` here
return trouve(T[:mid], x, c+2)
print (trouve([1,3,8,13,14,15,20], 14))
Note that you can optimise a bit:
def trouve(T, x, c = 0):
if len(T) == 0:
return (False, c)
mid = len(T) // 2
# you don't need the `len(T) == 1` case, as it can be
# treated in the recursive call. See change below:
if x > T[mid]:
return trouve(T[mid+1:], x, c+1) # exclude mid itself
# Move equality test below greater-then test, since the
# equality has little chance of being true:
if T[mid] == x:
return (True, c+2)
return trouve(T[:mid], x, c+2)
print (trouve([1,3,8,13,14,15,20], 14))
... although for the example I gave, the count is still the same in this version.
If you want to go the global variable route (since you mentioned it), this is how you would do it.
trouve_count = 0
def trouve(T, x) :
global trouve_count
# Increment trouve_count like this when necessary:
trouve_count += 1
# ...
Be careful using these in larger programs, as you may accidentally use the same global name twice, causing problems.

Instead of continue, rerun function

I'm wondering how to do the following in Python.
If I have a function with a for loop, it is possible to with an if statement to skip certain numbers.
This is an implementation of fisher-yates d got from activestate.com.
import random
def shuffle(ary):
a=len(ary)
b=a-1
for d in range(b,0,-1):
e=random.randint(0,d)
if e == d:
continue
ary[d],ary[e]=ary[e],ary[d]
return ary
Now continue simply goes to the next value for d. How can I, instead of doing continue, rerun the function with the original parameter ary?
Note that the function is just some example code, I'm curious on how to do this in general.
Also, maintaining a copy of the array might not be possible if the list is big, so thats not really a solution imo.
This is a common recursive pattern. However, your case is a little different than usual because here you need to make a copy of your input list to use when you recurse if the shuffling fails.:
import random
def shuffle(ary):
initial = ary[:]
a=len(ary)
b=a-1
for d in range(b,0,-1):
e=random.randint(0,d)
if e == d:
return shuffle(initial)
ary[d],ary[e]=ary[e],ary[d]
return ary
ary = [1,2,3,4,5,6]
print shuffle(ary)
Also note that Wikipedia gives a (non-recursive) python implementation of the very similar Sattolo's algorithm.
from random import randrange
def sattoloCycle(items):
i = len(items)
while i > 1:
i = i - 1
j = randrange(i) # 0 <= j <= i-1
items[j], items[i] = items[i], items[j]
return
If I read the article correctly, to re-acquire Fisher-Yates, you'd just do one simple change:
from random import randrange
def FisherYates(items):
i = len(items)
while i > 1:
i = i - 1
j = randrange(i+1) # 0 <= j <= i
items[j], items[i] = items[i], items[j]
return
def function(list):
len(list)-1
for i in range(len(list)-1,0,-1):
e= randint(0,i)
while e > i:
e= randint(0,i)
"do something to the list"
return array
?
def function(list):
for i in (a for a in range(len(list)-1,0,-1) if randint(0,a) > a):
#do something with list
#do something else with remainder.
Not exactly what you asked for. Just wanted to remind you of this possibility.
you can copy the parameter to a temp variable. then call the function with the temp variable and use return;
def function(list):
listCopy = list;
len(list)-1
for i in range(len(list)-1,0,-1):
e= randint(0,i)
if e > i:
return function(listCopy)
else
"do something with the list"
return array

Calling a function recursively in Python by passing a List

I know there are easier ways to create a function which gives you the largest number in a list of numbers but I wanted to use recursion. When I call the function greatest, i get none. For example greatest([1,3,2]) gives me none. If there are only two elements in the list, I get the right answer so I know the problem must be with the function calling itself. Not sure why though.
def compare(a,b):
if a==b:
return a
if a > b:
return a
if a < b:
return b
def greatest(x):
if len(x)==0:
return 0
i=0
new_list=[]
while i< len(x):
if len(x)-i>1:
c=compare(x[i],x[i+1])
else:
c=x[i]
new_list.append(c)
i=i+2
if len(new_list)>1:
greatest(new_list)
else:
return new_list[0]
print greatest([1,3,2])
This line:
if len(new_list)>1:
greatest(new_list) # <- this one here
calls greatest but doesn't do anything with the value it returns. You want
return greatest(new_list)
After fixing that, your function seems to behave (although I didn't look too closely):
>>> import itertools
>>> for i in range(1, 6):
... print i, all(max(g) == greatest(g) for g in itertools.product(range(-5, 5), repeat=i))
...
1 True
2 True
3 True
4 True
5 True
A simple recursion can be like this :
from random import *
def greatest(x,maxx=float("-inf")):
if len(x)>0:
if x[0] > maxx:
maxx=x[0]
return greatest(x[1:],maxx)
else:
return maxx
lis=range(10,50)
shuffle(lis)
print greatest(lis) #prints 49

Categories