Grid Permutation Algorithm - Fixed Row Order - python

Imagine a 3x3 grid:
[A, B, %]
[C, %, D]
[E, F, G]
The percentages % stand for empty spaces/positions.
The rows can be moved like beads on a string, such that the permutations for the configurations for the first row could be any one of:
[A, B, %] or [A, %, B] or [%, A, B]
Similarly for the second row. The third row contains no empty slots and so cannot change.
I am trying to produce all possible grids, given the possible permutations of each row.
The output should produce the following grids:
[A, B, %] [A, B, %] [A, B, %]
[C, D, %] [C, %, D] [%, C, D]
[E, F, G] [E, F, G] [E, F, G]
[A, %, B] [A, %, B] [A, %, B]
[C, D, %] [C, %, D] [%, C, D]
[E, F, G] [E, F, G] [E, F, G]
[%, A, B] [%, A, B] [%, A, B]
[C, D, %] [C, %, D] [%, C, D]
[E, F, G] [E, F, G] [E, F, G]
I have tried a method of looking through each row and shifting the space left and right, then generating new grids off that and recursing. I keep all grids in a set and ensure I only produce positions which haven't already been examined to prevent infinite recursion.
However, my algorithm seems to be horrendously inefficient (~1s per permutation!!) and doesn't look very nice either. I was wondering if there was an eloquent way of doing this? In python in particular.
I have some vague ideas but I'm sure there is a way of doing this which is short and simple which I'm overlooking.
EDIT: 3x3 is just an example. Grid could be of any size and it's really the row combinations which matter. For example:
[A, %, C]
[D, E, %, G]
[H, I]
is also a valid grid.
EDIT 2: The letters must maintain their order. For example [A, %, B] != [B, %, A] and [B, A, %] isn't valid

First you have to get all desired permutations for each line. Then you calculate the cross product of all lines.
The permutations of a line can be simple calculated by having the letters [A,B,%] and varying the starting index:
import itertools
# Example: line = ['A','B','%']
def line_permutations(line):
if '%' not in line:
return [line]
line.remove('%') # use copy.copy if you don't want to modify your matrix here
return (line[:i] + ['%'] + line[i:] for i in range(len(line) + 1))
The cross product is easiest to achieve using itertools.product
matrix = [['A','B','%'], ['C', '%', 'D'], ['E', 'F', 'G']]
permutations = itertools.product(*[line_permutations(line) for line in matrix])
for p in permutations:
print(p)
This solution is optimal in memory and CPU requirements, because permutations are never recomputed.
Example output:
(['%', 'A', 'B'], ['%', 'C', 'D'], ['E', 'F', 'G'])
(['%', 'A', 'B'], ['C', '%', 'D'], ['E', 'F', 'G'])
(['%', 'A', 'B'], ['C', 'D', '%'], ['E', 'F', 'G'])
(['A', '%', 'B'], ['%', 'C', 'D'], ['E', 'F', 'G'])
(['A', '%', 'B'], ['C', '%', 'D'], ['E', 'F', 'G'])
(['A', '%', 'B'], ['C', 'D', '%'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['%', 'C', 'D'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['C', '%', 'D'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['C', 'D', '%'], ['E', 'F', 'G'])

Define a function called cycle
>>> def cycle(lst):
while True:
lst=lst[1:]+lst[0:1] if '%' in lst else lst
yield lst
Given an iterator, this will generate and return a cyclic left shift.
Now you have to pass each of the rows in the grid to the cycle
generator for the total iteration matching the length of the row
Now use itertools.product to find all combinations of the generated
row cyclic combinations.
In case there is no empty slot, no cycle permutation is generated
The final result is as follows
>>> for g in list(itertools.product(*[[x for (x,y) in zip(cycle(row),
range(0,len(row) if '%' in row else 1))] for row in grid])):
for r in g:
print r
print "="*10
For your Grid, this will generate
['B', '%', 'A']
['%', 'D', 'C']
['E', 'F', 'G']
===============
['B', '%', 'A']
['D', 'C', '%']
['E', 'F', 'G']
===============
['B', '%', 'A']
['C', '%', 'D']
['E', 'F', 'G']
===============
['%', 'A', 'B']
['%', 'D', 'C']
['E', 'F', 'G']
===============
['%', 'A', 'B']
['D', 'C', '%']
['E', 'F', 'G']
===============
['%', 'A', 'B']
['C', '%', 'D']
['E', 'F', 'G']
===============
['A', 'B', '%']
['%', 'D', 'C']
['E', 'F', 'G']
===============
['A', 'B', '%']
['D', 'C', '%']
['E', 'F', 'G']
===============
['A', 'B', '%']
['C', '%', 'D']
['E', 'F', 'G']
===============

A naive implementation:
g=[['A', 'B', '%'],
['C', '%', 'D'],
['E', 'F', 'G']]
from collections import deque
from itertools import product
def rotations(it):
d = deque(it,len(it))
for i in xrange(len(it)):
d.rotate(1)
yield list(d)
for i in product(*[rotations(x) if '%' in x else [x] for x in g]):
print i
gives:
(['%', 'A', 'B'], ['D', 'C', '%'], ['E', 'F', 'G'])
(['%', 'A', 'B'], ['%', 'D', 'C'], ['E', 'F', 'G'])
(['%', 'A', 'B'], ['C', '%', 'D'], ['E', 'F', 'G'])
(['B', '%', 'A'], ['D', 'C', '%'], ['E', 'F', 'G'])
(['B', '%', 'A'], ['%', 'D', 'C'], ['E', 'F', 'G'])
(['B', '%', 'A'], ['C', '%', 'D'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['D', 'C', '%'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['%', 'D', 'C'], ['E', 'F', 'G'])
(['A', 'B', '%'], ['C', '%', 'D'], ['E', 'F', 'G'])

Here it is. Note that on one side this approach is less clean, but it allows you to compute the permutations of # len(matrix[0])-1 only once and use them as templates for the output.
from itertools import permutations,product
def charPermutation(matrix):
permutation_list=list(permutations(["%%"]+["%s"]*(len(matrix[0])-1))) #Compute once, use infinitely
perms={i:[] for i in range(len(matrix))}
for it,line in enumerate(matrix):
chars=list(set(line)-set(["%"]))
if sorted(line)==sorted(chars):
perms[it]+=["".join([str(i) for i in line])]
else:
for p in permutation_list:
perms[it]+=["".join(["".join(p) % tuple(chars)])]
perms[it]=list(set(perms[it]))
return product(*[[list(k) for k in i] for i in perms.values()])
g=[
["A", "B", "%"],
["C", "%", "D"],
["E", "F", "G"]]
for x in charPermutation(g):
print [i for i in x]
[['A', '%', 'B'], ['C', 'D', '%'], ['E', 'F', 'G']]
[['A', '%', 'B'], ['%', 'C', 'D'], ['E', 'F', 'G']]
[['A', '%', 'B'], ['C', '%', 'D'], ['E', 'F', 'G']]
[['%', 'A', 'B'], ['C', 'D', '%'], ['E', 'F', 'G']]
[['%', 'A', 'B'], ['%', 'C', 'D'], ['E', 'F', 'G']]
[['%', 'A', 'B'], ['C', '%', 'D'], ['E', 'F', 'G']]
[['A', 'B', '%'], ['C', 'D', '%'], ['E', 'F', 'G']]
[['A', 'B', '%'], ['%', 'C', 'D'], ['E', 'F', 'G']]
[['A', 'B', '%'], ['C', '%', 'D'], ['E', 'F', 'G']]

Related

python join strings in list of lists

I have a list of lists of individual litters,
however I I would like a list of lists of a string.
What I have:
[
['a', 'b', 'c', 'd', 'e'],
['b', 'c', 'd', 'e', 'a'],
['c', 'd', 'e', 'a', 'b'],
['d', 'e', 'a', 'b', 'c'],
['e', 'a', 'b', 'c', 'd']
]
What I need:
[
['a b c d e'],
['b c d e a'],
['c d e a b'],
['d e a b c'],
['e a b c d']
]
I guess below will work as you wish.
list = [
['a', 'b', 'c', 'd', 'e'],
['b', 'c', 'd', 'e', 'a'],
['c', 'd', 'e', 'a', 'b'],
['d', 'e', 'a', 'b', 'c'],
['e', 'a', 'b', 'c', 'd']
]
newList = [[' '.join(elem)] for elem in list]
print(newList)
List comprehension:
result = [[' '.join(inner)] for inner in outer_list]
You can also do it with this
array = [['a', 'b', 'c', 'd', 'e'], ['f', 'g', 'h', 'i', 'j']]
string = [' '.join(i).split(',') for i in array]
print(string)
You can also do with map,
list(map(lambda x:[' '.join(x)], lst))

How to generalize this for loop for any lenght?

I want to generalize this in python for any "pos" length
for a in range(pos[0]):
for b in range(pos[1]):
for c in range(pos[2]):
for d in range(pos[3]):
for e in range(pos[4]):
for f in range(pos[5]):
neighbours.append([a, b, c, d, e, f])
I want to gather all the neighbours of my position in 6 dimensions. Neighbours are all combinations of x-1, x and x+1 for all coordinates. So I have to gather 3^dim -1 neighbours. pos is a {dim} length list with positions for all coordinatess. dx is discretization length. As you can see all loops are the same except for an increasing index in pos, so I want to generalize that, if possible.
for a in range(pos[0]- self.dx, pos[0]+2*self.dx, self.dx):
for b in range(pos[1]- self.dx, pos[1]+2*self.dx, self.dx):
for c in range(pos[2]- self.dx, pos[2]+2*self.dx, self.dx):
for d in range(pos[3]- self.dx, pos[3]+2*self.dx, self.dx):
for e in range(pos[4]- self.dx, pos[4]+2*self.dx, self.dx):
for f in range(pos[5]- self.dx, pos[5]+2*self.dx, self.dx):
neighbours.append([a, b, c, d, e, f])
You can solve it easily using recursion:
def combinations(pos, acc=[[]] * 3):
if len(pos) == 0:
return a Cloud
Amazon announced a $250 million venture fund to invest in Indian startups cc
else:
return combinations(pos[1:],
acc = \
[x + [y] for x in acc for y in pos[0]])
Test it by:
combinations([['a', 'b', 'c'], ['d', 'e'], ['f', 'g', 'h']])
Which gives:
[['a', 'd', 'f'],
['a', 'd', 'g'],
['a', 'd', 'h'],
['a', 'e', 'f'],
['a', 'e', 'g'],
['a', 'e', 'h'],
['b', 'd', 'f'],
['b', 'd', 'g'],
...
['a', 'd', 'f'],
['a', 'd', 'g'],
['a', 'd', 'h'],
['a', 'e', 'f'],
['a', 'e', 'g'],
['a', 'e', 'h'],
['b', 'd', 'f'],
['b', 'd', 'g'],
['b', 'd', 'h'],
['b', 'e', 'f'],
['b', 'e', 'g'],
['b', 'e', 'h'],
['c', 'd', 'f'],
['c', 'd', 'g'],
['c', 'd', 'h'],
['c', 'e', 'f'],
['c', 'e', 'g'],
['c', 'e', 'h']]
To remove duplicates, put a list(set()) around the result, or if you want to keep the order:
result_list_unique = []
for x in result_list:
if x not in result_list_unique:
result_list_unique.append(x)
and use result_list_unique

Identifying an assortment of lists whose elements make up the exact elements in a larger list

Python 3.
Preamble
So I have a list of elements, which may be ordered like this (or any other way):
List = [c, d, a, c, b]
Lets order it to make things easier:
List = [a, b, c, c, d]
So the list may have duplicates and has a length between 1 and 10.
The user will choose a range number, for example:
r = 3
The range number is part of a logic that produces the number of lists that contains all the possible combinations of 'List' subsequences for lengths 1 to r. Each combination may be permuted in any way. Considering 'List' and 'r' in this example the user would get the following selection of lists:
%Lists of length 1.
ListSelection1 = [[a], [b], [c], [c], [d]]
%Lists of length 2.
ListSelection2 = [[a, b], [a, c], [a, c], [a, d], [b, c], [b, c], [b, d], [c, c], [c, d], [c, d]]
%Lists of length 3.
ListSelection3 = [[a, b, c], [a, b, c], [a, b, d], [a, c, c], [a, c, d], [a, c, d], [b, c, c], [b, c, d], [b, c, d], [c, c, d]]
These lists will be arranged in another list, like this:
ListSelections = [ListSelection1, ListSelection2, ListSelection3]
The problem
How can I identify all possible combinations of (sub)lists in 'ListSelections' which together contains the same selection of elements as 'List'? Order of the elements does not matter. Regarding the example made above, accepted combinations of lists would be [b, c] and [a, c, d], or [b] + [c] + [d] + [a, c]. You get the point.
I need to identify all correct list-combinations and the positions of these lists in 'ListSelections'.
I think that what you want to find is the set of the partitions of a multiset. To do so you can use sympy as follows:
from sympy.utilities.iterables import multiset_partitions
res=[p for p in multiset_partitions(["a","b","c","c","d"])]
Output:
[[['a', 'b', 'c', 'c', 'd']],
[['a', 'b', 'c', 'c'], ['d']],
[['a', 'b', 'c', 'd'], ['c']],
[['a', 'b', 'c'], ['c', 'd']],
[['a', 'b', 'c'], ['c'], ['d']],
[['a', 'b', 'd'], ['c', 'c']],
[['a', 'b', 'd'], ['c'], ['c']],
[['a', 'b'], ['c', 'c', 'd']],
[['a', 'b'], ['c', 'c'], ['d']],
[['a', 'b'], ['c', 'd'], ['c']],
[['a', 'b'], ['c'], ['c'], ['d']],
[['a', 'c', 'c', 'd'], ['b']],
[['a', 'c', 'c'], ['b', 'd']],
[['a', 'c', 'c'], ['b'], ['d']],
[['a', 'c', 'd'], ['b', 'c']],
[['a', 'c', 'd'], ['b'], ['c']],
[['a', 'c'], ['b', 'c', 'd']],
[['a', 'c'], ['b', 'c'], ['d']],
[['a', 'c'], ['b', 'd'], ['c']],
[['a', 'c'], ['b'], ['c', 'd']],
[['a', 'c'], ['b'], ['c'], ['d']],
[['a', 'd'], ['b', 'c', 'c']],
[['a', 'd'], ['b', 'c'], ['c']],
[['a', 'd'], ['b'], ['c', 'c']],
[['a', 'd'], ['b'], ['c'], ['c']],
[['a'], ['b', 'c', 'c', 'd']],
[['a'], ['b', 'c', 'c'], ['d']],
[['a'], ['b', 'c', 'd'], ['c']],
[['a'], ['b', 'c'], ['c', 'd']],
[['a'], ['b', 'c'], ['c'], ['d']],
[['a'], ['b', 'd'], ['c', 'c']],
[['a'], ['b', 'd'], ['c'], ['c']],
[['a'], ['b'], ['c', 'c', 'd']],
[['a'], ['b'], ['c', 'c'], ['d']],
[['a'], ['b'], ['c', 'd'], ['c']],
[['a'], ['b'], ['c'], ['c'], ['d']]]
Your specification is a bit confused, but I suspect you either want 'permutations' or 'combinations':
https://docs.python.org/2/library/itertools.html
Python has a library that does this for you.
output = [itertools.permutations(input, r_) for r_ in range(r)]

remove list items from list of list in python

I have a list of characters:
Char_list = ['C', 'A', 'G']
and a list of lists:
List_List = [['A', 'C', 'T'], ['C', 'A', 'T', 'G'], ['A', 'C', 'G']]
I would like to remove each Char_list[i] from the list of corresponding index i in List_List.
Output must be as follows:
[['A','T'], ['C', 'T', 'G'], ['A', 'C']]
what I am trying is:
for i in range(len(Char_list)):
for j in range(len(List_List)):
if Char_list[i] in List_List[j]:
List_List[j].remove(Char_list[i])
print list_list
But from the above code each character is removed from all lists.
How can I remove Char_list[i] only from corresponding list in List_list?
Instead of using explicit indices, zip your two lists together, then apply a list comprehension to filter out the unwanted character for each position.
>>> char_list = ['C', 'A', 'G']
>>> list_list = [['A', 'C', 'T'], ['C','A', 'T', 'G'], ['A', 'C', 'G']]
>>> [[x for x in l if x != y] for l, y in zip(list_list, char_list)]
[['A', 'T'], ['C', 'T', 'G'], ['A', 'C']]
You may use enumerate with nested list comprehension expression as:
>>> char_list = ['C', 'A', 'G']
>>> nested_list = [['A', 'C', 'T'], ['C', 'A', 'T', 'G'], ['A', 'C', 'G']]
>>> [[j for j in i if j!=char_list[n]] for n, i in enumerate(nested_list)]
[['A', 'T'], ['C', 'T', 'G'], ['A', 'C']]
I also suggest you to take a look at PEP 8 - Naming Conventions. You should not be using capitalized first alphabet with the variable name.
Char_list = ['C', 'A', 'G']
List_List = [['A', 'C', 'T'], ['C', 'A', 'T', 'G'], ['A', 'C', 'G']]
for i in range(len(Char_list)):
List_List[i].remove(Char_list[i])
print(List_List)
OUTPUT
[['A', 'T'], ['C', 'T', 'G'], ['A', 'C']]
If the characters repeat in nested lists, Use this
Char_list = ['C', 'A', 'G']
List_List = [['A', 'C','C','C', 'T'], ['C', 'A', 'T', 'G'], ['A', 'C', 'G']]
for i in range(len(Char_list)):
for j in range(List_List[i].count(Char_list[i])):
List_List[i].remove(Char_list[i])
print(List_List)

Python 2d list sort by colum header

I have a 2d list:
['C', 'A', 'D', 'B'], #header row
['F', 'C', 'F', 'E'], #row 1
['F', 'E', 'F', 'F'], #row 2
['B', 'A', 'F', 'A'],
['A', 'F', 'C', 'E'],
['F', 'F', 'E', 'E'],
['C', 'E', 'F', 'C']
The first row in the list is the header row: C, A, D, B.
How can I change this so that the columns are in order so it will appear:
['A', 'B', 'C', 'D'], #header row
['C', 'E', 'F', 'F'], #row 1
['E', 'F', 'F', 'F'], #row 2
['A', 'A', 'B', 'F'],
['F', 'E', 'A', 'C'],
['F', 'E', 'F', 'E'],
['E', 'C', 'C', 'F']
I want the headers to be in order A,B,C,D but also move the columns underneath with the header
You can use sorted and zip, first create a list of your column with zip(*a) then sort it (based on first index) with sorted, and again convert to first state with zip and convert the indices to list with map :
>>> map(list,zip(*sorted(zip(*a))))
[['A', 'B', 'C', 'D'],
['C', 'E', 'F', 'F'],
['E', 'F', 'F', 'F'],
['A', 'A', 'B', 'F'],
['F', 'E', 'A', 'C'],
['F', 'E', 'F', 'E'],
['E', 'C', 'C', 'F']]
You could use numpy.
>>> import numpy as np
>>> data = np.array([['C', 'A', 'D', 'B'], #header row
... ['F', 'C', 'F', 'E'], #row 1
... ['F', 'E', 'F', 'F'], #row 2
... ['B', 'A', 'F', 'A'],
... ['A', 'F', 'C', 'E'],
... ['F', 'F', 'E', 'E'],
... ['C', 'E', 'F', 'C']])
>>> data[:,np.argsort(data[0])] # select sorted indices of first row as column indices.
array([['A', 'B', 'C', 'D'],
['C', 'E', 'F', 'F'],
['E', 'F', 'F', 'F'],
['A', 'A', 'B', 'F'],
['F', 'E', 'A', 'C'],
['F', 'E', 'F', 'E'],
['E', 'C', 'C', 'F']],
dtype='|S1')

Categories

Resources