Permutations in python3 - python-3.x

I can't figure out how to get permutations to return the actual permutation and not
I tried a lot of different things to no avail. The code I used was from itertools import permutations and then permutations([1,2,3]). Thanks!

This may not be answering your question (it appears to be missing the part after 'and not'), but from your code, what you are likely seeing is the repr of the itertools.permutations iterator. You can iterate through this object just as you would a normal list in order to access all of the items. If you want to convert it to a list, you can wrap it in list:
>>> from itertools import permutations
>>> permutations([1, 2, 3])
<itertools.permutations object at 0x1e67890>
>>> list(permutations([1, 2, 3]))
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
However as mentioned above, the iterator can be iterated over just like you would a normal list (the benefit of returning an iterator is that the entire sequence is not loaded into memory right away - it is instead loaded 'as needed'):
>>> for perm in permutations([1, 2, 3]):
... print(perm)
...
(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)

itertools.permutations is a generator, which means you have to retrieve results from it by using it like this:
for permutation in itertools.permutations([1,2,3]):
do_stuff_with(permutation)
or alternatively put all of them in a list:
list(itertools.permutations([1,2,3]))
or, less conveniently:
generator = itertools.permutations([1,2,3])
generator.__next__()

from itertools import permutations
#iteration
for p in permutations([1,2,3]):
print(p)
This should work perfectly.

Related

Generate possible combination of values from a list [duplicate]

This question already has answers here:
How to get all possible combinations of a list’s elements?
(32 answers)
Get all combinations of any length without sub-combinations [duplicate]
(1 answer)
Closed 8 months ago.
I have a list which contain values input = [1, 2, 3] and would need all the possible combination of this values i.e. Output = [[], [1], [2], [3], [1,2], [1,3], [2, 3], [1,2,3]].
I have used below code but it is not showing exact output values.
output = permutations([1, 2, 3], 2)
for i in output:
print(list(i))
Can someone help me with this?
From the output you're giving, it seems you want the combinations and not the permutations.
You can iterate over all possible valid lengths (0 to 3) and create a sequence like that.
import itertools as it
list(it.chain.from_iterable(it.combinations([1, 2, 3], i) for i in range(4)))
will output:
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]

List of list to get element whose values greater than 3

I have 2 list where each list is of size 250000. I wanted to iterate thru the lists and return the values that are greater than 3.
For example:
import itertools
from array import array
import numpy as np
input = (np.array([list([8,1]), list([2,3,4]), list([5,3])],dtype=object), np.array([1,0,0,0,1,1,1]))
X = input[0]
y = input[1]
res = [ u for s in X for u in zip(y,s) ]
res
I don't get the expected output.
Actual res : [(1, 8), (0, 1), (1, 2), (0, 3), (0, 4), (1, 5), (0, 3)]
Expected output 1 : [(8,1), (1,0), (2, 0), (3, 0), (4, 1), (5, 1), (3, 1)]
Expected output 2 : [(8,1), (4, 1), (5, 1))] ---> for greater than 3
I took references from stackoverflow. Tried itertools as well.
Using NumPy to store lists of non-uniform lengths creates a whole lot of issues, like the ones you are seeing. If it were an array integers, you could simply do
X[X > 3]
but since it is an array of lists, you have to jump through all sorts of hoops to get what you want, and basically lose all the advantages of using NumPy in the first place. You could just as well use lists of lists and skip NumPy altogether.
As an alternative I would recommend using Pandas or something else more suitable than NumPy:
import pandas as pd
df = pd.DataFrame({
'group': [0, 0, 1, 1, 1, 2, 2],
'data': [8, 1, 2, 3, 4, 5, 4],
'flag': [1, 0, 0, 0, 1, 1, 1],
})
df[df['data'] > 3]
# group data flag
# 0 0 8 1
# 4 1 4 1
# 5 2 5 1
# 6 2 4 1
Use filter
For example:
input = [1, 3, 2, 5, 6, 7, 8, 22]
# result contains even numbers of the list
result = filter(lambda x: x % 2 == 0, input)
This should give you result = [2, 6, 8, 22]
Not sureI quite understand exactly what you're trying to do... but filter is probably a good way.

Generate all combinations of a list of n^2 elements with each element being from 1 to n?

I am trying to enumerate the number of valid sudokus of a given size. I have a function that takes a sudoku transformed into a list as input and checks to see if it is a valid sudoku or not. My original method was just to write nested for loops to check every single combination of a list. For a 2 x 2 sudoku, my code looks something like this:
def enumerate2x2():
cnt = 0
for i1 in range(1,3):
for i2 in range(1,3):
for i3 in range(1,3):
for i4 in range(1,3):
if checkValidSudoku([i1, i2, i3, i4]):
cnt += 1
print(cnt)
This code just generates every possible combination of a 4-element list (that's how many squares are in a 2x2 sudoku) with each element in the list being either a 1 or a 2. It then checks each combination.
However, when trying this on a 5x5 sudoku i ran into a problem as python only allows you to have 20 nested loops, so I want to generalize this ugly method into something that will work with any size sudoku. Any help would be appreciated.
The Python product intrinsic function, just importing the itertools module, is what you need:
import itertools
sudoku = list(itertools.product(range(1,3), repeat=4))
for x in range(len(sudoku)):
print sudoku[x]
that simply calculate all the cartesian products, you were looking for, here below the output:
(1, 1, 1, 1)
(1, 1, 1, 2)
(1, 1, 2, 1)
(1, 1, 2, 2)
(1, 2, 1, 1)
(1, 2, 1, 2)
(1, 2, 2, 1)
(1, 2, 2, 2)
(2, 1, 1, 1)
(2, 1, 1, 2)
(2, 1, 2, 1)
(2, 1, 2, 2)
(2, 2, 1, 1)
(2, 2, 1, 2)
(2, 2, 2, 1)
(2, 2, 2, 2)
it seems no combination is now missing, isn't it? Have a look at this other question Combinations with repetition in python, where order MATTERS for more details on alternative implementation too.

Efficient way to loop through orthodiagonal indices in order

I wanted to find a better way to loop through orthodiagonal indices in order, I am currently using numpy but I think I'm making an unnecessary number of function calls.
import numpy as np
len_x, len_y = 50, 50 #they don't have to equal
index_arr = np.add.outer(np.arange(len_x), np.arange(len_y))
Currently, I am looping through like this:
for i in range(np.max(index_arr)):
orthodiag_indices = zip(*np.where(index_arr == i))
for index in orthodiag_indices:
# DO FUNCTION OF index #
I have an arbitrary function of the index tuple, index and other parameters outside of this loop. It feels like I don't need the second for loop, and I should be able to do the whole thing in one loop. On top of this, I'm making a lot of function calls from zip(*np.where(index_arr == i)) for every i. What's the most efficient way to do this?
Edit: should mention that it's important that the function applies to index_arr == i in order, i.e., it does 0 first, then 1, then 2 etc. (the order of the second loop doesn't matter).
Edit 2: I guess what I want is a way to get the indices [(0,0), (0,1), (1,0), (2,0), (1,1), (2,0), ...] efficiently. I don't think I can apply a vectorized function because I am populating an np.zeros((len_x, len_y)) array, and going back to the first edit, the order matters.
You could use tril/triu_indices. Since the order of the (former) inner loop doesn't matter dimensions can be swapped as needed, I'll assume L>=S:
L,S = 4,3
a0,a1 = np.tril_indices(L,0,S)
b0,b1 = np.triu_indices(S,1)
C0 = np.concatenate([a0-a1,b0+L-b1])
C1 = np.concatenate([a1,b1])
*zip(C0,C1),
# ((0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (3, 0), (2, 1), (1, 2), (3, 1), (2, 2), (3, 2))
I think itertools.product() will be of use here
import itertools as it
x,y = 2,3
a=list(it.product(range(x),range(y))
which gives a as
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]
If you need them in order then,
b=np.argsort(np.sum(a,1))
np.array(a)[b]
which gives,
array([[0, 0],
[0, 1],
[1, 0],
[0, 2],
[1, 1],
[1, 2]])
Hope that helps!

Selecting sublists of a list of lists to define a relation

If I happen to have the following list of lists:
L=[[(1,3)],[(1,3),(2,4)],[(1,3),(1,4)],[(1,2)],[(1,2),(1,3)],[(1,3),(2,4),(1,2)]]
and what I wish to do, is to create a relation between lists in the following way:
I wish to say that
[(1,3)] and [(1,3),(1,4)]
are related, because the first is a sublist of the second, but then I would like to add this relation into a list as:
Relations=[([(1,3)],[(1,3),(1,4)])]
but, we can also see that:
[(1,3)] and [(1,3),(2,4)]
are related, because the first is a sublist of the second, so I would want this to also be a relation added into my Relations list:
Relations=[([(1,3)],[(1,3),(1,4)]),([(1,3)],[(1,3),(2,4)])]
The only thing I wish to be careful with, is that I am considering for a list to be a sublist of another if they only differ by ONE element. So in other words, we cannot have:
([(1,3)],[(1,3),(2,4),(1,2)])
as an element of my Relations list, but we SHOULD have:
([(1,3),(2,4)],[(1,3),(2,4),(1,2)])
as an element in my Relations list.
I hope there is an optimal way to do this, since in the original context I have to deal with a much bigger list of lists.
Any help given is much appreciated.
You really haven't provided enough information, so can't tell if you need itertools.combinations() or itertools.permutations(). Your examples work with itertools.combinations so will use that.
If x and y are two elements of the list then you just want all occurrences where the set(x).issubset(y) and the size of the set difference is <= 1 - len(set(y) - set(x)) <= 1, e.g.:
In []:
[[x, y] for x, y in it.combinations(L, r=2) if set(x).issubset(y) and len(set(y)-set(x)) <= 1]
Out[]:
[[[(1, 3)], [(1, 3), (2, 4)]],
[[(1, 3)], [(1, 3), (1, 4)]],
[[(1, 3)], [(1, 2), (1, 3)]],
[[(1, 3), (2, 4)], [(1, 3), (2, 4), (1, 2)]],
[[(1, 2)], [(1, 2), (1, 3)]],
[[(1, 2), (1, 3)], [(1, 3), (2, 4), (1, 2)]]]

Resources