Python yield statement issue in recursive function? - python

Now, I learn to how to use yield in python program. so I want to implement word permutation in python.
def permuteArr(arr, index=0):
'''(list, int) -> list
Get all the permutation of the elements in list.
>>> arr = ['a', 'b', 'c']
>>> for val in permuteArr(arr):
print val
'''
if index == len(arr):
yield arr
else:
for idx in range(index, len(arr)):
arr[idx], arr[index] = arr[index], arr[idx]
for val in permuteArr(arr, idx+1):
yield val
arr[idx], arr[index] = arr[index], arr[idx]
if '__name__' == '__main__':
arr = ['a', 'b', 'c']
for val in permuteArr(arr, 0):
print val
However, I run it in python shell under window, the results are not correct. There are only four results.
>>> for v in permuteArr(['a', 'b', 'c']):
print v
['a', 'b', 'c']
['a', 'c', 'b']
['b', 'a', 'c']
['c', 'b', 'a']
Is anything wrong when I use yield or in my program?

In loop for val in permuteArr(arr, idx+1): replace idx + 1 on index + 1

Related

Combining values in an array in Python

I have an array like so: ['A', 'B', 'C', 'D', 'E'].
I've been trying to figure out how to make it like so: ['AB', 'CD', 'E']
I'm not sure where to start. Thanks in advance!
main.py
a = ['A', 'B', 'C', 'D', 'E']
b = [i + j for i, j in zip(a[:-1:2], a[1::2])]
if len(a) % 2 == 1:
b.append(a[-1])
print(b)
result
$ python main.py
['AB', 'CD', 'E']
>>> [''.join(a[i:i+2]) for i in range(0, len(a), 2)]
['AB', 'CD', 'E']
or (as I love iterators)
>>> it = iter(a)
>>> [s + next(it, '') for s in it]
['AB', 'CD', 'E']
I think that the easier way is to iterate through the array and concatenate the chars, it works if you have an array with even length, so you could add a check and append the last element in case of odd length.
array = ['A', 'B', 'C', 'D', 'E']
array2 = [f"{array[i]}{array[i+1]}" for i in range(0, len(array)-1, 2)]
if len(array)%2!=0:
array2.append(array[-1])
print(array2)
Try like this. This is very bare answer but should work.
my_array = ['A', 'B', 'C', 'D', 'E']
def combine_array(my_array):
mixed_array = []
start_new = True
for item in my_array:
if start_new:
mixed_array.append(item)
start_new = False
else:
mixed_array[-1] = mixed_array[-1] + item
start_new = True
return mixed_array
if __name__ == "__main__":
try:
print(combine_array(my_array))
except Exception as err:
print(err)
startArray = ['A', 'B', 'C', 'D', 'E']
currentIndex = 0
finishArray = ['']
for x in startArray:
if len(finishArray[currentIndex]) == 2:
currentIndex += 1
finishArray.insert(currentIndex,x)
else:
finishArray[currentIndex] += x
print(finishArray)

python consecutive elements to swap the list items [duplicate]

This question already has answers here:
What is the simplest way to swap each pair of adjoining chars in a string with Python?
(20 answers)
Closed 3 years ago.
here my input like:
['a','b','c','d','e','f']
output:
['b','a','d','c','f','e']
I tried to get consecutive list but i'm getting list in between empty string so please make to remove those empty list .
s = list(input().split())
def swap(c, i, j):
c[i], c[j] = c[j], c[i]
return ' '.join(c)
result = swap(s, 0, 1)
print(list(result))
current output:- ['b', ' ', 'a', ' ', 'c', ' ', 'd', ' ', 'e', ' ', 'f']
expected output:-['b', 'a', 'c', 'd', 'e','f']
You just need to return c as list, there is not need to convert to string and back again into a list:
s = ['a','b','c','d','e','f']
def swap(c, i, j):
c[i], c[j] = c[j], c[i]
return c
result = swap(s, 0, 1)
print(result)
Output:
['b', 'a', 'c', 'd', 'e', 'f']
a simple function to swap pairs that does not change the input:
def swap_pairs(list_to_swap):
s = list_to_swap[:] # create copy to not touch the original sequence
for i in range(0, len(s)-1, 2):
s[i], s[i+1] = s[i+1], s[i]
return s
s0 = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
s1 = ['a', 'b', 'c', 'd', 'e', 'f']
print(swap_pairs(s0))
print(swap_pairs(s1))
# ['b', 'a', 'd', 'c', 'f', 'e', 'g']
# ['b', 'a', 'd', 'c', 'f', 'e']
### check if s0 and s1 are untouched:
print(s0)
print(s1)
# ['a', 'b', 'c', 'd', 'e', 'f', 'g']
# ['a', 'b', 'c', 'd', 'e', 'f']
if you want to swap pairs 'in place', i.e. directly change the input, you could shorten the process to
def swap_pairs(s):
for i in range(0, len(s)-1, 2):
s[i], s[i+1] = s[i+1], s[i]
# return s
s1 = ['a', 'b', 'c', 'd', 'e', 'f']
swap_pairs(s1)
print(s1)
# ['b', 'a', 'd', 'c', 'f', 'e']
I think it's a matter of taste if a return statement should be added here. I'd consider it to be more clear not to return something since logically not needed. Anyway, be aware of variable scope.
this is the problem.. your joining on space. change it to the following.
def swap(c, i, j):
c[i], c[j] = c[j], c[i]
return ''.join(c)
for your output you could also do the following.
l = [x for x in [your output list] if x!= ' ']
or
l = [x for x in [your output list] if len(x.strip()) > 0]
Try returning only "C" and use recursion for swapping of all elements of list Then you will get expected Output. Check below code.
Output of below code: ['b','a','d','c','f','e']
s = ['a','b','c','d','e','f']
def swap(c, i, j):
if j<=len(c) and len(c)%2==0:
c[i], c[j] = c[j], c[i]
swap(c,i+2,j+2)
elif j<len(c):
c[i], c[j] = c[j], c[i]
swap(c,i+2,j+2)
return c
result = swap(s, 0, 1)
print(list(result))
and if you want Only output= ['b','a','c','d','e','f'] then no need of recursion just return c. Check below code:
s = ['a','b','c','d','e','f']
def swap(c, i, j):
c[i], c[j] = c[j], c[i]
return c
result = swap(s, 0, 1)
print(list(result))

How can I reverse a section of a list using a loop in Python?

I'm in need of a little help reversing a section of a list in Python using a loop.
I have a list: mylist = ['a', 'b', 'c', 'd', 'e', 'f']
Also have an index number, this number will tell where to start the reversing. For example, if the reverse-index number is 3, it needs to be something like this: ['d', 'c', 'b', 'a', 'e', 'f']
What I currently have:
def list_section_reverse(list1, reverse_index):
print("In function reverse()")
n_list = []
for item in range( len(list1) ):
n_list.append( (list1[(reverse_index - 1) - item]) )
item += 1
return n_list
mylist = ['a', 'b', 'c', 'd', 'e', 'f']
print( list_section_reverse(mylist, 3) )
Which returns ['c', 'b', 'a', 'f', 'e', 'd']
How can I alter my code, so that it prints out ['d', 'c', 'b', 'a', 'e', 'f']?
You can simply use:
def list_section_reverse(list1, reverse_index):
return list(reversed(list1[:reverse_index+1])) + list1[reverse_index+1:]
Edit: The problem with your existing solution is that you keep reversing after reverse_index. If you have to use a loop, try this:
def list_section_reverse(list1, reverse_index):
print("In function reverse()")
n_list = list1[:]
for i in range(reverse_index + 1):
n_list[i] = list1[-i-reverse_index]
return n_list
mylist = ['a', 'b', 'c', 'd', 'e', 'f']
print(list_section_reverse(mylist, 3))
The pythonic solution:
list1[reverse_index::-1] + list1[reverse_index+1:]
Now, that's not using loops like you asked. Well, not explicitly... Instead we can break down the above into its constituent for loops.
def list_section_reverse(list1, reverse_index):
if reverse_index < 0 or reversed_index >= len(list1):
raise ValueError("reverse index out of range")
reversed_part = []
for i in range(reverse_index, -1, -1): # like for i in [n, n-1, ..., 1, 0]
reversed_part.append(list1[i]
normal_part = []
for i in range(reverse_index + 1, len(list1)):
normal_part.append(list1[i])
return reversed_part + normal_part
Is it allowed to make a copy of the list?
def list_section_reverse(list1, reverse_index):
print("In function reverse()")
n_list = [ element for element in list1 ]
for item in range( reverse_index + 1 ):
n_list[ item ] = list1[ reverse_index - item ]
item += 1
return n_list
mylist = ['a', 'b', 'c', 'd', 'e', 'f']
print(list_section_reverse(mylist, 3))
Outs:
In function reverse()
['d', 'c', 'b', 'a', 'e', 'f']
You can modify the list inplace using a slice.
mylist[:4] = mylist[:4][::-1]
You can try this. This makes use of no slicing, and can use either a while loop or for loop.
def reversed_list(my_list, index):
result = []
list_copy = my_list.copy()
i = 0
while i < index+1:
result.append(my_list[i])
list_copy.remove(my_list[i])
i+=1
result.reverse()
return result + list_copy
Or with a for loop
def reversed_list(my_list, index):
result = []
list_copy = my_list.copy()
for i in range(len(my_list)):
if i < index + 1:
result.append(my_list[i])
list_copy.remove(my_list[i])
result.reverse()
return result + list_copy

Indexing a list of permutations in Python

This code generates the list of all permutations:
def permute(xs, low=0):
if low + 1 >= len(xs):
yield xs
else:
for p in permute(xs, low + 1):
yield p
for i in range(low + 1, len(xs)):
xs[low], xs[i] = xs[i], xs[low]
for p in permute(xs, low + 1):
yield p
xs[low], xs[i] = xs[i], xs[low]
for p in permute(['A', 'B', 'C', 'D']):
print p
What I would like to do create an index for the list of permutations so that if I call a number I can access that particular permutation.
For example:
if index.value == 0:
print index.value # ['A','B','C','D']
elif index.value == 1:
print index.value # ['A','B','D','C']
#...
I am new to Python, thank you in advance for any guidance provided.
You can also create a new function getperm to get the permutation index from your generator:
def getperm(index,generator):
aux=0
for j in generator:
if aux == index:
return j
else:
aux = aux +1
In: getperm(15,permute(['A', 'B', 'C', 'D']))
Out: ['C', 'A', 'D', 'B']
Iterators does not support "random access". You'll need to convert your result to list:
perms = list(permute([....]))
perms[index]
Like levi said, it sounds like you want to use a dictionary.
The dictionary will look something like this:
#permDict = {0:['A', 'B', 'C', 'D'], 1:['A', 'B', 'D', 'C'], ...}
permDict = {}
index = 0
for p in permute(['A', 'B', 'C', 'D']):
permDict[index] = p
index += 1
Then just get a value according to the key you have assigned.
if index == 0:
print permDict[0] # ['A','B','C','D']
elif index == 1:
print permDict[1] # ['A','B','D','C']
#...
Or just store each permutation in a list and call those indices.
permList = [p for p in permute(['A', 'B', 'C', 'D'])]
#permList[0] = ['A', 'B', 'C', 'D']
#permlist[1] = ['A', 'B','D', 'C']
You can generate the desired permutation directly (without going through all previous permutations):
from math import factorial
def permutation(xs, n):
"""
Return the n'th permutation of xs (counting from 0)
"""
xs = list(xs)
len_ = len(xs)
base = factorial(len_)
assert n < base, "n is too high ({} >= {})".format(n, base)
for i in range(len_ - 1):
base //= len_ - i
offset = n // base
if offset:
# rotate selected value into position
xs[i+1:i+offset+1], xs[i] = xs[i:i+offset], xs[i+offset]
n %= base
return xs
then
>>> permutation(['A', 'B', 'C', 'D'], 15)
['C', 'B', 'D', 'A']

function for nCk chose k elements from list of n in python

I'm trying to write a function that makes nCk from the list in python
for example from the list for pairs:
['a', 'b', 'c']
output should be:
[['a','b'],['a','c'],['b','c']]
however I'm getting no output
here's my attempt:
def chose(elements, k):
output = []
for i in range(len(elements)):
if k == 1:
output.append(elements[i])
for c in chose(elements[i+1:], k-1):
output.append(elements[i])
output.append(c)
return output
print chose(['a', 'b', 'c'],2)
can you kindly tell what is wrong with function
Use itertools.combinations if you want to find all combinations:
from itertools import combinations
a = ['a', 'b', 'c']
result = [list(i) for i in combinations(a,2)]
The documentation and implementation of the combinations() function can be found on here ...
Update
This function should do what you want:
def chose(elements, k):
output = []
if k == 1:
return [[i] for i in elements]
else:
for i in range(len(elements)):
head = elements[i]
tails = chose(elements[i+1:], k-1)
output += [[head] + tail for tail in tails]
return output
print chose(['a','b','c'], 2)
You can use a powerset without using any imports:
def power_set(items,k):
n = len(items)
for i in xrange(2**n):
combo = []
for j in xrange(n):
if (i >> j) % 2 == 1:
combo.append(items[j])
if len(combo) == k:
yield combo
print(list(power_set(['a', 'b', 'c'],2)))
[['a', 'b'], ['a', 'c'], ['b', 'c']]

Categories