我正在尝试编写一个函数来计算字符串的唯一排列数。例如aaa
将返回1
而abc
将返回6
我正在写这样的方法:
(伪代码:)
len(string)! / (A!*B!*C!*...)
其中A,B,C是每个唯一字符的出现次数。例如,字符串'aaa'
为3! / 3! = 1
,而'abc'
为3! / (1! * 1! * 1!) = 6
。
到目前为止我的代码是这样的:
def permutations(n):
'''
returns the number of UNIQUE permutations of n
'''
from math import factorial
lst = []
n = str(n)
for l in set(n):
lst.append(n.count(l))
return factorial(len(n)) / reduce(lambda x,y: factorial(x) * factorial(y), lst)
一切正常,除非我尝试传递一个只有一个唯一字符的字符串,即aaa
- 我得错了答案:
>>> perm('abc')
6
>>> perm('aaa')
2
>>> perm('aaaa')
6
现在,我可以告诉问题是在长度为1的列表中运行带有阶乘的lambda函数。但我不知道为什么。大多数其他lambda函数在长度为1的列表上工作,即使它期望两个元素:
>>> reduce(lambda x,y: x * y, [3])
3
>>> reduce(lambda x,y: x + y, [3])
3
这个没有:
>>> reduce(lambda x,y: ord(x) + ord(y), ['a'])
'a'
>>> reduce(lambda x,y: ord(x) + ord(y), ['a','b'])
195
我应该采取哪些不同的做法?我知道我可以通过许多不同的方式重写函数来避免这种情况(例如,不使用lambda
),但我正在寻找为什么这种方法不起作用。
答案 0 :(得分:2)
请参阅reduce()
的文档,有一个可选的'initializer'参数放在列表中的所有其他元素之前,以便一个元素列表的行为是一致的,例如,对于{{1你可以将ord()
设置为initializer
为0的字符:
ord()
答案 1 :(得分:1)
Python的reduce
函数并不总是知道默认(初始)值应该是什么。应该有一个采用初始值的版本。提供合理的初始值,reduce
应该可以很好地工作。
另外,根据评论,您可能只需在lambda中的第二个参数上使用factorial
:
reduce(lambda x,y: x * factorial(y), lst, 1)
答案 2 :(得分:1)
如果您需要len(s)! / A!*B!*C!
,那么使用reduce()
将无效,因为它会计算factorial(factorial(A)*factorial(B))*factorial(C)
。换句话说,它确实需要操作是可交换的。
相反,您需要生成因子列表,然后将它们相乘:
import operator
reduce(operator.mul, [factorial(x) for x in lst])
答案 3 :(得分:0)
通过首先计算序列中前两个元素的结果来减少工作,然后从那里伪递归地跟随。大小为1的列表是一种特殊情况。
我会在这里使用列表理解:
prod( [ factorial(val) for val in lst ] )
祝你好运!