2013-02-25 73 views
1

我試圖在書中做一個問題,但我不知道如何。問題是,Write函數geometric()將整數列表作爲輸入,如果列表中的整數形成幾何序列,則返回True。如果比率a1/a0,a2/a1,a3/a2,a4/a3,...,a-a0,a1,a2,a3,a4,...,an- an-1/an-2都是平等的。python幾何序列

def geometric(l): 
for i in l: 
    if i*1==i*0: 
     return True 
else: 
    return False 

我真的不知道如何開始這個,我完全畫空白。任何幫助,將不勝感激。

謝謝!

例如:

geometric([2,4,8,16,32,64,128,256]) 
>>> True 

geometric([2,4,6,8])` 
>>> False 

回答

0

像這樣

def is_geometric(l): 
    if len(l) <= 1: # Edge case for small lists 
     return True 
    ratio = l[1]/float(l[0]) # Calculate ratio 
    for i in range(1, len(l)): # Check that all remaining have the same ratio 
     if l[i]/float(l[i-1]) != ratio: # Return False if not 
      return False 
    return True # Return True if all did 

而且更冒險

def is_geometric(l): 
    if len(l) <= 1: 
     return True 
    r = l[1]/float(l[0]) 
    # Check if all the following ratios for each 
    # element divided the previous are equal to r 
    # Note that i is 0 to n-1 while e is l[1] to l[n-1] 
    return all(True if e/float(l[i]) == r else False for (i, e) in enumerate(l[1:])) 
1

一個簡單的方法是這樣的:

 
def is_geometric(a): 
    r = a[1]/float(a[0]) 
    return all(a[i]/float(a[i-1]) == r for i in xrange(2,len(a))) 

基本上,它計算前兩者之間的比率,並使用all來確定生成器的所有成員是否都爲真。生成器的每個成員都是一個布爾值,表示兩個數字之間的比率是否等於前兩個數字之間的比率。

3

這應該有效地處理所有可迭代的對象。

from itertools import izip, islice, tee 

def geometric(obj): 
    obj1, obj2 = tee(obj) 
    it1, it2 = tee(float(x)/y for x, y in izip(obj1, islice(obj2, 1, None))) 
    return all(x == y for x, y in izip(it1, islice(it2, 1, None))) 

assert geometric([2,4,8,16,32,64,128,256]) 
assert not geometric([2,4,6,8]) 

退房itertools - http://docs.python.org/2/library/itertools.html

+0

是作爲獎勵,我可以通過避免做任何部門(這可能在理論上,導致浮點四捨五入問題)堅持純粹的整數運算!我喜歡。 – Ric 2013-02-25 07:35:53

+0

但是你在'all()'中放鬆了短路嗎?你必須計算所有比率。 – Ric 2013-02-25 07:41:11

+0

不,所有'應該照顧短路。嘗試'幾何(xrange(1,1000000000))'......立即運行。 – pyrospade 2013-02-25 07:53:36

1

這裏是我的解決方案。它基本上與pyrospade的itertools代碼相同,但發生器反彙編。

def geometric(iterable): 
    it = iter(iterable) 
    try: 
     a = next(it) 
     b = next(it) 
     if a == 0 or b == 0: 
      return False 
     c = next(it) 
     while True: 
      if a*c != b*b: # <=> a/b != b/c, but uses only int values 
       return False 
      a, b, c = b, c, next(it) 
    except StopIteration: 
     return True 

一些測試結果:

>>> geometric([2,4,8,16,32]) 
True 
>>> geometric([2,4,6,8,10]) 
False 
>>> geometric([3,6,12,24]) 
True 
>>> geometric(range(1, 1000000000)) # only iterates up to 3 before exiting 
False 
>>> geometric(1000**n for n in range(1000)) # very big numbers are supported 
True 
>>> geometric([0,0,0]) # this one will probably break every other code 
False 
+0

你應該注意到這是Python 3代碼(因爲在Python 2.x中'range'不返回一個迭代器)。這是一個非常棒的解決方案。天才的想法代數重新排列'a/b!= b/c'到'a * c!= b * b'。我很嫉妒! – pyrospade 2013-02-25 15:56:49

+0

唯一的問題是'geometric([0,0,0])'可能不應該是'True',因爲幾何序列是用分割定義的 - http://en.wikipedia.org/wiki/Geometric_series – pyrospade 2013-02-25 16:13:14

+0

@pyrospade:關於[0,0,0],你可能是對的。這取決於你如何定義事物。 [幾何進程](http://en.wikipedia.org/wiki/Geometric_progression)上的維基百科頁面給出了一個定義:全零序列滿足('0,0 * r,0 * r ** 2,.. 。'對於任何'r'),但問題確實有一個需要劃分的定義。在任何情況下,如果'b'或'c'爲零,我就不允許對代數比率進行代數運算,所以我認爲它的計算方法不正確。 – Blckknght 2013-02-26 00:49:46