Im having trouble trying to make a permutation code with recursion. This is suppose to return a list back to the use with all the posible position for each letter. so for t
I know this is a me too, but I think this one might be easier for some folks to understand....
Another for loop recursively permutes through all the other possibilities.
def permute(s):
out = []
if len(s) == 1:
out = [s]
else:
for i,let in enumerate(s):
for perm in permute(s[:i]+s[i+1:]):
out += [let+perm]
return out
This is the easiest solution I came up with.
def permutations(_string):
# stores all generated permutations
permutations = []
# this function will do recursion
def step(done, remain):
# done is the part we consider "permutated"
# remain is the set of characters we will use
# if there is nothing left we can appened generated string
if remain == '':
permutations.append(done)
else:
# we iterate over the remaining part and indexing each character
for i, char in enumerate(remain):
# we dont want to repeat occurance of any character so pick the remaining
# part minus the currect character we use in the loop
rest = remain[:i] + remain[i + 1:]
# use recursion, add the currect character to done part and mark rest as remaining
step(done + char, rest)
step("", _string)
return permutations
You can test it with:
@pytest.mark.parametrize('_string,perms', (
("a", ["a"]),
("ab", ["ab", "ba"]),
("abc", ["abc", "acb", "cba", "cab", "bac", "bca"]),
("cbd", ["cbd", "cdb", "bcd", "bdc", "dcb", "dbc"])
))
def test_string_permutations(_string, perms):
assert set(permutations(_string)) == set(perms)
These examples codes are really helpful but I found a test case failed when I was doing a code practice on CodeSignal. basically all the given approach here ignoring if there are any duplicates.
Input: s: "ABA"
Output: ["ABA", "AAB", "BAA", "BAA", "AAB", "ABA"]
Expected Output: ["AAB", "ABA", "BAA"]
So, if you see, it has following duplicates in the output:
["BAA", "AAB", "ABA"]
I modified this by bit here
def stringPermutations(s):
news = s
if len(news) == 1:
return [news]
res = []
for permutation in stringPermutations(news[1:]):
for i in range(len(news)):
res.append(permutation[:i] + news[0:1] + permutation[i:])
# To Remove Duplicates From a Python List: list(dict.fromkeys(res))
# To Sort List : sorted()
return sorted(list(dict.fromkeys(res)))
def main():
arr = 'ABA'
print(stringPermutations(arr))
if __name__ == '__main__':
main()
But this answer is not appropriate as per time complexity. Time complexity with this approach is: o(n^2)
I think the below approach is quite reasonable.
def stringPermutations(string, prefix, permutation_list):
#Edge case check
if len(string) == 0:
permutation_list.append(prefix)
else:
for i in range(len(string)):
rem = string[0:i] + string[i + 1:]
stringPermutations(rem, prefix + string[i], permutation_list)
return sorted(list(dict.fromkeys(permutation_list)))
def main():
permutation_list = []
print(stringPermutations('aba','', permutation_list))
if __name__ == '__main__':
main()