Generate all combinations of a list of n^2 elements with each element being from 1 to n? - python-3.x

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.

Related

How are Tuple Priority Queue Organised?

Context I am using A Star to go through a maze. Using a 2 by 2 maze as an example below is how the coordinates will be put into a priority queue.
from queue import PriorityQueue
PQ = PriorityQueue()
PQ.put(2, 2, (2,2))
PQ.put(2, 1, (1,2))
PQ.put(2, 1, (2,1))
Is my understanding of how the elements in the priority queue will be organized correctly?
Check if the first entry of the tuple is smaller
(2, 2, (2,2)) vs (2, 1, (1,2)) vs (2, 1, (2,1)) =
2 < 2 < 2 = not true, no change to current order
Check if the second entry is smaller
2 > 1 & 1 = 1
Current order = (2, 1, (1,2)), (2, 1, (2,1)), (2, 2, (2,2))
Check if the third entry is smaller
1 > 2 & 2 = 2 no change to current order
Will it go on to check the fourth entry?
Also is there a way to print all the items in my priority queue?
using print(PQ.queue) outputs [2, 2, 2]

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.

Sort list of tuples based on multiple criteria

Given a list of tuples, [(x, y, z), ....., (x_n, y_n,z_n)], x, y are nonnegative number and z is either 0 or 1, I want to sort the list based on the following three criteria-
if x_i != x_j, sort on ascendening order of x(tuple[0])
if x_i == x_j and z_i != z_j, sort on ascendening order of z(tuple[2])
if x_i == x_j and z_i == z_j and z_i == 0, sort on descending order of y(tuple[1])
if x_i == x_j and z_i == z_j and z_i == 1, sort on ascending order of y(tuple[1])
Input: [(1, 1, 0), (2, 1, 1), (1, 2, 0), (2, 2, 1), (1, 3, 0), (2, 3, 1)]
output:[(1, 3, 0), (1, 2, 0), (1, 1, 0), (2, 1, 1), (2, 2, 1), (2, 3, 1)]
Since Python 3 does not support custom comparator function for sort as I know for JAVA, I do not know how to incorporate the above three criteria in the sort method.
I can sort based on the two criteria (either 1,2 or 1,3) of the above-mentioned criterion. Adding the third criteria makes one of 2 or 3 invalid. I am adding my code here-
points.sort(key=lambda p: p[2])
points.sort(key=lambda p: p[1], reverse=True)
points.sort(key=lambda p: p[0])
OUTPUT: [(1, 3, 0), (1, 2, 0), (1, 1, 0), (2, 3, 1), (2, 2, 1), (2, 1, 1)] (criteria 3 not satisfied)
Can anybody suggest, what should be the value of key argument in this situation? Thanks
Just encoding your criteria...
points.sort(key=lambda p: (p[0], p[2], p[1] if p[2] else -p[1]))
If you have truly ridiculously complicated sorting rules, you can just write a comparator function, then use functools.cmp_to_key to make it into a valid key argument. So write your insane comparator function, add from functools import cmp_to_key to the top of your file, then do:
points.sort(key=cmp_to_key(my_insane_comparator))
and it will work as expected. All cmp_to_key really does is make a custom class with a custom __lt__ (less than operator) that performs the work of the comparator in the __lt__ on each comparison.

How do I create a rollover counter within a list in Python?

I need to build a rollover counter within a list in python. Given a starting list of a variable length startlist, and all terms minnum, the counter should increment index 0 by one until it reaches maxnum, at which point index 0 resets to minnum and index one increments by one. This continues until all terms of the list are maxnum, at which point the loop should end. Here is an example.
minnum = 1, maxnum = 2, startlist = [1, 1, 1] The counting begins. [1, 1, 1] -> [2, 1, 1] -> [1, 2, 1] -> [2, 2, 1] -> [1, 1, 2] -> [2, 1, 2] -> [1, 2, 2] -> [2, 2, 2] -> end
I have tried a lot of code but nothing seems to work. If someone could please help me out with this that would be much appreciated.
Maybe you can use itertools:
from itertools import product
def main():
minimum = 1
maximum = 2
num_counters = 3
# Build the counter values iterable object
counter_range = range(minimum, maximum+1)
# Build the cartesian product of your counters.
# You have to reverse the generated tuples to make it match your requirements
counters = [tuple(reversed(x)) for x in product(counter_range, repeat=num_counters)]
print(counters)
if __name__ == '__main__':
main()
[(1, 1, 1), (2, 1, 1), (1, 2, 1), (2, 2, 1), (1, 1, 2), (2, 1, 2), (1, 2, 2), (2, 2, 2)]

Permutations in python3

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.

Resources