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
Related
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.
I use PyCharm to realize a program which is aimed to generate primes. Code like this:
def _odd_iter():
n = 1
while True:
yield n
n = n + 2
def _not_divisible(n):
return lambda x: x % n > 0
def primes():
it = _odd_iter()
yield 2
while True:
i = next(it)
yield i
it = filter(_not_divisible, it) # !!!!!!!!!!don't know how it works!!!!!!!!!!
for n in primes():
if n < 1000:
print(n)
else:
break
For me the annotated code is obscure, I dont know how it works and whether it is right, so I add a breakpoint on it and determine to debug. But it is a generator, I cannot see the detail numbers. What can I do?
filter(function or None, iterable) --> filter object
Return an iterator yielding those items of iterable for which function(item) is true. If function is None, return the items that are true.
You can't see the details because it returns an iterable object, do this to see what it returns:
it = list(filter(_not_divisible, it)) # or next(filter(...))
from random import *
def Number(N):
if N>0:
return [ choice( [0,1] ) for i in range(N)]
else:
return ("Only Positive #'s!")
How would I do this recursively?
Let's say N=5, so [0,1,2,3,4] for each # to be replaced with either a 0 or a 1. I just can't seem to wrap my head around doing this list manipulation recursively.
Here's one option:
from random import choice # don't use * imports
def Number_recursive(N):
if N < 0:
raise ValueError('N must be positive')
if N == 0:
return []
return [choice((0, 1))] + Number_recursive(N-1)
Note the raising of an error rather than returning a string; this tells the caller more directly that something went wrong.
I don't understand how recursion will help here. How about just simplifying it like this:
from random import choice
def binary_list(length):
return [choice([0, 1]) for x in range(0, length)]
def all_gt(nums, n):
i = []
for c in nums:
if c > n:
i += c
return i
This is the code that i used and 'i' is supposed to return the value in nums larger than n.
But mine returns nothing inside the bracket. E.g.,
all_gt([1,2,3,4], 2) => [3,4]
Anyone knows how to fix?
Thanks
You declared i to be a list, so you need to append to it instead of adding.
def all_gt(nums, n):
i = []
for c in nums:
if c > n:
i.append(c) ## <----- note this
return i
Alternatively, you could have done this:
i += [c]
in place of the append.
Outdent your return statement so that it isn't executed as part of the loop.
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