How to find position of letters in array of strings - python

I have a problem where I need to find where letters are in a matrix of strings. The input is: maze1=['*****','* * *','* G**','*D***','* ***']
The expected output is a tuple of the letters coordinates. For this example, the expected output is [(2,2),(3,1)]
Here is my code so far I run into a problem when checking if the element is a letter:
treasure=[]
for i in range(len(maze)):
for j in range(len(maze)):
if maze[i][j].lower().isAlpha():
treasure[i] = maze[i][j]
print(treasure)

In [2]: maze1=['*****','* * *','* G**','*D***','* ***']
In [3]: [(i,j) for i,s in enumerate(maze1) for j,char in enumerate(s) if char.isalpha()]
Out[3]: [(2, 2), (3, 1)]

Using regex
import re
result=[]
maze1 =['*****','* * *','* G**','*D***','* ***']
for counter, value in enumerate(maze1):
m=re.search('([a-zA-Z]+)',value)
if m :
result.append((counter, m.start()))
Output
[(2, 2), (3, 1)]

Assuming your maze has 5 columns:
[(p//5,p%5) for p,l in enumerate("".join(maze1)) if l.isalpha()]
returns:
[(2, 2), (3, 1)]

Related

Given a List get all the combinations of tuples without duplicated results

I have a list=[1,2,3,4]
And I only want to receive tuple results for like all the positions in a matrix, so it would be
(1,1),(1,2),(1,3),(1,4),(2,1),(2,2),(2,3),(2,4),(3,1),(3,2),(3,3),(3,4),(4,1),(4,2),(4,3),(4,4)
I've seen several codes that return all the combinations but i don't know how to restrict it only to the tuples or how to add the (1,1),(2,2),(3,3),(4,4)
Thank you in advance.
You just need a double loop. A generator makes it easy to use
lst = [1,2,3,4]
def matrix(lst):
for i in range(len(lst)):
for j in range(len(lst)):
yield lst[i], lst[j]
output = [t for t in matrix(lst)]
print(output)
Output:
[(1, 1), (1, 2), (1, 3), (1, 4), (2, 1), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 1), (4, 2), (4, 3), (4, 4)]
If you just want to do this for making pairs of all symbols in the list
tuple_pairs = [(r,c) for r in lst for c in lst]
If you have instead some maximum row/colum numbers max_row and max_col you could avoid making the lst=[1,2,3,4] and instead;
tuple_pairs = [(r,c) for r in range(1,max_row+1) for c in range(1,max_col+1)]
But that's assuming that the lst's goal was to be = range(1, some_num).
Use itertools.product to get all possible combinations of an iterable object. product is roughly equivalent to nested for-loops with depth specified by the keyword parameter repeat. It returns an iterator.
from itertools import product
lst = [1, 2, 3, 4]
combos = product(lst, repeat=2)
combos = list(combos) # cast to list
print(*combos, sep=' ')
Diagonal terms can be found in a single loop (without any extra imports)
repeat = 2
diagonal = [(i,)*repeat for i in lst]
print(*diagonal sep=' ')
You can do that using list comprehension.
lst=[1,2,3,4]
out=[(i,i) for i in lst]
print(out)
Output:
[(1, 1), (2, 2), (3, 3), (4, 4)]

Generating 2D grid indices using list comprehension

I would like to store the row and column indices of a 3 x 3 list in list. It should look like the following:
rc = [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2,1),(2,2)]
How can I get this list using a list comprehension in Python?
Some consider multiple for loops inside a list comprehension to be poor style. Use itertools.product() instead:
from itertools import product
list(product(range(3), repeat=2))
This outputs:
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
How about:
[(x, y) for x in range(3) for y in range(3)]
If I understand correctly, and the input is A, the B can be output as follows:
A = [[1,2,3],[4,5,6],[7,8,9]]
B =[(A[i], A[j]) for i in range(3) for j in range(3)]

all possible permutations for a string

Having a string='january' ,
how can I generate following cases:
case1(Replacing 1 character) => taking j and replace it with all ASCII letters(a-z). then do the same with: a , n , u , a , r , y.
Basically we would have
(Aanuary , Banuary ,..... ,Zanuary )+ (jAnuary , jBanuary .....jZanuary) + ....+(januarA , januarB , ....., januarZ)
I have done this part using following code, However, I have no idea how to do it for more than one letter since there are lots of permutations.
monthName= 'january'
asci_letters = ['a' , 'b' , .... , 'z']
lst = list(monthName)
indxs = [i for i , _ in enumerate(monthName)]
oneLetter=[]
for i in indxs:
word = monthName
pos = list(word)
for j in asci_letters:
pos[i] = j
changed = ("".join(pos))
oneLetter.append(changed)
Case2: Taking 2 characters and replacing them:
(AAnuary , ABnuary ,.....,AZanuary) + (BAnuary , BBanuary, .... , BZanuary) + (AaAuary , AaBuary,.....,AaZuary) + ...... + (januaAB , .... , januaAZ)
Case3 : doing the same for 3 characters
Case7: doing the same for 7 characters(length of string)
To summarize, I want to create all possible cases of replacing, 1 letter, 2 letters,3 letters, up to all letters of a string.
It's very likely that you can't hold all these permutations in memory because it will quickly become very crowded.
But to get all indices for the cases you can use itertools.combinations. For 1 it will give the single indices:
from itertools import combinations
string_ = 'january'
length = len(string_)
print(list(combinations(range(length), 1)))
# [(0,), (1,), (2,), (3,), (4,), (5,), (6,)]
Likewise you can get the indices for case 2-7:
print(list(combinations(range(length), 2)))
# [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (1, 2), (1, 3), (1, 4),
# (1, 5), (1, 6), (2, 3), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6),
# (4, 5), (4, 6), (5, 6)]
Then it's just a matter of inserting the itertools.product of string.ascii_uppercase at the given indices:
from itertools import product
import string
print(list(product(string.ascii_uppercase, repeat=1)))
# [('A',), ('B',), ('C',), ('D',), ('E',), ('F',), ('G',), ('H',), ('I',),
# ('J',), ('K',), ('L',), ('M',), ('N',), ('O',), ('P',), ('Q',), ('R',),
# ('S',), ('T',), ('U',), ('V',), ('W',), ('X',), ('Y',), ('Z',)]
Likewise for different repeats given the "case".
Putting this all together:
def all_combinations(a_string, case):
lst = list(a_string)
length = len(lst)
for combination in combinations(range(length), case):
for inserter in product(string.ascii_uppercase, repeat=case):
return_string = lst.copy()
for idx, newchar in zip(combination, inserter):
return_string[idx] = newchar
yield ''.join(return_string)
Then you can get all desired permutations for each case by:
list(all_combinations('january', 2)) # case2
list(all_combinations('january', 4)) # case4
list(all_combinations('january', 7)) # case7
Or if you need all of them:
res = []
for case in [1, 2, 3, 4, 5, 6, 7]:
res.extend(all_combinations('january', case))
But that will require a lot of memory.
You can use itertools.combinations_with_replacement for this, which gives you an iterator with all permutations:
from itertools import combinations_with_replacement
# First Param is an iterable of possible values, second the length of the
# resulting permutations
combinations = combinations_with_replacement('ABCDEFGHIJKLMNOPQRSTUVWXYZ',7)
# Then you can iterate like this:
for combination in combinations:
#Do Stuff here
Don't try to convert this iterator to a list of all values, because you probably gonna get a MemoryException.
For your distance you might want to use python distance package. (You need to install it via pip first).
For your case, that you want to get all combinations for Characters a-z with length = 7 (because of January):
import distance
from itertools import combinations_with_replacement
str_to_compary_with = "JANUARY"
for i in range(len(str_to_compare_with):
combinations = combinations_with_replacement('ABCDEFGHIJKLMNOPQRSTUVWXYZ', i+1)
# Then you can iterate like this:
for combination in combinations:
# This is calculating the hamming distance for the combination with the string you want to compare to
# Here you have to figure out yourself if you want to save that output to a file or whatever you wanna do with the distance
hamming_dist = distance.hamming(''.join(combination), str_to_compare_with)
This should do everything that you wanted with help of product and permutations:
from itertools import product, permutations
monthName= 'january'
letters = list('abcdefghijklmnopqrstuvwxyz')
n = len(monthName)
indxs = range(n)
mn = list(monthName)
cases = {k: [] for k in range(2, n+1)}
for num in range(2, n+1):
letter_combos = list(product(*[letters for _ in range(num)]))
positions = permutations(indxs, num)
for p in positions:
for l in letter_combos:
l = iter(l)
for i in p:
mn[i] = next(l)
mn = ''.join(mn)
cases[num].append(mn)
mn = list(monthName)
If you want to know how it is working, you can test this with a subset of letters, say from A-F:
x = []
for i in range(65,70): #subset of letters
x.append(chr(i))
def recurse(string,index,arr):
if(index>len(string)-1):
return
for i in range(index,len(string)):
for item in x:
temp = string[:i]+item+string[i+1:]
arr.append(temp)
recurse(temp,i+1,arr)
arr = []
recurse('abc',0,arr)
print arr

For loop to compare one element with all the remaining elements of an array

I have an array in Python [0,1,2,3,4] with 5 elements. I want to compare elements in following fashion.
(0,1),(0,2),(0,3),(0,4),(1,2),(1,3),(1,4),(2,3),(2,4),(3,4),(4,4)
What I am doing is as follows.
for i in range(len(array)):
for j in range(i+1,len(array)):
But this is comparing in following fashion.
(0,1),(1,2),(2,3),(3,4)...
Where I am doing it wrong?
This code produces the desired result:
array = [0,1,2,3,4]
for i in range(len(array)):
for j in range(i+1,len(array)):
print(array[i], array[j])
print(array[-1], array[-1])
This code is one way that you may have gotten the erroneous result:
for i in range(len(array)):
for j in range(i+1,len(array)):
print(array[i], array[j])
break
Using itertools is another option:
>>> [x for x in itertools.combinations(xrange(5), 2)]
[(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]

generating all permutations of 2 ones and 3 zeroes with itertools

probably basic, but couldn't find it in any other question.
I tried:
print ["".join(seq) for seq in itertools.permutations("00011")]
but got lots of duplications, seems like itertools doesn't understand all zeroes and all ones are the same...
what am I missing?
EDIT:
oops. Thanks to Gareth I've found out this question is a dup of: permutations with unique values.
Not closing it as I think my phrasing of the question is clearer.
list(itertools.combinations(range(5), 2))
returns a list of 10 positions where the two ones can be within the five-digits (others are zero):
[(0, 1),
(0, 2),
(0, 3),
(0, 4),
(1, 2),
(1, 3),
(1, 4),
(2, 3),
(2, 4),
(3, 4)]
For your case with 2 ones and 13 zeros, use this:
list(itertools.combinations(range(5), 2))
which returns a list of 105 positions. And it is much faster than your original solution.
Now the function:
def combiner(zeros=3, ones=2):
for indices in itertools.combinations(range(zeros+ones), ones):
item = ['0'] * (zeros+ones)
for index in indices:
item[index] = '1'
yield ''.join(item)
print list(combiner(3, 2))
['11000',
'01100',
'01010',
'01001',
'00101',
'00110',
'10001',
'10010',
'00011',
'10100']
and this needs 14.4µs.
list(combiner(13, 2))
returning 105 elements needs 134µs.
set("".join(seq) for seq in itertools.permutations("00011"))

Categories

Resources