I'm having trouble writing a function to display all of the permutations of a list. Here is my code. The main function is given and I cannot change it. When I ran the code, nothing showed up. What's wrong with my code?
def perm(lst):
if len(lst) == 0:
return []
if len(lst) == 1:
return [lst]
l = []
for i in range(len(lst)):
m = lst[i]
rem = lst[:i] + lst[i+1:]
for p in perm(rem):
l.append([m] + p)
return l
def main():
list = input().split(',')
start = []
perm(list)
if __name__ == "__main__":
main()
The input is: A,B,C
The expected output is:
['A', 'B', 'C']
['A', 'C', 'B']
['B', 'A', 'C']
['B', 'C', 'A']
['C', 'A', 'B']
['C', 'B', 'A']
Nothing's wrong with your code. Just need to print the results.
def main():
list = input().split(',')
print perm(list)
A bit of advice: it's a bad idea to use list as variable name, since it will alias the built-in type list.
Your function is fine as far as the permutations go. However, it only returns the list of permutations. It appears, the task as given expects it to print them as well. Just insert right before (or instead of) the return statement:
def perm(lst, lvl=0): # add recursion level as parameter
if len(lst) == 0:
return []
if len(lst) == 1:
return [lst]
l = []
for i in range(len(lst)):
m = [lst[i]]
for p in perm(lst[:i] + lst[i+1:], lvl+1):
l.append(m + p)
if lvl == 0: # only print if it is the top call
for p in l:
print(p)
return l
There is no print in your code, which is why you don't have any output. Because your function is recursive, and at deeper recursion levels the list is shorter, you'll only want to print at the outermost level.
It is probably the easiest if you wrap your function in yet another function, and only print in that wrapping function. Rename the original function to something else, and call the outer one perm:
def perm(lst):
# The original function, but renamed:
def recurse(lst):
print('recurse', lst)
if len(lst) == 0:
return []
if len(lst) == 1:
return [lst]
l = []
for i in range(len(lst)):
m = lst[i]
rem = lst[:i] + lst[i+1:]
for p in recurse(rem): # call the renamed function
l.append([m] + p)
return l
# only print in the wrapping function
l = recurse(lst)
print (l)
return l
With some use of list comprehension and moving the len(lst) == 0 test out of the recursive function, you can rewrite the above to:
def perm(lst):
def recurse(lst):
if len(lst) == 1:
return [lst]
return [[m] + p for i, m in enumerate(lst) for p in recurse(lst[:i] + lst[i+1:])]
l = recurse(lst) if len(lst) > 0 else []
print(l)
return l
You can also use itertools.permutations for this:
>>> from itertools import permutations
>>> list(permutations(['A','B','C']))
[('A', 'B', 'C'), ('A', 'C', 'B'), ('B', 'A', 'C'), ('B', 'C', 'A'), ('C', 'A', 'B'), ('C', 'B', 'A')]
Related
This question already has answers here:
Rolling or sliding window iterator?
(29 answers)
Closed 7 years ago.
I am trying to make an overlap function in python that takes any iterable, an int n, and an int m (whose default value is 1) as parameters, and produce lists of n values:
The first list contains the first n values;
Every subsequent list drops the first m from the previous list
Adds next m values from the iterator, until there are fewer than n values to put in the returned list.
Example:
for i in overlap('abcdefghijk',4,2):
print(i,end=' ')
Its output is ['a','b','c','d'], ['c','d','e','f'], ['e','f','g','h'], and ['g','h',i','j'] for n=4 and m=2. In this case if the function is something like this:
def overlap(iterable, n, m=1)
How can this be done? The main problem I am facing is how to stop when there are less than n values.
Current code: credits to anmol_uppal's solution.
def hide(iterable):
for v in iterable:
yield v
def overlap(word, n, m):
start = 0
while(start+n < len(word)):
yield list(word[start:start+n])
start += m
if __name__ == '__main__':
for i in overlap('abcdefghijk',3,2):
print(i, end=' ')
print()
for i in overlap(hide('abcdefghijk'),3,2):
print(i, end=' ')
print()
But the problem is we cannot use len() with generators.
I have tried this code but I don't know why it's giving unexpected results for the second test case
def hide(iterable):
for v in iterable:
yield v
def window(seq, size, step=1):
iters = [iter(seq) for i in range(size)]
[next(iters[i]) for j in range(size) for i in range(-1, -j-1, -1)]
while(True):
yield [next(i) for i in iters]
[next(i) for i in iters for j in range(step-1)]
if __name__ == '__main__':
for i in window('abcdefghijk', 3, 2):
print(i, end=' ')
print()
for i in window(hide('abcdefghijk'), 3, 2):
print(i, end=' ')
print()
def overlap(word, n,m):
ans = []
start = 0
while(start+n<len(word)):
ans.append(list(word[start:start+n]))
start+=m
return ans
>>> print overlap("abcdefghijk", 4, 2)
>>> [['a', 'b', 'c', 'd'], ['c', 'd', 'e', 'f'], ['e', 'f', 'g', 'h'], ['g', 'h', 'i', 'j']]
>>> print overlap("abcdefghi", 4, 2)
>>> [['a', 'b', 'c', 'd'], ['c', 'd', 'e', 'f'], ['e', 'f', 'g', 'h']]
Also if you would like to yield the results instead of returning them,then you can use the following simpler version:
def overlap(word, n,m):
start = 0
while(start+n<len(word)):
yield list(word[start:start+n])
start+=m
for i in overlap("abcdefghijk", 4, 2):
print (i,end = " ")
To make it work with the hide() function you need to convert it to string first, so:
for i in overlap("".join(hide("abcdefghijk")),3, 2):
print i
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']
I'm not sure about the term of this technique. I want to create a list where if I try to access an element outside the list range, the list would "loop itself". Example of the behaviour I want to achieve:
>>> musical_scale = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
>>> musical_scale[2]
E
>>> musical_scale[7]
C
>>> musical_scale[-1]
B
I guess I could write a class which does this, but I thought there might be a more correct way of doing it.
Creating a subclass of List would be a pretty useful way of doing this. Something like this, perhaps:
class modList(list):
def __getitem__(self, i):
if len(self) == 0:
raise IndexError # Or do something else if you want, like return []
i = i % len(self) # self.__len__() works also
return super(modList, self).__getitem__(i) # In Python 3, super().__getitem__(i)
If you want to do slicing, it's a little more complicated, but similar. Found this while looking through StackOverflow:
def __getitem__(self, i):
if isinstance(i, int):
if len(self) == 0:
raise IndexError
i = i % len(self)
return super(modList, self).__getitem__(i) # list.__getitem__(i) works too
elif isinstance(i, slice):
if len(self) == 0:
return []
start = i.start % len(self)
stop = i.stop % len(self)
step = i.step
return super(modList, self).__getItem__(slice(start, stop, step))
else:
raise TypeError("invalid index")
Though this slice modding could give you a situation like [3:2], which will return an empty list. Basically slicing is hard and you'll need to decide how you want to implement it, but hopefully this is a start.
http://www.stackoverflow.com/questions/3911483/python-slice-how-to-i-know-the-python-slice-but-how-can-i-use-built-in-slice-ob
(Thanks #JonClements for all the suggestions in chat.)
EDIT: now we have some handlers for if you have an empty list. #wim suggests raising an error for single accesses, and returning [] for slices. Really it's up to you what you want to do but that seemed sensible to me, so that's what I've included in this answer.
EDIT EDIT: if you're using Python 2.x, I believe you also need to override __getslice__.
Use the modulus operator % to "loop back" after indexing past the end of the list
>>> musical_scale = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
def getValue(x, l):
return l[x % len(l)]
>>> getValue(0, musical_scale)
'C'
>>> getValue(9, musical_scale)
'E'
In case you'd like to extend the list class to handle getting and setting...
class UnsatList(list):
def __getitem__(self, index):
try:
return list.__getitem__(self, index % len(self))
except ZeroDivisionError:
raise IndexError('list assignment index out of range')
def __setitem__(self, index, value):
try:
return list.__setitem__(self, index % len(self), value)
except ZeroDivisionError:
raise IndexError('list assignment index out of range')
if __name__ == '__main__':
test_list = UnsatList([1,2,3,4])
assert test_list[0] == 1
assert test_list[4] == 1
assert test_list[8] == 1
assert test_list[-8] == 1
test_list[4] = 5
assert test_list[0] == 5
assert test_list[4] == 5
assert test_list[8] == 5
assert test_list[-8] == 5
Here is a solution, but remember The Zen of Python: Flat is better than nested.
You can write for example:
a = [1, [2]]
a[1].append(a)
Then your list a has "infinite depth", and you can loop on these two elements by repeatedly doing:
a[0]
a = a[1]
You can't do that without playing with depth, because unlike e.g. Lisp, Python lists are varying-length arrays, not linked-lists.
Here are little functions to do the whole stuff automatically:
def loopify(a):
r = b = []
for x in a:
b.append(x)
b.append([])
c = b
b = b[1]
c[1] = r
return r
def loopgen(a):
while True:
yield a[0]
a = a[1]
Then with your example:
musical_scale = loopify(['C', 'D', 'E', 'F', 'G', 'A', 'B'])
g = loopgen(musical_scale)
[next(g) for i in range(20)]
This yields:
['C', 'D', 'E', 'F', 'G', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'A']
Of course, it's also possible to use mod or to keep track of the current index and reseting it to 0 when you overflow your list. Other answers show you how to do that.
Also notice that the linked-list approach does not permit random access, only sequential access (thus the generator above). If you need to access you list randomly, modular arithmetic is the most appropriate way.
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']]
I have a list:
l=['a','>>','b','>>','d','e','f','g','>>','i','>>','>>','j','k','l','>>','>>']
I need to extract all the neighbors of '>>' and split them into groups where they have elements in between that are neither '>>' or neigbors of '>>'.
For the example list the expected outcome would be:
[['a', 'b', 'd'], ['g', 'i', 'j'], ['l']]
I have tried quite a few things, but all the simple ones have failed one way or another. At the moment the only code that seems to work is this:
def func(L,N):
outer=[]
inner=[]
for i,e in enumerate(L):
if e!=N:
try:
if L[i-1]==N or L[i+1]==N:
inner.append(e)
elif len(inner)>0:
outer.append(inner)
inner=[]
except IndexError:
pass
if len(inner):
outer.append(inner)
return outer
func(l,'>>')
Out[196]:
[['a', 'b', 'd'], ['g', 'i', 'j'], ['l']]
Although it seems to work, i am wondering if there is a better,cleaner way to do it?
I would argue that the most pythonic and easy to read solution would be something like this:
import itertools
def neighbours(items, fill=None):
"""Yeild the elements with their neighbours as (before, element, after).
neighbours([1, 2, 3]) --> (None, 1, 2), (1, 2, 3), (2, 3, None)
"""
before = itertools.chain([fill], items)
after = itertools.chain(items, [fill]) #You could use itertools.zip_longest() later instead.
next(after)
return zip(before, items, after)
def split_not_neighbour(seq, mark):
"""Split the sequence on each item where the item is not the mark, or next
to the mark.
split_not_neighbour([1, 0, 2, 3, 4, 5, 0], 0) --> (1, 2), (5)
"""
output = []
for items in neighbours(seq):
if mark in items:
_, item, _ = items
if item != mark:
output.append(item)
else:
if output:
yield output
output = []
if output:
yield output
Which we can use like so:
>>> l = ['a', '>>', 'b', '>>', 'd', 'e', 'f', 'g', '>>', 'i', '>>', '>>',
... 'j', 'k', 'l', '>>', '>>']
>>> print(list(split_not_neighbour(l, ">>")))
[['a', 'b', 'd'], ['g', 'i', 'j'], ['l']]
Note the neat avoidance of any direct indexing.
Edit: A more elegant version.
def split_not_neighbour(seq, mark):
"""Split the sequence on each item where the item is not the mark, or next
to the mark.
split_not_neighbour([1, 0, 2, 3, 4, 5, 0], 0) --> (1, 2), (5)
"""
neighboured = neighbours(seq)
for _, items in itertools.groupby(neighboured, key=lambda x: mark not in x):
yield [item for _, item, _ in items if item != mark]
Here is one alternative:
import itertools
def func(L, N):
def key(i_e):
i, e = i_e
return e == N or (i > 0 and L[i-1] == N) or (i < len(L) and L[i+1] == N)
outer = []
for k, g in itertools.groupby(enumerate(L), key):
if k:
outer.append([e for i, e in g if e != N])
return outer
Or an equivalent version with a nested list comprehension:
def func(L, N):
def key(i_e):
i, e = i_e
return e == N or (i > 0 and L[i-1] == N) or (i < len(L) and L[i+1] == N)
return [[e for i, e in g if e != N]
for k, g in itertools.groupby(enumerate(L), key) if k]
You can simplify it like this
l = ['']+l+['']
stack = []
connected = last_connected = False
for i, item in enumerate(l):
if item in ['','>>']: continue
connected = l[i-1] == '>>' or l[i+1] == '>>'
if connected:
if not last_connected:
stack.append([])
stack[-1].append(item)
last_connected = connected
my naive attempt
things = (''.join(l)).split('>>')
output = []
inner = []
for i in things:
if not i:
continue
i_len = len(i)
if i_len == 1:
inner.append(i)
elif i_len > 1:
inner.append(i[0])
output.append(inner)
inner = [i[-1]]
output.append(inner)
print output # [['a', 'b', 'd'], ['g', 'i', 'j'], ['l']]
Something like this:
l=['a','>>','b','>>','d','e','f','g','>>','i','>>','>>','j','k','l','>>','>>']
l= filter(None,"".join(l).split(">>"))
lis=[]
for i,x in enumerate(l):
if len(x)==1:
if len(lis)!=0:
lis[-1].append(x[0])
else:
lis.append([])
lis[-1].append(x[0])
else:
if len(lis)!=0:
lis[-1].append(x[0])
lis.append([])
lis[-1].append(x[-1])
else:
lis.append([])
lis[-1].append(x[0])
lis.append([])
lis[-1].append(x[-1])
print lis
output:
[['a', 'b', 'd'], ['g', 'i', 'j'], ['l']]
or:
l=['a','>>','b','>>','d','e','f','g','>>','i','>>','>>','j','k','l','>>','>>']
l= filter(None,"".join(l).split(">>"))
lis=[[] for _ in range(len([1 for x in l if len(x)>1])+1)]
for i,x in enumerate(l):
if len(x)==1:
for y in reversed(lis):
if len(y)!=0:
y.append(x)
break
else:
lis[0].append(x)
else:
if not all(len(x)==0 for x in lis):
for y in reversed(lis):
if len(y)!=0:
y.append(x[0])
break
for y in lis:
if len(y)==0:
y.append(x[-1])
break
else:
lis[0].append(x[0])
lis[1].append(x[-1])
print lis
output:
[['a', 'b', 'd'], ['g', 'i', 'j'], ['l']]
Another medthod using superimposition of original list
import copy
lis_dup = copy.deepcopy(lis)
lis_dup.insert(0,'')
prev_in = 0
tmp=[]
res = []
for (x,y) in zip(lis,lis_dup):
if '>>' in (x,y):
if y!='>>' :
if y not in tmp:
tmp.append(y)
elif x!='>>':
if x not in tmp:
print 'x is ' ,x
tmp.append(x)
else:
if prev_in ==1:
res.append(tmp)
prev_in =0
tmp = []
prev_in = 1
else:
if prev_in == 1:
res.append(tmp)
prev_in =0
tmp = []
res.append(tmp)
print res