Given a list of positive integers and a target value, generate a solution set. For example, if the list is [10, 1, 2, 7, 6, 1, 5] and the target is 8, the solution set is...
[
[1, 7],
[1, 2, 5],
[2, 6]
[1, 1, 6]
[
I know there a multiple solutions to this, such as dp, but I am trying to get my dfs solution working and I believe I am very close, but I simply cannot get the correct result. If possible, I would like it if you didn't change my initial answer too much, if that's not possible, any solution will do.
def combinationSum(self, candidates, target):
candidates.sort()
total = []
self.helper(candidates, 0, target, [], total)
def helper(self, candidates, curr, target, temp, total):
if target == 0:
total.append(temp)
return
if target < 0:
return
for i in range(curr, len(candidates)):
# avoid duplicates
if i > curr and candidates[i] == candidates[i-1]:
continue
temp.append(candidates[i])
self.helper(candidates, i+1, target-candidates[i], temp, total)
# I'm not sure what to do here
This obviously does not give me the right result but I do think I am on the right track towards generating the solution set. I simply do not understand what I need to do after the recursive call to remove unnecessary elements.
I think this is along the lines of what you are trying to do:
def solve(target, sum, candidates, answer):
if sum == target:
print answer
return
if len(candidates) == 0 or sum > target:
return
first = candidates[0]
count = candidates.count(first);
answer.append(first)
solve(target, sum+first, candidates[1:], answer) #using the current number
answer.pop()
solve(target, sum, candidates[count:], answer) #skipping the current number and any duplicates
if __name__ == "__main__":
candidates = [10, 1, 2, 7, 6, 1, 5]
candidates.sort();
solve(8, 0, candidates, [])
The key point is that solve has two recursive calls.
The first recursive call uses the first number in the candidates list. So it
appends the first number to the answer
adds the first number to the sum
removes only the first number from the candidates list that is
passed to the next level
The second recursive call doesn't use the first number in the candidates list. And since it doesn't use the first number, it also doesn't use any duplicates of the first number. That's the reason for the count variable. candidates.count(first) is the number of entries in the list that are equal to first. So in the recursive call candidates[count:] removes the first element and any duplicates. (This assumes that the list is sorted, which should be done once before calling solve).
Here's one possible solution using recursion – I chose a tuple to represent the combinations, but you could've used list for those too
def combinationSum (l, target, sum = 0, comb = ()):
# base case: empty input [l]
if not l:
return []
# inductive case: [l] has at least one element
else:
# [x] is the first sub-problem
# [xs] is the rest of the sub-problems
x, *xs = l
# [x] plus [sum] is bigger than [target]
if x + sum > target:
return \
combinationSum (xs, target, sum, comb)
# [x] plus [sum] is smaller than [target]
elif x + sum < target:
return \
combinationSum (xs, target, sum + x, (x, *comb)) + \
combinationSum (xs, target, sum, comb)
# [x] plus [sum] is equal to [target]
else:
return \
[ (x, *comb) ] + \
combinationSum (xs, target, sum + x, (x, *comb)) + \
combinationSum (xs, target, sum, comb)
data = [10, 1, 2, 7, 6, 1, 5]
print (combinationSum (data, 8))
# [(5, 2, 1), (7, 1), (1, 6, 1), (6, 2), (5, 1, 2), (1, 7)]
If you want combinationSum to allow for duplicate values, you only have to change one part. Note, the program considers eg (5, 1, 1, 1) a solution 3 times because the 1 appears in 3 unique positions. If you only wanted (5, 1, 1, 1) to appear once, you'd have to consider a different approach.
...
elif x + sum < target:
return \
combinationSum (xs, target, sum + x, (x, *comb)) + \
combinationSum (l , target, sum + x, (x, *comb)) + \
combinationSum (xs, target, sum, comb)
...
print (combinationSum (data, 8))
# [ (1, 1, 1, 1, 1, 1, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (2, 1, 1, 1, 1, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (1, 2, 1, 1, 1, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (2, 2, 1, 1, 1, 1)
# , (1, 1, 2, 1, 1, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (1, 2, 2, 1, 1, 1)
# , (1, 1, 1, 2, 1, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (5, 1, 1, 1)
# , (2, 2, 2, 1, 1)
# , (1, 1, 2, 2, 1, 1)
# , (1, 1, 1, 1, 2, 1, 1)
# , (6, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (5, 1, 1, 1)
# , (1, 2, 2, 2, 1)
# , (1, 1, 1, 2, 2, 1)
# , (1, 1, 1, 1, 1, 2, 1)
# , (5, 2, 1)
# , (7, 1)
# , (1, 6, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (5, 1, 1, 1)
# , (2, 2, 2, 2)
# , (1, 1, 2, 2, 2)
# , (1, 1, 1, 1, 2, 2)
# , (6, 2)
# , (1, 1, 1, 1, 1, 1, 2)
# , (5, 1, 2)
# , (1, 7)
# , (1, 1, 6)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (5, 1, 1, 1)]
# ]
Related
I have a little bit changed algorithm for 1-0 Knapsack problem.
It calculates max count (which we can put to the knapsack) as well.
I'm using it to find max subset sum which <= target sum. For example:
weights: 1, 3, 4, 5, target sum: 10
result: 1, 4, 5 (because 1 + 4 + 5 = 10)
weights: 2, 3, 4, 9 target sum: 10
result: 2, 3, 4 (2 + 3 + 4 = 9, max possible sum <= 10)
I use 2 DP tables: one for calculating max possible sum (dp) and one for max possible amount (count).
The question is: how I can derive chosen values from the both tables?
Example:
weights: [3, 2, 5, 2, 1, 1, 3], target_sum: 10
indexes: 0, 1, 2, 3, 4, 5, 6
dp:
0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1: [0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3]
2: [0, 0, 2, 3, 3, 5, 5, 5, 5, 5, 5]
3: [0, 0, 2, 3, 3, 5, 5, 7, 8, 8, 10]
4: [0, 0, 2, 3, 4, 5, 5, 7, 8, 9, 10]
5: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
6: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
7: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
count:
0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1: [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
2: [0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2]
3: [0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3]
4: [0, 0, 1, 1, 2, 2, 2, 2, 2, 3, 3]
5: [0, 1, 1, 2, 2, 3, 3, 2, 3, 3, 4]
6: [0, 1, 2, 2, 3, 3, 4, 4, 3, 4, 4]
7: [0, 1, 2, 1, 2, 3, 3, 4, 4, 5, 5]
Here, items with weight [3, 2, 1, 3, 1] should be derived (because they have max possible count) instead of (for example) [5, 2, 3].
Some notation explanations:
dp means the same as in original Knapsack problem: i - for the items, j for the weight.
The value in the dp[i][j] mean the sum of chosen items (weights) which have sum <= j.
Each cell in the count corresponds to dp and shows max possible amount of items (with total weight = dp[i][j])
How chosen items could be derived efficiently?
I know how to derive just any items from the dp (e.g. not the max amount of them) by reconstructing it from the bottom-right cell.
Also, I've found a hack which allows to derive the items if input is sorted.
But I'm looking for the way which allows to do that without soring.
Is it's possible?
The code which constructs these two tables doesn't matter much, but here it is:
def max_subset_sum(ws, target_sum):
n = len(ws)
k = target_sum
dp = [[0] * (k + 1) for _ in range(n + 1)]
count = [[0] * (k + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, k + 1):
curr_w = ws[i - 1]
if curr_w > j:
dp[i][j] = dp[i - 1][j]
count[i][j] = count[i - 1][j]
else:
tmp = round(dp[i - 1][j - curr_w] + curr_w, 2)
if tmp >= dp[i - 1][j]:
dp[i][j] = tmp
count[i][j] = count[i - 1][j - curr_w] + 1
else:
dp[i][j] = dp[i - 1][j]
count[i][j] = count[i - 1][j]
return get_items(dp, k, n, ws)
def get_items(dp, k, n, ws):
# The trick which allows to get max amount of items if input is sorted
start = n
while start and dp[start][k] == dp[start - 1][k]:
start -= 1
res = []
w = dp[start][k]
i, j = start, k
while i and w:
if w != dp[i - 1][j]:
res.append(i - 1)
w = round(w - ws[i - 1], 2)
j -= ws[i - 1]
i -= 1
return res
Also, I have weird attempt to get max amount of items.
But it's produces incorrect result which sums to 9: [3, 1, 1, 2, 2]
def get_items_incorrect(dp, count, k, n, ws):
start = n
res = []
w = dp[start][k]
i, j = start, k
while i and w:
# while dp[i][j] < ws[i - 1]:
# i -= 1
while ws[i - 1] > j:
i -= 1
if i < 0:
break
max_count = count[i][j]
max_count_i = i
while i and w == dp[i - 1][j]:
if count[i - 1][j] > max_count:
max_count = count[i - 1][j]
max_count_i = i - 1
i -= 1
res.append(max_count_i - 1)
w = round(w - ws[max_count_i - 1], 2)
j -= ws[max_count_i - 1]
i = max_count_i - 1
return res
Sorry for the long read and thank you for any help!
Seems you have overcomplicated the problem. This kind of problem (without item cost) might be solved using 1D list. Weights for the best cases are stored in parallel list.
After table filling we look for the largest occupied index (largest possible sum <= target) and unwind used items chain.
def sol(wts, target):
dp = [-1] * (target + 1)
dp[0] = 0
items = [0] * (target + 1)
wts.sort()
for w in weights:
for i in range(target, w-1, -1):
if (dp[i-w] >= 0) and (dp[i-w] > dp[i]):
dp[i] = dp[i-w] + 1
items[i] = w
last = target
while (last) and (dp[last] < 0):
last -= 1
best = dp[last]
res = []
while (last):
res.append(items[last])
last -= items[last]
return(best, res)
weights = [1, 2, 3, 3, 5, 2, 1]
target_sum = 9
print(sol(weights, target_sum))
Given an array of n numbers find all the ways of inserting + and - between them so that the result of the expression is positive.
I've found this problem recently and I thought it was interesting, but I'm not exactly sure how to solve it. I think I should try backtracking, no?
Any help or hints are deeply appreciated!
Edit: Would this be a correct solution? (I wrote it in python)
def outputSolution(list):
print(list)
def solution(x, dim):
return len(x) == dim-1
def consistent(list, array):
partial_sum = array[0]
for i in range(len(list)):
if list[i] == 0:
partial_sum = partial_sum - array[i+1]
if list[i] == 1:
partial_sum = partial_sum + array[i+1]
absolute_remaining_sum = 0
for i in range(len(list)+1, len(array)): #the remaining elements in array
absolute_remaining_sum =absolute_remaining_sum + abs(array[i])
if partial_sum + absolute_remaining_sum < 0:
return False
else:
return True
def solve(list, array):
"""
array - the array of n given integers
list - the candidate to a solution
"""
dim = len(array)
for el in range(2): # el = 0 or 1 (0 for - and 1 for +)
if len(list) < dim - 1:
list.append(el)
if consistent(list, array):
if solution(list, dim):
outputSolution(list)
solve(list[:], array)
list.pop()
solve([], array)
My thought process was that there are n-1 gaps between those numbers. Each gap can have a '+' or a '-' in it. And so I build a list where list[i] is equal with 0 if between array[i] and array[i+1] there is an "-", and list[i] is equal with 0 if between array[i] and array[i+1] there is an "+". And I generated all the possible ways of choosing the values in the list, then I checked if that possible candidate is consistent or not. And I said that if the partial sum (calculated using the + and - in our current list) added to the maximum sum of the remaining elements of the given array is a negative number, then the candidate is inconsistent. If the candidate is consistent and it has the required length, then I said that it is a solution.
For example, if I had the array "array = [1,2,3,4,5,6,7]" as input, I was given the following solutions:
[0, 0, 0, 1, 1, 1]
[0, 0, 1, 0, 1, 1]
[0, 0, 1, 1, 0, 1]
[0, 0, 1, 1, 1, 0]
[0, 0, 1, 1, 1, 1]
[0, 1, 0, 0, 1, 1]
[0, 1, 0, 1, 0, 1]
[0, 1, 0, 1, 1, 0]
[0, 1, 0, 1, 1, 1]
[0, 1, 1, 0, 0, 1]
[0, 1, 1, 0, 1, 0]
[0, 1, 1, 0, 1, 1]
[0, 1, 1, 1, 0, 1]
[0, 1, 1, 1, 1, 0]
[0, 1, 1, 1, 1, 1]
[1, 0, 0, 0, 1, 1]
[1, 0, 0, 1, 0, 1]
[1, 0, 0, 1, 1, 0]
[1, 0, 0, 1, 1, 1]
[1, 0, 1, 0, 0, 1]
[1, 0, 1, 0, 1, 1]
[1, 0, 1, 1, 0, 1]
[1, 0, 1, 1, 1, 0]
[1, 0, 1, 1, 1, 1]
[1, 1, 0, 0, 1, 1]
[1, 1, 0, 1, 0, 1]
[1, 1, 0, 1, 1, 0]
[1, 1, 0, 1, 1, 1]
[1, 1, 1, 0, 0, 1]
[1, 1, 1, 0, 1, 0]
[1, 1, 1, 0, 1, 1]
[1, 1, 1, 1, 0, 0]
[1, 1, 1, 1, 0, 1]
[1, 1, 1, 1, 1, 0]
[1, 1, 1, 1, 1, 1]
Backtracking is indeed a reasonable strategy. Since you need to enumerate, there's only one pruning trick that makes an asymptotic difference. Suppose that the array starts with a very large negative number, e.g.,
−50 10 10 10 10 1 2 3 4 5
The sum always includes a −50 term, so the sign for each 10 must be positive since otherwise the remaining numbers aren't large enough to make the overall sum positive. By making the example bigger (more and bigger numbers), we can create an exponential gap between the complexity of naive backtracking and the number of solutions.
If we implement the usual depth-first backtracking strategy and maintain the sum of the absolute values of the remaining array elements, then we can prune every node where the partial sum plus the sum of absolute values is not positive. Since every node not pruned yields at least one solution, we end up with an optimal output-sensitive time complexity.
I need to change array(1,0,2,3,4,0,0,5,6,0,7) with array(1,1,2,3,4,4,4,5,6,6,7).
My code:
select
arrayMap (i-> (if(i=0, indexOf(arr,i)-1, i)), arr)
from (select array(1,0,2,3,4,0,0,5,6,0,7) as arr)
But it returns array(1,1,2,3,4,1,1,5,6,1,7). How to do it?
It looks like pretty weird but works (remark: zero-indexed 0-value be ignored):
SELECT
arrayEnumerate(arr) AS indexes,
[0, 1, 0, 2, 0, 0, 0, 3, 4, 0, 0, 5, 6, 0, 7, 8, 0] AS arr,
arrayMap(i -> if((arr[i] = 0) AND (i > 1), arr[(i - arrayFirst(x -> (arr[(i - x)] != 0), indexes))], arr[i]), indexes) AS result
FORMAT Vertical
Result:
Row 1:
──────
indexes: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
sourceData: [0,1,0,2,0,0,0,3,4,0,0,5,6,0,7,8,0]
result: [0,1,1,2,2,2,2,3,4,4,4,5,6,6,7,8,8]
I got quite standard DP problem - board nxn with integers, all positive. I want to start somewhere in the first row, end somewhere in the last row and accumulate as much sum as possible. From field (i,j) I can go to fields (i+1, j-1), (i+1, j), (i+1, j+1).
That's quite standard DP problem. But we add one thing - there can be an asterisk on the field, instead of the number. If we meet the asterisk, then we got 0 points from it, but we increase multiplier by 1. All numbers we collect later during our traversal are multiplied by multiplier.
I can't find out how to solve this problem with that multiplier thing. I assume that's still a DP problem - but how to get the equations right for it?
Thanks for any help.
You can still use DP, but you have to keep track of two values: The "base" value, i.e. without any multipliers applied to it, and the "effective" value, i.e. with multipliers. You work your way backwards through the grid, starting in the previous-to-last row, get the three "adjacent" cells in the row after that (the possible "next" cells on the path), and just pick the one with the highest value.
If the current cell is a *, you get the cell where base + effective is maximal, otherwise you just get the one where the effective score is highest.
Here's an example implementation in Python. Note that instead of * I'm just using 0 for multipliers, and I'm looping the grid in order instead of in reverse, just because it's more convenient.
import random
size = 5
grid = [[random.randint(0, 5) for _ in range(size)] for _ in range(size)]
print(*grid, sep="\n")
# first value is base score, second is effective score (with multiplier)
solution = [[(x, x) for x in row] for row in grid]
for i in range(1, size):
for k in range(size):
# the 2 or 3 values in the previous line
prev_values = solution[i-1][max(0, k-1):k+2]
val = grid[i][k]
if val == 0:
# multiply
base, mult = max(prev_values, key=lambda t: t[0] + t[1])
solution[i][k] = (base, base + mult)
else:
# add
base, mult = max(prev_values, key=lambda t: t[1])
solution[i][k] = (val + base, val + mult)
print(*solution, sep="\n")
print(max(solution[-1], key=lambda t: t[1]))
Example: The random 5x5 grid, with 0 corresponding to *:
[4, 4, 1, 2, 1]
[2, 0, 3, 2, 0]
[5, 1, 3, 4, 5]
[0, 0, 2, 4, 1]
[1, 0, 5, 2, 0]
The final solution grid with base values and effective values:
[( 4, 4), ( 4, 4), ( 1, 1), ( 2, 2), ( 1, 1)]
[( 6, 6), ( 4, 8), ( 7, 7), ( 4, 4), ( 2, 4)]
[( 9, 13), ( 5, 9), ( 7, 11), (11, 11), ( 9, 9)]
[( 9, 22), ( 9, 22), ( 9, 13), (11, 15), (12, 12)]
[(10, 23), ( 9, 31), (14, 27), (13, 17), (11, 26)]
Thus, the best solution for this grid is 31 from (9, 31). Working backwards through the grid solution grid, this corresponds to the path 0-0-5-0-4, i.e. 3*5 + 4*4 = 31, as there are 2 * before the 5, and 3 * before the 4.
Given n rounds, print all possible permutations to rock paper scissor using a stack as the main strategy.
I use to know how to do this, but I'm stump after not having exercise stacks for a while.
Can someone provide a helpful hint as to how the stack should be populated?
I know there are 3^n outputs for n input.
For n = 1, the expected answer is 3. A possible solution would be:
def rps(n)
stack = []
answer = []
if n > 0
stack.push([r,p,s])
n -= 1
while !stack.isEmpty()
array = stack.pop();
forEach elem in array
// I still can't figure out where to go from here!!
I know in the recursive solution, it'll go r,p,s for n=1
for n=2, the answer gets appended with rr, rp, rs, pr, pp, ps, sr, sp, ss
for n=3, it'll be rrr, rrp, rrs, rpr, etc...
From my understanding, we can start with empty stack, and for each permutation pop out of the stack, we append all possibility to the permutation, and add it back to the stack.
Stack s = new Stack();
s.add("");
ArrayList<String> result;
while(!s.isEmpty()){
String v = s.pop();
if(v.length() == n){//All n rounds finished, add to final result
result.add(v);
continue;
}
//Now, add the result of this round to the current permutation.
s.push(v + "r");
s.push(v + "s");
s.push(v + "p");
}
return result;
I generalize this question to finding all permutations of numbers from 0 to N (in this case N is 3). One way to solve this is using recursion:
def rec(stack, used):
if len(stack) == len(L):
print stack
i = stack.pop(-1)
used[i] = 0
return
for i in range(len(L)):
if used[i] == 0:
stack.append(i)
used[i] = 1
rec(stack,used)
if len(stack):
i = stack.pop(-1)
used [i] = 0
else:
return
N = 3
rec([],[0]*N,N)
What we do is we append the first unused item to our list and call the function again (backtracking). When our list is full print that list. This gives all of the possible permutations:
[0, 1, 2]
[0, 2, 1]
[1, 0, 2]
[1, 2, 0]
[2, 0, 1]
[2, 1, 0]
While this method is using a stack but I doubt that it was in fact the intention of the question.
The main idea of the question is Implement a backtrack method to find all permutations of a list in an iterative method. That's where the stack comes in.
We can simply imitate the recursive function by using a stack:
stack = [(0,1)]
used = [1,0,0]
N = 3
def iterative():
while 1:
if len(stack) == N:
print [x[0] for x in stack]
i,x = stack.pop(-1)
used[i] = 0
continue
top = stack.pop(-1)
index = top[1]
for i in range(index,N):
if used[i] == 0:
stack.append( (top[0],i+1) )
stack.append( (i,0) )
used[i] = 1
break
else:
used[top[0]] = 0
if len(stack)==0:
if top[0]+1 < N:
stack.append((top[0]+1,0))
used[top[0]+1] = 1
else:
break
The only difference is recursive functions have some local variables within them that upon resume of their execution they remember them. We can put these local variables in our stack. In this case in addition to the actual item that we put in the list we remember from what value we shoud resume our checking (this is the variable of the for loop in the recursive function). This is what happens:
#[stack] [used]
[(0, 1)] [1, 0, 0]
[(0, 2), (1, 0)] [1, 1, 0]
[(0, 2), (1, 3), (2, 0)] [1, 1, 1]
A new permutation: [0, 1, 2]
[(0, 2), (1, 3)] [1, 1, 0]
[(0, 2)] [1, 0, 0]
[(0, 3), (2, 0)] [1, 0, 1]
[(0, 3), (2, 2), (1, 0)] [1, 1, 1]
A new permutation: [0, 2, 1]
[(0, 3), (2, 2)] [1, 0, 1]
[(0, 3)] [1, 0, 0]
[(1, 0)] [0, 1, 0]
[(1, 1), (0, 0)] [1, 1, 0]
[(1, 1), (0, 3), (2, 0)] [1, 1, 1]
A new permutation: [1, 0, 2]
[(1, 1), (0, 3)] [1, 1, 0]
[(1, 1)] [0, 1, 0]
[(1, 3), (2, 0)] [0, 1, 1]
[(1, 3), (2, 1), (0, 0)] [1, 1, 1]
A new permutation: [1, 2, 0]
[(1, 3), (2, 1)] [0, 1, 1]
[(1, 3)] [0, 1, 0]
[(2, 0)] [0, 0, 1]
[(2, 1), (0, 0)] [1, 0, 1]
[(2, 1), (0, 2), (1, 0)] [1, 1, 1]
A new permutation: [2, 0, 1]
[(2, 1), (0, 2)] [1, 0, 1]
[(2, 1)] [0, 0, 1]
[(2, 2), (1, 0)] [0, 1, 1]
[(2, 2), (1, 1), (0, 0)] [1, 1, 1]
A new permutation: [2, 1, 0]
[(2, 2), (1, 1)] [0, 1, 1]
[(2, 2)] [0, 0, 1]
Finished