all permutations of string without using itertools - python-3.x

All possible strings of any length that can be formed from a given string
Input:
abc
Output:
a b c abc ab ac bc bac bca
cb ca ba cab cba acb
I have tried using this but it's limited to string abc, I want to generalize it like if input 'abcd' i will provide me output for the same.
def perm_main(elems):
perm=[]
for c in elems:
perm.append(c)
for i in range(len(elems)):
for j in range(len(elems)):
if perm[i]!= elems[j]:
perm.append(perm[i]+elems[j])
level=[elems[0]]
for i in range(1,len(elems)):
nList=[]
for item in level:
#print(item)
nList.append(item+elems[i])
#print(nList)
for j in range(len(item)):
#print(j)
nList.append(item[0:j]+ elems[i] + item[j:])
#print(nList)
level=nList
perm = perm + nList
return perm

You may not need itertools, but you have the solution in the documentation, where itertools.permutations is said to be roughly equivalent to:
def permutations(iterable, r=None):
# permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
# permutations(range(3)) --> 012 021 102 120 201 210
pool = tuple(iterable)
n = len(pool)
r = n if r is None else r
if r > n:
return
indices = list(range(n))
cycles = list(range(n, n-r, -1))
yield tuple(pool[i] for i in indices[:r])
while n:
for i in reversed(range(r)):
cycles[i] -= 1
if cycles[i] == 0:
indices[i:] = indices[i+1:] + indices[i:i+1]
cycles[i] = n - i
else:
j = cycles[i]
indices[i], indices[-j] = indices[-j], indices[i]
yield tuple(pool[i] for i in indices[:r])
break
else:
return
Or using product:
def permutations(iterable, r=None):
pool = tuple(iterable)
n = len(pool)
r = n if r is None else r
for indices in product(range(n), repeat=r):
if len(set(indices)) == r:
yield tuple(pool[i] for i in indices)
They are both generators so you will need to call list(permutations(x)) to retrieve an actual list or substitute the yields for l.append(v) where l is a list defined to accumulate results and v is the yielded value.
For all the possible sizes ones, iterate over them:
from itertools import chain
check_string = "abcd"
all = list(chain.from_iterable(permutations(check_string , r=x)) for x in range(len(check_string )))

Partial recursive solution. You just need to make it work for different lengths:
def permute(pre, str):
n = len(str)
if n == 0:
print(pre)
else:
for i in range(0,n):
permute(pre + str[i], str[0:i] + str[i+1:n])
You can call it using permute('', 'abcd'), or have another method to simplify things
def permute(str):
permute('', str)
Answer borrowed from here.
In general, you will have better luck translating code from C/Cpp/Java solutions to Python because they generally implement things from scratch and do things without much need of libraries.
UPDATE
Full solution:
def all_permutations(given_string):
for i in range(len(given_string)):
permute('', given_string, i+1)
def permute(prefix, given_string, max_len):
if len(given_string) <= 0 or len(prefix) >= max_len:
print(prefix)
else:
for i in range(len(given_string)):
permute(prefix + given_string[i], given_string[:i] + given_string[i+1:], max_len)
>>> all_permutations('abc')
a
b
c
ab
ac
ba
bc
ca
cb
abc
acb
bac
bca
cab
cba

Related

Max Points on a Line with python 3

algorithm question:
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
Example 1:
Input: [[1,1],[2,2],[3,3]]
Output: 3
Explanation:
^
|
| o
| o
| o
+------------->
0 1 2 3 4
Example 2:
Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Output: 4
the working python 3 code is below:
wondering
snippet 1 d[slope] = d.get(slope, 1) + 1 is working
but why this snippet 2 is not working correctly for example 2 even though snippet 1 and 2 are the same
if slope in d:
d[slope] += 1
else:
d[slope] = 1
def gcd(self, a, b):
if b == 0:
return a
return self.gcd(b, a%b)
def get_slope(self, p1, p2):
dx = p1[0] - p2[0]
dy = p1[1] - p2[1]
c = self.gcd(dx, dy)
dx /= c
dy /= c
return str(dy) + "/" + str(dx)
def is_same_points(self, p1:List[int], p2:List[int]):
return p1[0] == p2[0] and p1[1] == p2[1]
def maxPoints(self, points: List[List[int]]) -> int:
if not points:
return 0
n = len(points)
count = 1
for i in range(0, n):
d = {}
duped = 0
localmax = 1
p1 = points[i]
for j in range(i+1, n):
p2 = points[j]
if self.is_same_points(p1, p2):
duped += 1
else:
slope = self.get_slope(p1, p2)
# 1) not work: output is 3 in example 2
# if slope in d:
# d[slope] += 1
# else:
# d[slope] = 1
# 2) works: correct output 4 for example 2
d[slope] = d.get(slope, 1) + 1
localmax = max(localmax, d[slope]);
count = max(count, localmax + duped)
return count
Interesting problem and nice solution.
The reason why the commented out code doesn't work is because of that:
else:
d[slope] = 1 ## correct would be d[slope] = 2
Every 2 points are on the same line, you are counting only one point for the first two p1 p2, thus you get one less in the final answer.

Code fails on Test case. (InterQuartile Range)

This is a challenge from 10 Day statistics on Hackerrank.(https://www.hackerrank.com/challenges/s10-interquartile-range/problem?h_r=next-challenge&h_v=zen)
Task :
Task
The interquartile range of an array is the difference between its first (Q1) and third (Q3) quartiles (i.e., Q3 - Q1).
Given an array,X, of n integers and an array, F, representing the respective frequencies of X's elements, construct a data set, S, where each xi occurs at frequency fi. Then calculate and print S's interquartile range, rounded to a scale of 1 decimal place (i.e., 12.3 format).
Following is my code.
n = int(input())
x = list(map(int, input().split()))
f = list(map(int, input().split()))
s = []
for i in range(len(x)):
j = f[i]
for k in range(j):
s.append(x[i])
n = len(s)
s.sort()
if n%2 == 0:
Q21 = s[n//2]
Q22 = s[n//2 - 1]
Q2 = (Q21 + Q22) / 2
else:
Q2 = s[n//2]
LH = s[:n//2]
if n%2==0:
UH = s[n//2:]
else:
UH = s[n//2+1:]
Q1_len = len(LH)
Q3_len = len(UH)
if Q1_len%2 == 0:
Q11 = LH[Q1_len//2]
Q12 = LH[Q1_len//2 - 1]
Q1 = (Q11 + Q12) / 2
else:
Q1 = LH[Q1_len//2]
if Q3_len%2 == 0:
Q31 = UH[Q3_len//2]
Q32 = UH[Q3_len//2 - 1]
Q3 = (Q31 + Q32) / 2
else:
Q3 = UH[Q3_len//2]
print(round(Q3 - Q1,1))
# print(int(Q2))
# print(int(Q3))
Here is the test case: with std input.
5
10 40 30 50 20
1 2 3 4 5
Expected output:
30.0
My code output:
30.0 # I get this output on my code editor but not on Hackerrank
Can someone help me on this where I am wrong ?
I get the output what is expected but it shows as failed.
print(float(Q3 - Q1))
Basically is the answer.

Directed Graph: How to find the longest path of Node A to N Considering the ff code:

I have considered using DFS for tracking the vertex for each edges present to find the longest path but the problem is it gives only the L input to it and the edge corresponding to it. I want to find the longest path traversed by these vertices as a alphabetically nondecreasing string and if the string playes indefenitely it outputs infinite. Here is my initial working code:
from collections import defaultdict
def DFS(G,v,seen=None, path=None):
if seen is None: seen = []
if path is None: path = [v]
seen.append(v)
paths =[]
for i in G[v]:
if i not in seen:
i_path = path + [i]
paths.append(tuple(i_path))
paths.extend(DFS(G, i, seen[:], i_path))
return paths
t = int(input())
i,j = 1,0
graph = defaultdict(list)
while i < t:
n, a = [int(i) for i in input().split()]
while j < a:
n1,n2,l = input().split()
graph[l].append(n1)
graph[l].append(n2)
j+= 1
print(graph)
print(DFS(graph, 'A'))
i+=1
i want to know where i did wrong or maybe i missed something essential since the given output for the sample input is:
INPUT:
1 // test case
5 7 // n, a
2 3 B
3 1 E
1 2 A
1 2 R
2 4 D
3 5 E
4 3 D
Expected : ADDER
ACTUAL: D, D

How do I calculate a factorial for a specific amount of iterations in Python

I am trying to calculate a factorial for the number 56 for only 5 times, such that my answer should be = 458,377,920; where the factorial looks like this:
56 x 55 x 54 x 53 x 52 = 458,377,920.
my current code looks like the following and it is not working:
def my_factorial(n, b):
count = 1
vlue = n
if n == 1:
return n
else:
while b > count:
for i in range(b):
vlue = vlue * (vlue - 1)
b -= 1
print(vlue)
return vlue
my_factorial(56, 5)
the results are not as expected:
3080
9483320
89933348739080
8088007215424892292570507320
65415860716765120080996841652938441974495741189603075080
The body of the loop never decrement or used n
n -= 1
vlue = vlue * n
b -= 1
Try this
def my_factorial(n, b):
vlue = n
if n == 1:
return n
else:
for _ in range(b):
vlue = vlue * (n - 1)
n = n - 1
return vlue
print(my_factorial(56, 5))
FWIW, I rewrote the function from the ground up, as an exercise.
def falling_factorial(n, b):
"""
Return the product of n..n-b+1.
>>> falling_factorial(4, 2) # 4*3
12
>>> falling_factorial(5, 3) # 5*4*3
60
>>> falling_factorial(56, 1)
56
>>> falling_factorial(56, 0)
1
"""
r = 1 # Running product
for i in range(n, n-b, -1):
r *= i
return r
Usage:
>>> falling_factorial(56, 5)
458377920

Combination in Python

I am trying to understand the Algo of combinations function in python
def combinations(iterable, r):
# combinations('ABCD', 2) --> AB AC AD BC BD CD
# combinations(range(4), 3) --> 012 013 023 123
pool = tuple(iterable)
n = len(pool)
if r > n:
return
indices = list(range(r))
yield tuple(pool[i] for i in indices)
while True:
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
else:
return
indices[i] += 1
for j in range(i+1, r):
indices[j] = indices[j-1] + 1
yield tuple(pool[i] for i in indices)
But I am unable to understand why if indices[i] != i + n - r: and
for j in range(i+1, r):
indices[j] = indices[j-1] + 1is used in this function what is their role.
Please help me .
I think a solution like this will do, what you are trying to achieve
combinationDict = []
def combinations(iterable, r, cnt, subPart):
if cnt > r:
return
if cnt == r:
combinationDict.append(subPart)
return
if (len(iterable) < r):
return
i = 0
while i < len(iterable):
combinations(iterable[:i]+iterable[i+1:], r, cnt+1, subPart+iterable[i])
combinations(iterable[:i]+iterable[i+1:], r, cnt, subPart)
i += 1
combinations("ABCD", 2, 0, "")
print(combinationDict)
Basically main aim of the above solution is, at each step of recursion, either to add a particular element at i or don't add it to the combination.
Let's say for example of ABCD and 2, we start with A, then we add B, then we see size is 2, we return, we add C to A as we return back to the recursive call.
Now this, solution has exponential time complexity as it is a brute force solution.
Hope this helps!

Resources