Related
def getList(n, input_list, caching_list):
The function should return a list that adds up to a number "n" using numbers from the input_list, given that numbers can be repeated. Looking to use recursion.
current code:
def getList(n, input_list, caching_list):
if n == 0 :
return caching_list
if n < 0 or len(input_list) == 0:
return []
for i in input_list:
if find_sum(n-i,input_list,caching_list) == caching_list:
caching_list.append(i)
return caching_list
return []
example
n = 13, input_list= [2,3,5] should result in [2,2,2,2,2,3] or [5,5,2] or anything that adds to 13.
Doing this with using a number just 1 time is easy, but how would one consider the case of using same number multiple times?
With recursion, this can be solved using a depth-first search (DFS) algorithm, but it can throw RecursionError: maximum recursion depth exceeded in comparison
def find(n2, plist):
result = []
def find2(n):
if n == 0:
return True
if n < 0:
return False
for p in plist:
if find2(n-p):
result.append(p)
return True
find2(n2)
return result
print(find(17, [2,3,5])) # [3, 2, 2, 2, 2, 2, 2, 2]
print(find(7, [3,5])) # []
print(find(77777, [3,5,7,11])) # recursion error
To get rid of the recursion error, recursive DFS can be rewritten into iterative DFS.
I find itertools can be very handy for stuff like this. I am sure there are better ways to do it, but this might get you want you need:
import itertools
def find_sum(n, p_list):
max_len = n // min(p_list)
min_len = n // max(p_list)
for i in range(min_len, max_len+1):
I = itertools.combinations_with_replacement(p_list, i)
for j in I:
if(sum(j) == n):
return(list(j))
return([])
print(find_sum(17,[2,3,5]))
# [2, 5, 5, 5]
print(find_sum(7, [3, 5]))
# []
You could easily alter the code to give you all combinations.
def find_sum(n, p_list):
max_len = n // min(p_list)
min_len = n // max(p_list)
answers = []
for i in range(min_len, max_len+1):
I = itertools.combinations_with_replacement(p_list, i)
for j in I:
if(sum(j) == n):
answers.append(list(j))
return(answers)
find_sum(17,[2,3,5])
#[[2, 5, 5, 5], [2, 2, 3, 5, 5], [3, 3, 3, 3, 5], [2, 2, 2, 3, 3, 5], [2, 3, 3, 3, 3, 3], [2, 2, 2, 2, 2, 2, 5], [2, 2, 2, 2, 3, 3, 3], [2, 2, 2, 2, 2, 2, 2, 3]]
Regarding #dantebarba's comment, I haven't really looked to see how it will scale for large problems and there may be more efficient approaches.
These 3 lines of code should raise some red flags:
if find_sum(n-i,p,p_list,sum_list) == sum_list:
sum_list.append(i)
return sum_list
You have a recursive function storing its results in sum_list, modifying it, and also depending on its values for equality checks. This makes your program extremely difficult to reason about. Does the behavior change if you swap the arguments around the equality sign? I have no idea.
In general, your recursive programs should try to avoid passing their result as a parameter. Since that if statement is really asking whether we can make a certain sum, why not break that into a separate function?
def can_sum(n, p_list, cache={}):
if n in cache:
return cache[n]
if n == 0:
return True
if n < 0:
return False
return any(can_sum(n-p, p_list) for p in p_list)
You want to use some kind of caching (otherwise, your program is exponential-time), and functools.cache is preferable if you can use outside libraries, but this will do the job.
How should your find_sum function return results without passing the result as a parameter? Just add your value to the end, exactly like your code did:
def find_sum(n, p_list):
for p in p_list:
if can_sum(n-p, p_list):
return find_sum(n-p, p_list) + [p]
return []
def pairs(x):
for num in x:
if num == num :
return x
y = [2, 2, 2, 2, 2, 4, 3, 3]
pairs (y)
print (y)
this is returning [2, 2, 2, 2, 2, 4, 3, 3]
but I want to return [2,2,3]
I've tried 3 codes already other than this one
help me
Your code seems to be intended to find all the numbers that exist in pairs in the list. The best way would be (for a sorted list) to just cycle through the list and check successive elements.
Your code just matches if the current number is the same as the current numbers always returns true and returns all elements. A correct Code might be:
y = [2, 2, 2, 2, 2, 4, 3, 3]
y=sorted(y) # Sorts the given list
def pairs(arr):
i = 0 # Counter variable
res = [] #result list
while i < len(arr)-1:
if arr[i] == arr[i+1]:
res.append(arr[i]) # If the successive elements are the same, add
# it to the result array and since we have already
# checked the next element, increment the counter by
# two
i+=2
else:
i+=1 # If the elements are different we need to check the
# next element as well so increment by 1
return res
print(pairs(y))
You are comparing the element with itself which is always true. Here is the correct logic
y = [2, 2, 2, 2, 2, 4, 3, 3]
filt = []
i=0
while (i< (len(y)-1)):
if y[i] == y[i+1]:
filt.append(y[i])
i+=1
i+=1
print(filt)
I am working on a question as following:
Given a set of numbers that might contain duplicates, find all of its distinct subsets.
You can use the following as an example :
Example 1:
Input: [1, 3, 3]
Output: [], [1], [3], [1,3], [3,3], [1,3,3]
Example 2:
Input: [1, 5, 3, 3]
Output: [], [1], [5], [3], [1,5], [1,3], [5,3], [1,5,3], [3,3],
[1,3,3], [3,3,5], [1,5,3,3]
My approach is
class Solution:
def distinct_subset(self, nums):
n = len(nums)
previousEnd = 0
output = []
for i in range(n):
# judge if the current element is equal to the previous element
# if so, only update the elements generated in the previous iteration
if i > 0 and nums[i] == nums[i-1]:
previousStart = previousEnd + 1
else:
previousStart = 0
perviousEnd = len(output)
# create a temp array to store the output from the previous iteration
temp = list(output[previousStart:previousEnd])
# add current element to all the array generated by the previous iteration
output += [j + [nums[i]] for j in temp]
return output
def main():
print("Here is the list of subsets: " + str(Solution().distinct_subset([1, 3, 3])))
print("Here is the list of subsets: " + str(Solution().distinct_subset([1, 5, 3, 3])))
main()
However, my approach will only return []:
Here is the list of subsets: []
Here is the list of subsets: []
Process finished with exit code 0
I am not sure why did I go wrong. The algorithm supposes to update the output in each iteration. But now it failed.
Please feel free to share your ideas. Thanks for your help in advanced.
Yes, I ran your code and it appears no matter what you do the function will always return an output of an empty list, because nothing is actually changing in the list, it is always blank.
Forgive me, but I had to look up what 'all distinct subsets' meant, and I stumbled across this code, but it seems to do exactly what you are asking.
# Python3 program to find all subsets of
# given set. Any repeated subset is
# considered only once in the output
def printPowerSet(arr, n):
# Function to find all subsets of given set.
# Any repeated subset is considered only
# once in the output
_list = []
# Run counter i from 000..0 to 111..1
for i in range(2**n):
subset = ""
# consider each element in the set
for j in range(n):
# Check if jth bit in the i is set.
# If the bit is set, we consider
# jth element from set
if (i & (1 << j)) != 0:
subset += str(arr[j]) + "|"
# if subset is encountered for the first time
# If we use set<string>, we can directly insert
if subset not in _list and len(subset) > 0:
_list.append(subset)
# consider every subset
for subset in _list:
# split the subset and print its elements
arr = subset.split('|')
for string in arr:
print(string, end = " ")
print()
# Driver Code
if __name__ == '__main__':
arr = [10, 12, 12, 17]
n = len(arr)
printPowerSet(arr, n)
However, as you can see the above code does not use classes just a single function. If that works great, if you are required to use a class, let me know you will need to change the above code obviously.
I assume the below is what you are looking for:
[1, 3, 3] to [1,3]
[1, 5, 3, 3] to [1,5,3]
The set(list) function will do that for you real easy, however it doesn't handle compound data structure well.
Below code will work for compound data from, one level deep:
[[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]
to:
[[1, 1], [0, 1], [0, 0], [1, 0]]
code:
def get_unique(list):
temp = []
for i in list:
if i not in temp:
temp.append(i)
yield i
print(*get_unique(list))
I've trimmed the above code to give you your desired outputs, still not in a class though, is this okay?...
def distinct_subset(user_input):
n = len(user_input)
output = []
for i in range(2 ** n):
subset = ""
for j in range(n):
if (i & (1 << j)) != 0:
subset += str(user_input[j]) + ", "
if subset[:-2] not in output and len(subset) > 0:
output.append(subset[:-2])
return output
def main():
print("Here is the list of subsets: " + str(distinct_subset([1, 3, 3])))
print("Here is the list of subsets: " + str(distinct_subset([1, 5, 3, 3])))
main()
You're looking for distinct combinations of the powerset of your list.
Using itertools to generate the combinations and a set to eliminate duplicates, you could write the function like this:
from itertools import combinations
def uniqueSubsets(A):
A = sorted(A)
return [*map(list,{subset for size in range(len(A)+1)
for subset in combinations(A,size)})]
print(uniqueSubsets([1,3,3]))
# [[1, 3], [3, 3], [1], [3], [], [1, 3, 3]]
print(uniqueSubsets([1,5,3,3]))
# [1, 3] [3, 3] [1] [3] [3, 3, 5] [1, 3, 5] [1, 5] [5] [] [1, 3, 3, 5] [1, 3, 3] [3, 5]
If you have a lot of duplicates, it may be more efficient to filter them out as you go. Here is a recursive generator function that short-circuits the expansion when a combination has already been seen. It generates combinations by removing one element at a time (starting from the full size) and recursing to get shorter combinations.
def uniqueSubsets(A,seen=None):
if seen is None: seen,A = set(),sorted(A)
for i in range(len(A)): # for each position in the list
subset = (*A[:i],*A[i+1:]) # combination without that position
if subset in seen: continue # that has not been seen before
seen.add(subset)
yield from uniqueSubsets(subset,seen) # get shorter combinations
yield list(A)
print(*uniqueSubsets([1,3,3]))
# [] [3] [3, 3] [1] [1, 3] [1, 3, 3]
print(*uniqueSubsets([1,5,3,3]))
# [] [3] [3, 3] [5] [5, 3] [5, 3, 3] [1] [1, 3] [1, 3, 3] [1, 5] [1, 5, 3] [1, 5, 3, 3]
In both cases we are sorting the list in order to ensure that the combinations will always present the values in the same order for the set() to recognize them. (otherwise lists such as [3,3,1,3] could still produce duplicates)
def _findsum (arr, N):
if len(arr)== 1:
return arr[0]
else:
return arr[0]+_findSum(arr[1:], N)
arr =[]
arr = [1, 2, 3, 4, 5]
N = len(arr)
ans =_findSum(arr,N)
print (ans)
_findsum(arr,N)
OutPut= 15
I need to write a recursive program to sum all elements of a non-uniform nested list.
I need the code to print something similar to the list below.
[7, [4, 6], 2, [1, 3, 5]].
Your question is a little unclear but I'm guessing you need to print the sum of all the numbers present in the parent list. Here's a hint.
In the function, iterate through the list which is passed as a parameter. If the type of the current element is list, call the function with that list as the parameter. If not, return the sum of the elements.
def findsum(arr):
if len(arr) == 0:
return 0
first = arr[0]
rest = arr[1:]
if type(first) == list:
return findsum(first) + findsum(rest)
else:
return first + findsum(rest)
x = [1, [[2, 3], 4]]
print(findsum(x)) # returns 10
If I understood your question correctly, this program should return the sum of the elements in your nested list.
A shorter version looks like this:
def findsum(arr):
return sum((findsum(element) if (type(element) == list) else element) for element in arr)
x = [7, [[2,[-1]]]]
print(findsum(x)) # returns 8
and records--in a separate list--these occurrences in terms of the indices where they were found.
For example find_all([1, 2, 3, 4, 5, 2], 2) returns [1, 5]. find_all([1, 2, 3], 0) returns [ ].
I'm totally new to python and this question is stumping me on my first homework. I need to
take 2 arguments: a list of items, and a single element to search for in the list
returns 1 list: a list of indices into the input list that correspond to elements in the input list that match what we were looking for
not sure
Simple Method using list comprehension
def find_all(l, value):
return [i for i, v in enumerate(l) if v == value]
mylist = [1, 2, 3, 4, 5, 2]
print(find_all(mylist, 2)) # [1, 5]
Use this method since list.index only returns the first match
and you want them all
You can try something like this
def find_all(input_list, search_value):
result = []
for idx, num in enumerate(input_list):
if num == search_value:
result.append(idx)
return result
You should go through the tutorials available on the internet to learn the Python Basics.
https://treyhunner.com/2016/04/how-to-loop-with-indexes-in-python/
https://www.programiz.com/python-programming/function-argument
def find_all(list, num):
newlist = []
for i in range(len(list)):
if (list[i] == num):
newlist.append(i)
return newlist
list = [1, 2, 3, 6, 5, 2]
mylist = find_all(list, 2)
print mylist
Hope this helps.