All combinations of 2 repetitive elements - python

I would like to know all combinations of 0 and 1 that I can obtain in a determinated length list and defining the number of 0 elements and 1 elements.
Sample:
Length: 4
Number of 0: 2
Number of 1: 2 (this information is length - number of zeroes)
I want to obtain following list:
combination = [[0,0,1,1], [0,1,0,1], [0,1,1,0], [1,0,1,0], [1,0,0,1], [1,1,0,0]]
I have tried with iterations.product, but I can not define the number of 0 and 1.
I did a filter to group all combinations depending on the sum of the list (if sum is 2, I have all the combinations of my sample). However, I need to know all combinations for a length of 106 elements (0s and 1s) and laptop cannot work.

Assuming that your question is: "list all combinations of an equal number
of zeroes and ones for a given number of zeroes".
We use "product" to iterate over all possible sequences of double the length
of the number of zeroes, filtering out all occurrences where zeroes and
ones are not equal (so sum(list) must be equal to number of zeroes).
Print the length of the list.
Repeat to print the actual list.
This will not work well for large number of zeroes.
import itertools
num_zeroes = 2
base_tuple = (0, 1) # * num_zeroes
perms = itertools.product(base_tuple, repeat=2 * num_zeroes)
p2 = itertools.filterfalse(lambda x: sum(x) != num_zeroes, perms)
print(len(list(p2)))
# 6
perms = itertools.product(base_tuple, repeat=2 * num_zeroes)
p2 = itertools.filterfalse(lambda x: sum(x) != num_zeroes, perms)
print(list(p2))
# [(0, 0, 1, 1), (0, 1, 0, 1), (0, 1, 1, 0),
# (1, 0, 0, 1), (1, 0, 1, 0), (1, 1, 0, 0)]

There's actually a very nice recursive solution to the problem of generating all binary strings of length n with exactly k bits set. There are of course n!/(n!k!) such strings.
Let's assume we have a function binaryNK(n, k) which returns the required set. The key observation is that this set can be partitioned into two subsets:
those with a leading 1 followed by each member of binaryNK(n-1, k-1)
those with a leading 0 followed by each member of binaryNK(n-1, k)
Of course, 1 is only valid when k > 0, and 2 is only valid when n > k. The terminating condition is n == 0, at which point we have a solution.
Here's some simple code to illustrate:
def binaryNK(s, n, k):
if n == 0: print(s)
if k > 0: binaryNK(s+"1", n-1, k-1)
if n > k: binaryNK(s+"0", n-1, k)
binaryNK("", 5, 2)
Output:
11000
10100
10010
10001
01100
01010
01001
00110
00101
00011

Related

How to generate all possible list from given range of list which will target given input sum

Input: Target sum
Output: count of all possible permutations with given sum from list [1,2,3]
Example input: 4 and corresponding output: 7
All possible pairs:
1, 1, 1, 1
1, 2, 1
1, 1, 2
1, 3
2, 1, 1
2, 2
3, 1
For these given permutations for explanation of output these all must be taken from [1,2,3] for any input.
Here is what I've tried so far:
def combinationSum(self, candidates, target):
rests = [[] for _ in range(target)]
for num in candidates:
if num > target:
continue
else:
rests[target - num].append([num])
for cur_rest in range(target - 1, num - 1, -1):
for result in rests[cur_rest]:
rests[cur_rest - num].append(result + [num])
return rests[0]
s=Solution()
c=[1,2,3]
t=int(input())
print(s.combinationSum(c,t))
As per solution suggested by #Tomerikoo, I have created solution with some modification.
def combinationSum(self, candidates, target):
# List for storing possible all sequence of permutations
seq_list = []
# This loop will generate all possible permutation for given candidates
for i in range(1, target + 1):
# Extend given list with cartesian product of given candidates
# To calculate cartesian product set use itertools.product with candidates
# with set size ranging from 1 to target number
# This is necessary as we have to find all possible combinations
seq_list.extend([p for p in itertools.product(candidates, repeat=i)])
# Just select those sequence whose sum is target
result = [seq for seq in seq_list if sum(seq) == target]
# Return length of result set
return len(result)
s=Solution()
c=[1,2,3]
t=int(input())
print(s.combinationSum(c,t))
Hope this help!!!

how can solve this problem with dynamic programming?

Instructions : rat can move just up or right
input:
The first line contains the number of table size n and the number of cheese m.
From the next line, the position x, y of the cheese is given
Output :
The maximum number of cheese to eat
Exemple1:
input : 1 1 1
output : 1 1
Example2:
input :
3 2
1 2
3 1
output : 1
Example 3:
input :
5 5
2 3
3 2
4 3
4 5
5 2
output: 3
how can I solve with python?
I tried
def maxAverageOfPath(table, N):
dp = [[0 for i in range(N)] for j in range(N)]
dp[0][0] = table[0][0]
# Initialize first column of total table(dp) array
for i in range(0, N):
dp[i][0] = 0
for j in range(0, N):
dp[0][j] = 0
for i in range(0, N):
for j in range(0, N):
print(i, j)
if i == N-1 and j == N-1:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
continue
if i == N-1 :
dp[i][j] = table[i][j + 1]
continue
if j == N-1 :
dp[i][j] = table[i + 1][j]
continue
dp[i][j] = max(table[i + 1][j], table[i][j + 1])
return dp
but failed...
For dynamic programming you want an edge condition(s) and a way to score where you are right now. After that it's more-or-less smart brute force. The smart part comes from memoizing so you don't repeat work.
Here's a basic recursive approach for python that does the following:
Organize table of cheese as a frozen set of tuples. This can be hashed for memoization and you can determine of a location is in the set in constant time.
Creates an edge condition for the end (when both coordinates are N) and an edge condition for when you walk off the map -- that just returns 0.
Uses lru_cache to memoize. You can implement this yourself easily.
from functools import lru_cache
def hasCheese(table, location):
''' Helper function just to improve readability '''
return 1 if location in table else 0
#lru_cache()
def maxC(table, N, location = (0, 0)):
# edge conditions final square and off the grid:
if location[0] == N and location[1] == N:
return hasCheese(table, location)
if any(l > N for l in location):
return 0
# recursion
score_here = hasCheese(table, location)
return max(score_here + maxC(table, N, (location[0] + 1, location[1])),
score_here + maxC(table, N, (location[0], location[1] + 1))
)
t = frozenset([(2, 3), (3, 2), (4, 3), (4, 5), (5, 2)])
N = 5
print(maxC(t, N))
# prints 3
If you want to do this in a top-down manner using a matrix, you need to be very careful that you always have the previous index set. It's easier to make mistakes doing it this way because you need to get the indexes and order just right. When you set it up as two nested increasing loops, that means the next value is always the current cell plus the max of the two cells one unit less — you should always be looking backward in the matrix. It's not clear what you are trying to do when you are looking forward with this:
dp[i][j] = table[i][j + 1]
because j+1 has not been determined yet.
Since the cheese coordinates are 1 indexed, an easy way forward is to make your matrix zero indexed and N+1 in size. Then when you start your for loops at 1 you can always look and at lower index without undershooting the matrix and avoid a lot of the if/else logic. For example:
def hasCheese(table, location):
''' Helper function just to improve readability '''
return 1 if location in table else 0
def maxAverageOfPath(table, N):
# matrix is sized one unit bigger
dp = [[0 for i in range(N+1)] for j in range(N+1)]
# iterate 1-5 inclusive
for i in range(1, N+1):
for j in range(1, N+1):
# because the zeroth row and column are already zero, this works without undershooting the table
dp[i][j] = hasCheese(table, (i, j)) + max(dp[i][j-1], dp[i-1][j])
# solution is in the corner
return dp[N][N]
t = {(2, 3), (3, 2), (4, 3), (4, 5), (5, 2)}
N = 5
print(maxAverageOfPath(t, N)) #3
When you'r done your matrix will look like:
[0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 1, 1]
[0, 0, 1, 1, 1, 1]
[0, 0, 1, 2, 2, 3]
[0, 0, 2, 2, 2, 3]
Your starting point is at (1, 1) starting in the top-right and your answer is the bottom left corner.
At each point you have two options to move further :
array [row] [col+1]
array [row+1] [col]
As we have to find out a path which involves max cheese.
It can be achived by recurring through the array like below to solve the same:
Solution =>
array [i] [j] + Max(Recur(array [i] [j+1]), Recur(array [i+1] [j]));

How to choose specific minimum values in lists and do mathematical operations on them

After getting data from user input I put the input in lists like this:
x= [3, 2, 1, 0, 1, 2]
y= [1, 2, 0, 3, 4, 1]
I have manged to write this as:
rows = 3
weight = 0
high =0
low =0
while rows>=3 and rows<=200:
rows, weight = map(int, input().split())
break
count_input = 0
while count_input<rows:
while high>=0 and low<=100:
high, low = map(int, input().split())
i=i+1
if count_input==rows:
break
To choose the minimum number in a list i tried this:
smallest = None
for number in [1, 0, 3, 4, 5, 2]:
if smallest is None or number < smallest:
smallest = number
print('Smallest:', smallest)
my questions are:
How to determine minimum values in these two lists and add minimum values together BUT taking into account that selected minimum values of same positions like x[0] and y[0], or x[1] and y[1] can not be added together.
Elements in diagonal position to each other like x[0] and y[1], x[2] and y[3] can not be added together
Also How to put a limit for number of chosen values, like choosing the minimum 4 values found in lists together
This is how I would approach finding the minimum of the data set, with the logic for not using values between the lists if they have the same index or a diagonal index
x = [3, 2, 1, 0, 1, 2]
y = [1, 2, 0, 3, 4, 1]
final_min = max(x) + max(y)
for x_index in range(0, len(x)):
for y_index in range(0, len(y)):
if y_index == x_index - 1 or y_index == x_index or y_index == x_index + 1:
pass
else:
test_min = x[x_index] + y[y_index]
if test_min < final_min:
print(test_min) # prints 3, 2, 1
final_min = test_min
print(final_min) # prints 1
This makes sense by visually looking at the data, as there are 3 places that the sum would be 1, and the only place it could be smaller (0) would be 0 + 0 but that is a diagonal pair so it cannot be included. You should keep in mind that this is a computationally expensive approach though because it iterates through the y list for every index in the x list, and if your lists are large this will take a LONG time! Also, if the lists are different lengths then the program will likely hit an IndexError and I have not included safeguards for that. I cannot help you on your final point because I do not understand what is meant by:
How to put a limit for number of chosen values, like choosing the minimum 4 values found in lists together
You would need to clarify for anybody to understand what is meant here.
Use min(..) and index(..).
This solution may not be entirely correct, but you get the idea...
def add_min_with_constraints(a, b):
if len(a) == 0 or len(b) == 0:
return -math.inf
min_a_i = a.index(min(a))
min_b_i = b.index(min(b))
if min_a_i == min_b_i or abs(min_a_i - min_b_i) == 1: # same or diagonal indices
# exclude the current minimums
return add_min_with_constraints(a[:min_a_i] + a[min_a_i+1:],
b[:min_b_i] + b[min_b_i+1:])

If numbers in list are equal to n, print out their indices

The Task:
You are given two parameters, an array and a number. For all the numbers that make n in pairs of two, return the sum of their indices.
input is: arr = [1, 4, 2, 3, 0, 5] and n = 7
output: 11
since the perfect pairs are (4,3) and (2,5) with indices 1 + 3 + 2 + 5 = 11
So far I have this, which prints out the perfect pairs
from itertools import combinations
def pairwise(arr, n):
for i in combinations(arr, 2): # for index in combinations in arr, 2 elements
if i[0] + i[1] == n: # if their sum is equal to n
print(i[0],i[1])
Output:
4,3 2,5
However does anyone has tips on how to print the indices of the perfect pairs? Should I use numpy or should I change the whole function?
Instead of generating combinations of array elements you can generate combinations of indices.
from itertools import combinations
def pairwise(arr, n):
s = 0
for i in combinations(range(len(arr)), 2): # for index in combinations in arr, 2 elements
if arr[i[0]] + arr[i[1]] == n: # if their sum is equal to n
# print(arr[i[0]],arr[i[1]])
# print(i[0],i[1])
s += i[0] + i[1]
# print(s)
return s
You can use a dictonary mapping the indexes:
def pairwise(arr, n):
d = {b:a for a,b in enumerate(arr)} #create indexed dict
for i in combinations(arr, 2): # for index in combinations in arr, 2 elements
if i[0] + i[1] == n: # if their sum is equal to n
print(d[i[0]],d[i[1]])
Here you have a live example
Rather than generating combinations and checking if they add up to n, it's faster to turn your list into a dict where you can look up the exact number you need to add up to n. For each number x you can easily calculate n - x and then look up the index of that number in your dict.
This only works if the input list doesn't contain any duplicate numbers.
arr = [1, 4, 2, 3, 0, 5]
n = 7
indices = {x: i for i, x in enumerate(arr)}
total = 0
for i, x in enumerate(arr):
remainder = n - x
if remainder in indices:
idx = indices[remainder]
total += i + idx
# the loop counts each pair twice (once as [a,b] and once as [b,a]), so
# we have to divide the result by two to get the correct value
total //= 2
print(total) # output: 11
If the input does contain duplicate numbers, you have rewrite the code to store more than one index in the dict:
import collections
arr = [1, 4, 2, 3, 0, 5, 2]
n = 7
indices = collections.defaultdict(list)
for i, x in enumerate(arr):
indices[x].append(i)
total = 0
for i, x in enumerate(arr):
remainder = n - x
for idx in indices[remainder]:
total += i + idx
# the loop counts each pair twice (once as [a,b] and once as [b,a]), so
# we have to divide the result by two to get the correct value
total //= 2
You should use the naive approach here:
process each element of the array with its indice
for each element test for all elements after this one (to avoid duplications) whether their sum is the expected number and if it is add the sum of their indices
Code could be:
def myfunc(arr, number):
tot = 0
for i, val in enumerate(arr):
for j in range(i+1, len(arr)):
if val + arr[j] == number:
tot += i + j
return tot
Control:
>>> myfunc([1, 4, 2, 3, 0, 5], 7)
11
>>> myfunc([2, 4, 6], 8)
2

The number of ways to find unique numbers that sum to a number in Python

This is the description of the problem:
There is a list of integers, sequence. There is another integer argument, target. The objective is to return the number of unique ways target can be expressed as the sum of four distinct numbers in sequence.
This is my code:
def __main__(sequence, target):
big = 0
for elem in sequence:
for elem_ in sequence:
for _elem_ in sequence:
for _elem__ in sequence:
if (elem + elem_ + _elem_ + _elem__ == target):
big+=1
print(str(big))
__main__([2, 1, 1, 1, 2, 1, 2, 2, 1], 6)
The algorithm seems fine to me. But I keep getting the answer 2400 for this, when according to the test case, the answer should be 60. I suspect I'm going over one method four times, but then again dividing 2400 by 4 does not give you 60.
You can use itertools.combinations():
import itertools
def sums(lst, n):
count = 0
for sample in list(itertools.combinations(lst, 4)):
if sum(sample) == n:
count += 1
return count
print(sums([2, 1, 1, 1, 2, 1, 2, 2, 1], 6)) # => 60
From the docs:
Return r length subsequences of elements from the input iterable.
Combinations are emitted in lexicographic sort order. So, if the input iterable is sorted, the combination tuples will be produced in sorted order.
Elements are treated as unique based on their position, not on their value. So if the input elements are unique, there will be no repeat values in each combination.
combinations(range(4), 3) # --> 012 013 023 123
Here's one way to do it:
def sums(sequence, target):
n = len(sequence)
total = 0
for i1 in range(n):
v1 = sequence[i1]
for i2 in range(i1+1, n):
v2 = sequence[i2]
for i3 in range(i2+1, n):
v3 = sequence[i3]
for i4 in range(i3+1, n):
v4 = sequence[i4]
if v1+v2+v3+v4 == target:
total += 1
return total
def main():
print(sums([2, 1, 1, 1, 2, 1, 2, 2, 1], 6))
main()
This ensures that each list element is used at most once, and gives the desired result of 60.
The looping is a little less concise than I'd like, but it's efficient, and doesn't require any temporary list slices.

Categories