I am trying to understand the following program to find a number of the subset which forms a given sum from a given list.
def count_sets(arr, total):
return rec(arr, total, len(arr)-1)
def rec(arr, total, i):
print(arr, total, i)
if total == 0:
return 1
if i < 0:
return 0
if arr[i] > total:
return rec(arr, total, i-1)
else:
return rec(arr, total-arr[i], i-1) + rec(arr, total, i-1)
arr = [2,10,6,4]
print(count_sets(arr, 16))
the program works without any error, however, I am not able to find how it works.
It is a backtracking algorithm. In recursion rec(arr, total, i), it picks the last element arr[i] in rest array, and here are two main situations:
use arr[i]: rec(arr, total-arr[i], i-1)
not use arr[i]: rec(arr, total, i-1), and when arr[i] > total of course you can only not use it.
and we must have terminate condition for recursion, that is:
[success] find the subarray equal to total: if total == 0: return 1
[failed] reach the head: if i < 0: return 0
Hope I make it clear, and comment if you have further questions. : )
Related
I've tried to create a generator function which can find simple moving average of the list, but it doesn't work at all. I think the root of the problem might be in finding sum
def gen(lst, n):
s = 0
for i, _ in enumerate(lst):
if lst[i] < n:
s += lst[n - (n-i)]
my code does nothing when i play it. What should I do?
if lst[i] < n:
You do not define i
but I guess i is a index of lst so try:
for i, _ in enumerate(lst):
if lst[i] < n:
s += lst[n - (n-i)]
EDIT:
def gen(lst, n):
if n > len(lst):
print("Sorry can't do this")
try:
for i, _ in enumerate(lst[:-(n-1)]):
s = sum(lst[i:i+n])
yield s/n
except ZeroDivisionError:
print("Sorry can't do this")
You may have some issues with this code snippet because you did not include some relevant variables and how they are used.
Below is an example of how you can calculate a moving average of list_of_numbers, given a position p with a period of n.
def mAverage(list_of_numbers, p, n):
if n < p:
return sum(list_of_numbers[p-n:p])/n
else:
return sum(list_of_numbers[0:p])/(p + 1)
Note: At the beginning of the list this function will only calculate the moving average with a period equal to the position in the list.
I am trying to implement jump search in Python. The code looks logically fine to me. I am getting -1 for all the numbers except for the first element of the array. Can someone help please?
def jumpsearch(array,x):
n=len(array)
m=int(sqrt(n))
if array[0]>x:
return -1
for i in (0,n-1,m):
if array[i]==x:
return i
if x<array[i]:
for k in (i-m,i):
if array[k]==x:
return k
return -1
j=[1,2,3,4,5,6,7,8]
print(j)
jumpsearch(j,2)
When you do for k in (i-m,i): you don't iterate in a range, but k only takes 2 values: i-1 and m.
Same for the line for i in (0,n,m):.
You also get uncorrect results because you never check in the last block. Indeed even by doing for i in range(0, n, m): you will stop when i + m >= n, so you have to check in the last part to be sure that the element is not there.
def jumpsearch(array, x):
n=len(array)
m=int(math.sqrt(n))
if array[0] > x:
return -1
for i in range(0, n, m):
if array[i] == x:
return i
elif x < array[i]:
for k in range(i-m, i):
if array[k]==x:
return k
else:
return -1
for j in range(i+1,n):
if array[j] == x:
return j
else:
return -1
Given heap as an array with keys , how to print all keys ? So far I got
def heapPrint (arr,i):
if (len(arr) == 0 or len(arr) == 1):
return
if (left(i) > len(arr) or right(i) > len(arr)):
return
if (left(i) < len(arr) and right(i) < len(arr):
print (arr[left(i)],arr[right(i)])
heapPrint (arr,left(i))
heapPrint (arr,right(i))
Isnt there any better solution where I could print just 1 node and not 2? Thanks
I think you're looking for something like this:
def heapPrint(arr, i)
# if the index is larger than the heap length
if i >= len(arr):
return;
# if it's a leaf node, then return
if left(i) >= len(arr) and right(i) >= len(arr):
return
if left(i) < len(arr):
print(arr[left(i)], end=' ')
if right(i) < len(arr):
print(arr[right(i)], end='')
print('')
# these calls will return immediately if the
# index is too large.
heapPrint(arr, left(i))
heapPrint(arr, right(i))
My python skills are minimal, so there might be some syntax errors there, but that's the basic idea.
What is the recursive call (or inductive steps) for a function that returns the number of integers from 1 to N, which evenly divide N. The idea is to concieve a pure recursive code in python for this function. No 'for' or 'while' loops, neither modules can be used. The function num_of_divisors(42) returns 8, representing 1, 2, 3, 6, 7, 14, 21, and 42 as divisors of 42.
def num_of_divisors(n):
return sum(1 if n % i==0 else 0 for i in range(((n+1)**0.5)//1)
Good luck explaining it to your teacher!
If you really can't use for loops (?????????) then this is impossible without simulating one.
def stupid_num_of_divisors_assigned_by_shortsighted_teacher(n, loop_num=1):
"""I had to copy this from Stack Overflow because it's such an
inane restriction it's actually harmful to learning the language
"""
if loop_num <= (n+1) ** 0.5:
if n % loop_num == 0:
return 2 + \
stupid_num_of_divisors_assigned_by_shortsighted_teacher(n, loop_num+1)
else:
return stupid_num_of_divisors_assigned_by_shortsighted_teacher(n, loop_num+1)
else:
if n % loop_num == 0:
return 1
Bonus points: explain why you're adding 2 in the first conditional, but only 1 in the second conditional!
Here you go buddy your teacher'll be happy.
def _num_of_divisors(n, k):
if (k == 0):
return 0
return _num_of_divisors(n, k-1) + (n % k == 0)
def num_of_divisors(n):
return _num_of_divisors(n, n)
It's easier than you think to convert such a simple problem from a loop to a recursive function.
Start with a loop implementation:
n = 42
result = []
for i in range(n+1):
if n % i == 0:
result.append(i)
then write a function
def num_of_divisors_helper(i, n, result):
if <condition when a number should be added to result>:
result.append(n)
# Termination condition
if <when should it stop>:
return
# Recursion
num_of_divisors_helper(i+1, n, result)
Then you define a wrapper function num_of_divisors that calls num_of_divisors_helper. You should be able to fill the gaps in the recursive function and write the wrapper function yourself.
It's a simple, inefficient solution, but it matches your terms.
Without using %
def is_divisible(n, i, k):
if k > n:
return False
if n - i*k == 0:
return True
else:
return is_divisible(n, i, k+1)
def num_of_divisors(n, i=1):
if i > n/2:
return 1
if is_divisible(n, i, 1):
return 1 + num_of_divisors(n, i+1)
else:
return num_of_divisors(n, i+1)
num_of_divisors(42) -> 8
def n_divisors(n,t=1):
return (not n%t)+(n_divisors(n,t+1) if t < n else 0)
good luck on the test later ... better hit those books for real, go to class and take notes...
with just one input i guess
t=0
def n_divisors(n):
global t
t += 1
return (not n%t)+(n_divisors(n) if t < n else 0)
This question already has answers here:
Understanding recursion [closed]
(20 answers)
Closed 5 months ago.
How can I write a function that computes:
C(n,k)= 1 if k=0
0 if n<k
C(n-1,k-1)+C(n-1,k) otherwise
So far I have:
def choose(n,k):
if k==0:
return 1
elif n<k:
return 0
else:
Assuming the missing operands in your question are subtraction operators (thanks lejlot), this should be the answer:
def choose(n,k):
if k==0:
return 1
elif n<k:
return 0
else:
return choose(n-1, k-1) + choose(n-1, k)
Note that on most Python systems, the max depth or recursion limit is only 1000. After that it will raise an Exception. You may need to get around that by converting this recursive function to an iterative one instead.
Here's an example iterative function that uses a stack to mimic recursion, while avoiding Python's maximum recursion limit:
def choose_iterative(n, k):
stack = []
stack.append((n, k))
combinations = 0
while len(stack):
n, k = stack.pop()
if k == 0:
combinations += 1
elif n<k:
combinations += 0 #or just replace this line with `pass`
else:
stack.append((n-1, k))
stack.append((n-1, k-1))
return combinations
Improving from Exponential to Linear time
All of the answers given so far run in exponential time O(2n). However, it's possible to make this run in O(k) by changing a single line of code.
Explanation:
The reason for the exponential running time is that each recursion separates the problem into overlapping subproblems with this line of code (see Ideone here):
def choose(n, k):
...
return choose(n-1, k-1) + choose(n-1, k)
To see why this is so bad consider the example of choose(500, 2). The numeric value of 500 choose 2 is 500*499/2; however, using the recursion above it takes 250499 recursive calls to compute that. Obviously this is overkill since only 3 operations are needed.
To improve this to linear time all you need to do is choose a different recursion which does not split into two subproblems (there are many on wikipedia).
For example the following recursion is equivalent, but only uses 3 recursive calls to compute choose(500,2) (see Ideone here):
def choose(n,k):
...
return ((n + 1 - k)/k)*choose(n, k-1)
The reason for the improvement is that each recursion has only one subproblem that reduces k by 1 with each call. This means that we are guaranteed that this recursion will only take k + 1 recursions or O(k). That's a vast improvement for changing a single line of code!
If you want to take this a step further, you could take advantage of the symmetry in "n choose k" to ensure that k <= n/2 (see Ideone here):
def choose(n,k):
...
k = k if k <= n/2 else n - k # if k > n/2 it's equivalent to k - n
return ((n + 1 - k)/k)*choose(n, k-1)
Solution from wikipedia (http://en.wikipedia.org/wiki/Binomial_coefficient)
def choose(n, k):
if k < 0 or k > n:
return 0
if k > n - k: # take advantage of symmetry
k = n - k
if k == 0 or n <= 1:
return 1
return choose(n-1, k) + choose(n-1, k-1)
You're trying to calculate the number of options to choose k out of n elements:
def choose(n,k):
if k == 0:
return 1 # there's only one option to choose zero items out of n
elif n < k:
return 0 # there's no way to choose k of n when k > n
else:
# The recursion: you can do either
# 1. choose the n-th element and then the rest k-1 out of n-1
# 2. or choose all the k elements out of n-1 (not choose the n-th element)
return choose(n-1, k-1) + choose(n-1, k)
just like this
def choose(n,k):
if k==0:
return 1
elif n<k:
return 0
else:
return choose(n-1,k-1)+choose(n-1,k)
EDIT
It is the easy way, for an efficient one take a look at wikipedia and spencerlyon2 answer