Im trying to replicate the function from itertools.permutations()
for purely didactic reasons.
One way of doing it was using lists of 1s, where 0 marks that a given elements has already being used.
So for instance, a list of letters:
list_l = ['a','b','c']
and the list [0,1,1]
marks that a
has already being used.
I pass this list to same function, and it generates the sublists [0,0,1]
and [0,1,0]
which corresponds to letters b being selected and c by elimination for the first list and c and then b for the second.
This method of marking the letters in positions of a list, requires me to keep an historial for each position of the combination, so even though I get the correct result I would like to make the function a generator giving one result at a time, but I don't know how to do it without breaking the recursivity and therefore destroying the program. I need the return for keeping the historial clean for the next element to be generated and i doubt it is possible to use yield and return in parallel.
I leave my code here. Thank you
def generate_string(list, a):
comb = ''
for n, v in enumerate(a[0]):
if v==0:
comb = comb + lista[n]
for i in range(len(a)-1):
for n,j in enumerate(zip(a[i], a[i+1])):
if j[0] != j[1]:
comb = comb + lista[n]
for n, v in enumerate(a[-1]):
if v==1:
comb = comb + lista[n]
return comb
def comb(lista, uns = None, historial = []):
if uns == None:
l = [1] *len(lista)
comb(lista, uns = l)
else:
if sum(uns) == 1:
print(generate_string(lista, historial).upper())
return historial[:-1]
else:
for n, valor in enumerate(uns):
uns2 = copy.deepcopy(uns)
if valor == 1:
uns2[n] = 0
historial.append(uns2)
historial = comb(lista, uns2, historial)
return historial[:-1]
lista = ['a','b','c','d']
comb(lista)