2011-09-26 81 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