Python3 itertools permutation & combination question - python-3.x

I want to build a combination of all 7-digit numbers possible from a set of numbers following the rules below.
Each digit can only hold values as shown below from python3 list variables N1-N7 as an example.
N1 = [0,1,2]
N2 = [0,1]
N3 = [0,1,2]
N4 = [0]
N5 = [1]
N6 = [0,1]
N7 = [0]
Total of all the digits in any of the 7-digit numbers should be exactly 5. Valid examples of the 7-digit numbers.
0120110,1110110,1120100,2020100

You can use the Cartesian product method of the itertools library,
Basically it generates all possible combinations of each group.
For example,
import itertools
list(itertools.product([1,2], ['a', 'b']))
Should return:
[(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
Applying it to your constraint that we need to pick the first digit from N1, second digit from N2 etc...
result = [''.join(map(str, combination)) for combination in itertools.product(N1, N2, N3, N4, N5, N6, N7)]
This does not enforce that the sum will be equal to five, so we can add it with a simple if statement:
result = [''.join(map(str, cartesian_product)) for cartesian_product in itertools.product(N1, N2, N3, N4, N5, N6, N7) if sum(cartesian_product) == 5]
Resulting in:
['0120110', '1020110', '1110110', '1120100', '2010110', '2020100', '2100110', '2110100']

Related

Sum of two square matrixes code keeps failing

I have this task: 'Write a program that adds two square matrices. The program will read the dimension of the matrix, N, and will then read N*N numbers representing the first matrix, row by row. It will then read another N*N numbers representing the second matrix. The program will output the resulting matrix, one row per line. ' for which I wrote the code below. However, the platform I am doing the task on keeps saying that 1 of 2 tests failed...It works just fine for me. Maybe the problem is on their side?
from operator import add
#Enter a digit for you matrix, e.g if you want it to be 2x2 enter 2
n = int(input())
#Input digits for both matrixes rows one at a time
matrix1_r1 = [int(input()) for x in range(n)]
matrix1_r2 = [int(input()) for x in range(n)]
matrix2_r1 = [int(input()) for x in range(n)]
matrix2_r2 = [int(input()) for x in range(n)]
final1 = list(map(add, matrix1_r1, matrix2_r1))
final2 = list(map(add, matrix1_r2, matrix2_r2))
print(final1)
print(final2)
Their sample innput is:
2
1
2
3
4
5
6
7
8
their sample output is:
[6, 8]
[10, 12]
Your code works for the example, and for any input that is 2 by 2. It will fail for any other sized matrix, because your code only computes two rows for each matrix. Rather than hard-coding something so fundamental, you should be using nested loops and a list of lists to get the right number of rows. Or, if you want to be a little fancy, list comprehensions can do it all really neatly:
n = int(input())
matrix1 = [[int(input()) for col in range(n)] for row in range(n)]
matrix2 = [[int(input()) for col in range(n)] for row in range(n)]
matrix_sum = [[a + b for a, b in zip(row1, row2)] for row1, row2 in zip(matrix1, matrix2)]
print(*matrix_sum, sep='\n')

Finding x numbers in list greater than 0 with potential duplicates and assigning index of original list

I have lists of floats which will have some zeros in it. Eg.
numbers = [1.2, 0.0, 0.0, 1.2, 2.0, 2.5, 17, 1.3, 1.8, 1.3, 1.2]
I am trying to assign these values to n numbers (assuming it will be the first 5) for the lowest 5 values that are greater than 0.
I can get the first by using:
first = min(o for o in numbers if o > 0)
But as there are duplicates in the smallest value (1.2), I cannot easily assign second, third, fourth and fifth.
I need to assign these and allow me to keep the index of their values in the original list and assign these too. Eg.
first_pos = numbers.index(first)
I cannot use the above for second as it will assign it the first index value.
Is there any efficient way using a for loop or list comprehension or even a small function to assigning the other numbers so that:
second = 1.2
second_pos = 4
third = 1.2
third_pos = 10
fourth = 1.3
fourth_pos = 7
fifth = 1.3
fifth_pos = 9
I cannot do this with any list comprehension I know of for second as it will not pick up a duplicate. Eg.:
sec = min(o for o in numbers if o > first)
The lists vary in length of values (at least 5, though) and may or may not have duplicates and zeros but many will.
IIUC, one way using sorted with enumerate:
sorted(((n, i) for n, i in enumerate(numbers) if i > 0), key=lambda x: x[1])[:5]
Output of (index, value) pairs of first 5 smallest values:
[(0, 1.2), (3, 1.2), (10, 1.2), (7, 1.3), (9, 1.3)]
Ok, to badly answer my own question, I have been able to do this by copying and removing the zeros, enumerating over the list for the index values and removing each number once assigned:
number = [n for n in numbers if n > 0]
numbs = [n for n, x in enumerate(numbers) if x > 0]
for n in number:
first = min(number)
first_pos = number.index(first)
first_ind = numbs[first_pos]
number.remove(first)
numbs.remove(first_ind)
for n in number:
second = min(number)
sec_pos = number.index(second)
sec_ind = numbs[sec_pos]
number.remove(second)
numbs.remove(sec_ind)
This will keep and assign the values and indexes of each minimum value greater than zero.
Is there any way to add this into a function to assign all values greater than zero in the list to its own variables?

Iterate through Pandas dataframe rows in a triangular fashion

I have a Pandas dataframe df like this:
col1. col2
0. value11 List1
1. value12 List2
2. value13. List3
.. ... ...
i. value1i. List_i
j. value1j. List_j
.. ... ...
Col1 is the key (it does not repeat). Col2 is a list. In the end, I want a set intersection of each of the rows of Col2.
I would like to iterate through this dataframe in a triangular fashion.
Something along the lines of:
for i = 0 ; i < len(df); i++
for j = i+1 ; j < len(df) ; j++
Set(List_i).intersect(Set(List_j)
So, 1st iterator goes through the full dataframe, while the second iterator, starts from one greater index than the 1st iterator and goes until the end of the dataframe.
How to do this efficiently and in a fast manner?
Edit:
Naive way of doing this is:
col1_list = list(set(df.col1))
num_col1_entries = len(col1_list)
for idx, value1 in enumerate(col1_list):
for j in range(idx + 1, num_col1_entries):
value2 = col1_list[j]
list1 = df.loc[df.col1 == value1]['col2']
list2 = df.loc[df.col2 == value2]['col2']
print(set(list1).intersection(set(list2)))
Expected output: n(n-1)/2 prints of set intersections of each pair of rows of col2.
You can use itertools. Let's say this is your dataframe:
col1. col2
0 value11 List1
1 value12 List2
2 value13 List3
3 value14 List4
4 value15 List5
5 value16 List6
Then get al the combinations (15) and print the intersection between the two lists:
from itertools import combinations
for pair in list(combinations(df.index, 2)):
print(pair)
list1 = df.iloc[pair[0],1]
list2 = df.iloc[pair[1],1]
print(set(list1).intersection(set(list2)))
Output (only printing the pair):
(0, 1)
(0, 2)
(0, 3)
(0, 4)
(0, 5)
(1, 2)
(1, 3)
(1, 4)
(1, 5)
(2, 3)
(2, 4)
(2, 5)
(3, 4)
(3, 5)
(4, 5)

Need help understanding code execution, for nested for loop

I have trouble understanding the element wise execution of the following code. The goal is to define a function, that returns the cartesian product of 2 sets. The problem should be solved using the methods in the code below.
I have tried looking up similar problems, but since i am new to programing and python i get stuck easy.
A = {1,2,3,4}
B = {3,4,5}
def setprod(m1,m2):
p=set()
for e1 in m1:
for e2 in m2:
p.add((e1,e2))
return p
setprod(A,B) returns {(1, 3), (3, 3), (4, 5), (4, 4), (1, 4), (1, 5), (2, 3), (4, 3), (2, 5), (3, 4), (2, 4), (3, 5)} The cartesian product is the set containing all the ordered pairs of elements of the two sets. The elements in A can be choosen 4 diffrent ways and B 3 giving 4x3=12 combinations.
I just can`t see why the code above accomplishes this.
If you have access to a debugging tool (perhaps you could install pycharm and use its debugger) you can see what's going on.
Let's step through what's going on in the code together mentally.
A = {1,2,3,4} #Step 1, load a set (1,2,3,4)
B = {3,4,5} #Step 2, load a set (3,4,5)
def setprod(m1,m2): #Step 4, define the function
p=set()
for e1 in m1:
for e2 in m2:
p.add((e1,e2))
return p
setprod(A,B) #Step 5, execute function with parameters
At this point if we want to see what setprod does we step into the function.
p=set() #Steppedin, step 1 create empty set
for e1 in m1: #Steppedin, step 2, begin forloop iterating through m1,
#which contains (1,2,3,4); e1 is set to 1
for e2 in m2: #Steppedin, step 3 begin inner for loop
#iterating through m2, which contains (3,4,5),
#e2 is set to 3, e1 contains the value 1
p.add((e1,e2)) #Stepped in, step 4. add (m1[0],m2[0]), represented by
# (e1,e2) to the set.
return p
At stepped in step 4, the next step is the same line of code but with different register values, e2 is no longer m2[0] but m2[1]
p.add((e1,e2)) #Stepped in, step 5. add (m1[0],m2[1]), represented by
# (e1,e2) to the set where e1 = 1 and e2 = 4
.
p.add((e1,e2)) #Stepped in, step 6. add (m1[0],m2[2]), represented by
# (e1,e2) to the set where e1 = 1 and e2 = 5
At this point we return to the parent for loop.
for e1 in m1: #Stepped in, step 7.
#use m1[1] as e1 and repeat previous process but
#with the new e1 value set to 2
for e2 in m2: #Stepped in, step 8. e1 contains 2, e2 is set to 3
p.add((e1,e2))
(Just a note, if you were debugging this, I believe you'll only see the values for e2 and e1 when you are at the section of the code p.add, saying that e1 is set to some value at #stepped in, step 7, isn't completely accurate but is helpful enough for looking at the idea of what is happening.)

how can i calculate the ratio in a data frame for all sub levels between two categories

I am trying to calculate ratio of values for every sub category in a dataframe which has two levels of index
Using python 3 and pandas
arrays = [np.array(['numerator', 'numerator', 'denominator', 'denominator']),
np.array(['A', 'B', 'A', 'B' ])]
df = pd.DataFrame(np.random.randn(10, 4), index=[n for n in range(10)], columns=arrays)
numerator denominator
A B A B
0 0.021060 0.150265 -0.798771 0.676246
1 0.490758 -0.310325 -1.632090 -1.246260
Want to add another index 'Ratio' which will have the same two levels [A and B] and will have the ratio as the value. i.e.
['Ratio']['A'] = ['numerator']['A']/['denominator']['A']
['Ratio']['B'] = ['numerator']['B']/['denominator']['B']
Want to do this with a clean code since i need to do this with cases where I can have more levels in the second index i.e. A, B, C, D...

Resources