class unique_element:
def __init__(self,value,occurrences):
self.value = value
self.occurrences = occurrences
def perm_unique(elements):
eset=set(elements)
listunique = [unique_element(i,elements.count(i)) for i in eset]
u=len(elements)
return perm_unique_helper(listunique,[0]*u,u-1)
def perm_unique_helper(listunique,result_list,d):
if d < 0:
yield tuple(result_list)
else:
for i in listunique:
if i.occurrences > 0:
result_list[d]=i.value
i.occurrences-=1
for g in perm_unique_helper(listunique,result_list,d-1):
yield g
i.occurrences+=1
a = list(perm_unique([1,1,2]))
print(a)
result:
[(2, 1, 1), (1, 2, 1), (1, 1, 2)]
EDIT (как это работает):
Я переписал верхнюю программу более длинной, но более читаемой
Обычно мне сложно объяснить, как что-то работает, но позвольте мне попробовать. Чтобы понять, как это работает, вам нужно понять схожую, но более простую программу, которая даст все перестановки с повторением.
def permutations_with_replacement(elements,n):
return permutations_helper(elements,[0]*n,n-1)#this is generator
def permutations_helper(elements,result_list,d):
if d<0:
yield tuple(result_list)
else:
for i in elements:
result_list[d]=i
all_permutations = permutations_helper(elements,result_list,d-1)#this is generator
for g in all_permutations:
yield g
Эта программа, очевидно, намного проще: d обозначает глубину в permutations_helper и имеет две функции. Одна из функций - это условие остановки нашего рекурсивного алгоритма, а другое - для списка результатов, которое передается.
Вместо того, чтобы возвращать каждый результат, мы его даем. Если функции / оператора yield
не было, нам пришлось бы вывести результат в какую-то очередь в точке остановки. Но таким образом, как только условие остановки встречается, результат распространяется через весь стек до вызывающего. Это цель for g in perm_unique_helper(listunique,result_list,d-1): yield g
, поэтому каждый результат распространяется до вызывающего.
Вернуться к исходной программе: У нас есть список уникальных элементов. Прежде чем мы сможем использовать каждый элемент, мы должны проверить, сколько из них все еще доступно, чтобы нажать его на result_list. Работа этой программы очень похожа по сравнению с permutations_with_replacement
разницей в том, что каждый элемент не может повторяться больше раз, чем в perm_unique_helper.
Если вы используете систему unix, вы можете использовать netstat, чтобы узнать, какой процесс прослушивает порт:
sudo netstat -nlp | grep 9000
Выключает опцию -p, недоступную для OS X. Если вы используют OS X, вы можете это сделать:
lsof -n -i4TCP:$PORT | grep LISTEN