2011-09-26 54 views
1

我正在尝试编写一个函数来计算字符串的唯一排列数。例如,aaa将返回1abc将返回6
我正在写的方法是这样的:在reduce函数中使用lambda函数中的math.factorial()

(伪代码:)

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),但我正在寻找为什么这种方法不起作用。

回答

1

Python的reduce函数并不总是知道默认(初始)值应该是什么。应该有一个具有初始值的版本。提供一个合理的初始值,你的reduce应该很好地工作。

此外,从意见,你应该只使用factorial在第二个参数中的拉姆达:

reduce(lambda x,y: x * factorial(y), lst, 1) 
+0

@agf和铂嗯Azure - 谢谢,这适用于大小为1的列表,但任何更大的失败。为什么?文档似乎认为应该将初始值视为列表只是一个元素的长度。 – HodofHod

+4

你可以尝试'reduce(lambda x,y:x * factorial(y),lst,1)'。你计算的拉姆达像'((1!* 2!)!* 3!)! ...'。 – cHao

+1

你确定你应该在第一个参数上使用'factorial(x)'吗?如果你想要所有阶乘的乘积,你应该使用'reduce(lambda x,y:x * factorial(y),lst,1)'。 –

0

首先降低工程计算结果为序列中的前两个元素,然后从那里伪递归地跟随。大小为1的列表是特例。

我会在这里使用列表理解:

prod([ factorial(val) for val in lst ]) 

祝你好运!

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]) 
2

查看文档reduce(),有是所有其他元素之前放置一个可选的“初始”的说法在列表中,这样的一个元素列表的行为是一致的,例如,您ord()拉姆达你可以设置initializer构成的字符与ord()为0的:

>>> reduce(lambda x, y: ord(x) + ord(y), ['a'], chr(0)) 
97