Generate permutations of string-code error - python

This is the code that i have a problem with.
def permute(word):
letters = list(word)
print(type(letters))
for letter in letters:
letter_copy = letters.remove(letter)
rtrn_list = letter + permute(letter_copy)
return rtrn_list
w = 'ABC'
print(permute(w))
i am new to programming. someone please say where the problem is. Thanks in advance

Find your problem my comparing to this implementation.
def permute(string):
'''
Recursively finds all possible combinations of the
elements -- or permuations -- of an input string and
returns them as a list.
>>>permute('abc')
['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
'''
output = []
if len(string) == 1:
output = [string]
else:
for i, let in enumerate(string):
for perm in permute(string[:i] + string[i + 1:]):
#print('Let is', let)
#print('Perm is', perm)
output += [let + perm]
return output
permute('abc')
Out[ ]:
['abc', 'acb', 'bac', 'bca', 'cab', 'cba']

For permutations you can use python builtin from itertools:
from itertools import permutations
p = []
for t in permutations('abc'):
p.append(''.join(t))
print(p)
Output is:
['abc', 'acb', 'bac', 'bca', 'cab', 'cba']

Related

Python: The resulting array of type string does not match

I want to make a program to group words consisting of the same characters in an array, but the results don't match when using the Python programming language
Example problem: Suppose I have 3 arrays of type string as follows:
oe1 = ["abc", "def"];
oe2 = ["asd", "cab", "fed", "eqw"];
oe3 = ["qwe", "efd", "bca"];
Note: The order of the array or the elements doesn't matter, the important thing is that they are grouped.
Output example:
[abc, cab, bca]
[asd]
[def, fed, efd]
[eqw, qwe]
But I try to use coding like this the results are not appropriate:
oe1 = ["abc", "def"];
oe2 = ["asd", "cab", "fed", "eqw"];
oe3 = ["qwe", "efd", "bca"];
anagram_list = []
for word_1 in oe1:
for word_2 in oe2:
for word_3 in oe3:
if word_1 != word_2 != word_3 and (sorted(word_1)==sorted(word_2)==sorted(word_3)):
anagram_list.append(word_1 + word_2 + word_3)
print(anagram_list)
my output is like this:
['abccabbca', 'deffedefd']
How do I make it match the example output above?
First off, let's combine those lists and sort them using a lambda that converts each string to a list of characters, then sorts that.
>>> sorted(oe1 + oe2 + oe3, key=lambda s: sorted(list(s)))
['abc', 'cab', 'bca', 'asd', 'def', 'fed', 'efd', 'eqw', 'qwe']
Then using itertools.groupby to group them based on the same lambda.
>>> k = lambda s: sorted(list(s))
>>> [list(v) for _, v in groupby(sorted(oe1 + oe2 + oe3, key=k), key=k)]
[['abc', 'cab', 'bca'], ['asd'], ['def', 'fed', 'efd'], ['eqw', 'qwe']]
This can be simplified a bit further by not first converting to a list and just sorting each string.
>>> sorted(oe1 + oe2 + oe3, key=sorted)
['abc', 'cab', 'bca', 'asd', 'def', 'fed', 'efd', 'eqw', 'qwe']
>>> [list(v) for _, v in groupby(sorted(oe1 + oe2 + oe3, key=sorted), key=sorted)]
[['abc', 'cab', 'bca'], ['asd'], ['def', 'fed', 'efd'], ['eqw', 'qwe']]
To be easier, let merge them all together. Also, use condition with set() to check whether 2 text are using the same set of characters.
However, my solution doesn't require any sort(). But I added it because I want the output to be the same as your desired output.
oe = oe1 + oe2 + oe3
oe.sort() # optional, no need for sorting
oe_group = []
for i in range(len(oe)):
if i == 0:
oe_group.append([oe[i]])
else:
for j in range(len(oe_group)):
if set(oe[i]) == set(oe_group[j][0]):
oe_group[j].append(oe[i])
break
if j == len(oe_group) - 1:
oe_group.append([oe[i]])
output
[['abc', 'bca', 'cab'], ['asd'], ['def', 'efd', 'fed'], ['eqw', 'qwe']]

Looping with regex (Python) appending after match to a list

So I'am trying to append every match of a string into a list with regex.
So here is my code. It only doesn't work (properly) unfortunatly.
seq = 'ABABABBBASHDBDHBEHDBEDH'
Empty_list = []
regex_ex = re.finditer(r'.{3}', seq)
for x in regex_ex:
Empty_list.append(x)
to access the value of your match you should use re.Match.group method:
for x in regex_ex:
Empty_list.append(x.group())
you could replace your for loop code with a list comprehension:
Empty_list = [x.group() for x in re.finditer(r'.{3}', seq)]
print(Empty_list)
output:
['ABA', 'BAB', 'BBA', 'SHD', 'BDH', 'BEH', 'DBE']
if you want a more compact code:
list(map(re.Match.group, re.finditer(r'.{3}', seq)))
output:
['ABA', 'BAB', 'BBA', 'SHD', 'BDH', 'BEH', 'DBE']
You're saving match object instead of matched string:
seq = 'ABABABBBASHDBDHBEHDBEDH'
Empty_list = []
regex_ex = re.finditer(r'.{3}', seq)
for x in regex_ex:
Empty_list.append(x.group(0)) # saves matched string
print(Empty_list)
Output:
['ABA', 'BAB', 'BBA', 'SHD', 'BDH', 'BEH', 'DBE']

Is it proper to use nested loops a lot in python?

I have a project and I am trying to do a complex cryptographic method. Is it normal to use nested loops a lot? Or did I miss something?
I intend to create a method which tries all strings to find password. For example, when I input ['A','B'] it should create each of these one by one:
['A', 'B', 'AA', 'AB', 'BA', 'BB', 'AAA', 'AAB', 'ABA', 'ABB', 'BAA', 'BAB', 'BBA', 'BBB', (triple permutations), (quadruple permutations), and it goes on ...]
My code:
def rulefinder():
global externalrul1
global externalrul2
rul2 = uniquestring1[0]
rul1 = uniquestring1[0]
for n in range (0,3):
for m in range (0, len(uniquestring1)):
for z in range(0, n+1):
for k in range (0,3):
for i in range(0, len(uniquestring1)):
for o in range(0, k+1):
for y in range (0, len(uniquestring1)):
rul2 = rul2[:-1] + uniquestring1[y]
for x in range (0, len(uniquestring1)):
rul1= rul1[:-1] + uniquestring1[x]
code=""
for cha in Genx1:
if cha==uniquestring1[0]:
code +=codereplacer(rul1)
elif cha==uniquestring1[1]:
code +=codereplacer(rul2)
print(code)
print(uniquestring1[0],rul1)
print(uniquestring1[1],rul2)
print(LastString)
if code == LastString:
axiom1=uniquestring1[0]
axiom2=uniquestring1[1]
externalrul1=rul1
externalrul2=rul2
print('rules are found')
print("First RULE:", uniquestring1[0], rul1)
print("Second RULE:", uniquestring1[1], rul2)
findsubgeneration(code, axiom1, rul1, axiom2, rul2)
return
rul1 = rul1[:o] + uniquestring1[i] + rul1[(o + 1):]
rul1 += codereplacer(uniquestring1[i])
rul2 = rul2[:z] + uniquestring1[m] + rul2[(z + 1):]
rul1 =""
rul2 += codereplacer(uniquestring1[m])
You are doing things in a very MATLAB-ic way (lots of loops, and iterating only on the index, instead of elements of iterables). Pythonic way is much more efficient (uses generators under the hood), and is much cleaner:
import itertools
l = ['A','B']
n = 5 # The size of your "expanding permutations"
res = []
for i in range(1,n):
res.extend(map(''.join, list(itertools.product(l, repeat=i))))
print res
Result:
['A', 'B', 'AA', 'AB', 'BA', 'BB', 'AAA', 'AAB', 'ABA', 'ABB', 'BAA', 'BAB', 'BBA', 'BBB',
'AAAA', 'AAAB', 'AABA', 'AABB', 'ABAA', 'ABAB', 'ABBA', 'ABBB', 'BAAA', 'BAAB', 'BABA', 'BABB', 'BBAA', 'BBAB', 'BBBA', 'BBBB']
Caution: As long as you are working with a small list, you should be fine but as l grows, the result is going to grow exponentially, and may eat out your memory. Hence, instead of doing an extend to the res list, you can write the results inside the loop into disk, on the fly.

String generation based on the other string in Python

I want to create a simple string generator and here is how it will work
I declare a pattern_string = "abcdefghijklmnopqrstuvwxyz"
My starting string lets say starting_string = "qywtx"
Now I want to generate strings as follows:
Check the last character in my starting_stringagainst the pattern string.
Last character is x. We find this character in the find it in the pattern_string:
abcdefghijklmnopqrstuvw x yz
and see that next character is y so I want output qywty.
...
However, when I reach the z, I want my string to increment second last character and set the last character to the first character of the starting_pattern so it will be qywra and so on...
Now questions:
Can I use REGEX to achieve that?
Are there any libraries out there that already handle such generation?
The following will generate the next string according to your description.
def next(s, pat):
l = len(s)
for i in range(len(s) - 1, -1, -1): # find the first non-'z' from the back
if s[i] != pat[-1]: # if you find it
# leave everything before i as is, increment at i, reset rest to all 'a's
return s[:i] + pat[pat.index(s[i]) + 1] + (l - i - 1) * pat[0]
else: # this is only reached for s == 'zzzzz'
return (l + 1) * pat[0] # and generates 'aaaaaa' (just my assumption)
>>> import string
>>> pattern = string.ascii_lowercase # 'abcde...xyz'
>>> s = 'qywtx'
>>> s = next(s, pattern) # 'qywty'
>>> s = next(s, pattern) # 'qywtz'
>>> s = next(s, pattern) # 'qywua'
>>> s = next(s, pattern) # 'qywub'
For multiple 'z' in the end:
>>> s = 'foozz'
>>> s = next(s, lower) # 'fopaa'
For all 'z', start over with 'a' of incremented length:
>>> s = 'zzz'
>>> s = next(s, lower) # 'aaaa'
To my knowledge there is no library function to do that. One that comes close is itertools.product:
>>> from itertools import product
>>> list(map(''.join, product('abc', repeat=3)))
['aaa', 'aab', 'aac', 'aba', 'abb', 'abc', 'aca', 'acb', 'acc', 'baa',
'bab', 'bac', 'bba', 'bbb', 'bbc', 'bca', 'bcb', 'bcc', 'caa', 'cab',
'cac', 'cba', 'cbb', 'cbc', 'cca', 'ccb', 'ccc']
But that doesn't not work with an arbitrary start string. This behaviour could be mimicked by combining it with itertools.dropwhile but that has the serious overhead of skipping all the combinations before the start string (which in the case of an alphabet of 26 and a start string towards the end pretty much renders that approach useless):
>>> list(dropwhile(lambda s: s != 'bba', map(''.join, product('abc', repeat=3))))
['bba', 'bbb', 'bbc', 'bca', 'bcb', 'bcc', 'caa', 'cab', 'cac', 'cba', 'cbb', 'cbc', 'cca', 'ccb', 'ccc']

Ranking permutations recursively in python

How can I format this function so that it works recursively? I want to go multiple levels deeper if possible, not just until 5.
permutations is a list with different permutations, and those individual permutation can also have permutations, etc. I want to rank them based on some calculations I do in get_permutations and return the new order of permutations. A good way to look at it is probably a large list of lists of lists of lists of lists. First I want to change the order of the first level, than one step deeper etc. But eventually I return the string based on those permutations and not the permutation itself (if that matters), with res1...res5 being the strings. I'm not smart enough to get it to work recursively, even though I know it should be possible...Any ideas?
permutations, res1 = get_permutations(str, 1)
for p2 in permutations:
permutations_2, res2 = get_permutations(p2,2)
for p3 in permutations_2:
permutations_3, res3 = get_permutations(p3,3)
for p4 in permutations_3:
permutations_4, res4 = get_permutations(p4, 4)
for p5 in permutations_4:
permutations_5, res5 = get_permutations(p5,5)
res4 += res5
res3 += res4
res2 += res3
res1 += res2
return res1
EDIT: this returns a single (best) permutation. That is what the result is for. So not a list of possible permutations, as mentioned in the answers. E.g. if we have a lists of lists of lists, if first sorts the list based on all subinformation, then sorts the multiple lists of lists based on the previous sorts and all subinformation and then sorts the lists of lists of lists based on the previous 2 sorts.
A recursive generator function that yields permutations in the expected order with regard to the original string:
def get_permutations(a):
if len(a) <= 1:
yield a
else:
for i in xrange(len(a)):
for p in get_permutations(a[:i]+a[i+1:]):
yield ''.join([a[i]])+p
>>> a = '123'
>>> list(get_permutations(a))
['123', '132', '213', '231', '312', '321']
The recursive principle here:
Base case: strings of lengthes (0, 1) have only one permutation: themselves.
Recursion: for each letter in the string, remove it and prepend it to each permutation of the string's remainder.
An example below, This method works by nesting for loops in a recursive manner repeat-times. We then accumulate the result of the sub-solutions, appending to a result list:
result = []
def permutations(alphabet, repeat, total = ''):
if repeat >= 1:
for i in alphabet:
# Add the subsolutions.
permutations(alphabet, repeat - 1, total + i)
else:
result.append(total)
return result
Sample Outputs:
permutations('ab', 3) ->
$ ['aaa', 'aab', 'aba', 'abb', 'baa', 'bab', 'bba', 'bbb']
permutations('ab', 3) ->
$ ['aaa', 'aab', 'aac', 'aba', 'abb', 'abc', 'aca', 'acb', 'acc', 'baa',
'bab', 'bac', 'bba', 'bbb', 'bbc', 'bca', 'bcb', 'bcc', 'caa', 'cab',
'cac', 'cba', 'cbb', 'cbc', 'cca', 'ccb', 'ccc']
permutations('ab', 1) ->
$ ['a', 'b']
Source: a previous answer of mine.

Categories