2013-12-14 70 views
3

連續增加元件的數量我在TalentBuddy一個問題,這聽起來像這樣查找列表

學生在實驗室活動的表現應該不斷的提高,但事實並非總是如此。 因爲進步是學生最重要的指標之一,所以讓我們編寫一個程序,計算任何給定學生提高績效的最長時間。例如,如果他在一門課程中的所有實驗室活動的成績分別是:9,7,8,2,5,5,8,7,那麼最長的時間段將是連續4個實驗室(2,5,5,8)。

到目前爲止,我似乎對代碼工作感到困惑。只是我工作的事情是

def longest_improvement(grades): 
    res = 0 
    for i in xrange(len(grades) - 2): 
     while grades[i] <= grades[i + 1]: 
      res += 1 
      i += 1 
    print res 

但是,打印17,而不是6grades = [1, 7, 2, 5, 6, 9, 11, 11, 1, 6, 1]

如何制定出其餘的代碼?謝謝

+0

我覺得Tim在Tim Sort中使用了這個想法... :) – thefourtheye

回答

3

解決一些老式的尾遞歸:

grades = [1, 7, 2, 5, 6, 9, 11, 11, 1, 6, 1] 

def streak(grades): 
    def streak_rec(longest, challenger, previous, rest): 
     if rest == []:    # Base case 
      return max(longest, challenger) 
     elif previous <= rest[0]: # Streak continues 
      return streak_rec(longest, challenger + 1, rest[0], rest[1:]) 
     else:      # Streak is reset 
      return streak_rec(max(longest, challenger), 1, rest[0], rest[1:]) 

    return streak_rec(0, 0, 0, grades) 

print streak(grades) # => 6 
print streak([2]) # => 1 
+1

'streak([1])=> 2' – Voo

+0

糟糕,錯誤的初始累加器!固定。謝謝:) –

+0

最好的解決方案!真棒:) –

0

您在內部while循環的每次迭代中使用相同的res變量。您可能需要重置它,並將最高中間結果保留在不同的變量中。

0

有點晚,但這裏是我的更新版本:

from funcy import ilen, ireductions 


def streak(last, x): 
    if last and x >= last[-1]: 
     last.append(x) 
     return last 
    return [x] 


def longest_streak(grades): 
    xs = map(ilen, ireductions(streak, grades, None)) 
    return xs and max(xs) or 1 

grades = [1, 7, 2, 5, 6, 9, 11, 11, 1, 6, 1] 
print longest_streak(grades) 
print longest_streak([2]) 

我決定到底,不僅產生正確 版本沒有錯誤,而是利用一個庫我很喜歡funcy :)

輸出:

6 
1 
+0

雖然發生器可能會被簡化,但我懷疑「funcy」或「 'toolz''(*甚至itertools *)庫將大大有助於推廣和簡化問題:) –

+0

這必須是我見過的這個問題的最複雜的解決方案。但我認爲它是否有效^^ – Voo

+0

IHMO根本不復雜。它正在對輸入列表進行基本分區。這可以通過使用好的函數庫來簡化很多。 –

1

由於目前的解決方案包括產量和地圖以及額外的內存開銷,它可能是一個好主意,至少提簡單的解決方案:

def length_of_longest_sublist(lst): 
    max_length, cur_length = 1, 1 
    prev_val = lst[0] 
    for val in lst[1:]: 
     if val >= prev_val : 
      cur_length += 1 
     else: 
      max_length = max(max_length, cur_length) 
      cur_length = 1 
     prev_val = val 
    return max(max_length, cur_length) 

我們可以通過直接獲得前值減少代碼:

def length_of_longest_sublist2(lst): 
    max_length, cur_length = int(bool(lst)), int(bool(lst)) 
    for prev_val, val in zip(lst, lst[1:]): 
     if val >= prev_val: 
      cur_length += 1 
     else: 
      max_length = max(max_length, cur_length) 
      cur_length = 1 
    return max(max_length, cur_length) 

這是一個很好的把戲(知道它允許它容易地爲空列表返回正確的結果),但讓不熟悉該成語的人感到困惑。

0

也許不一樣有效,以前的答案,但它的短:P

diffgrades = np.diff(grades) 
maxlen = max([len(list(g)) for k,g in groupby(diffgrades, lambda x: x >= 0) if k]) + 1 
+0

如果'len(等級)<2'將不起作用,否則很酷 – Suor

1

此方法使用相當基本的Python和回報聲明可以快速修改,以便您有一個所有連續長度的列表。

def longest_streak(grades): 
    if len(grades) < 2: 
     return len(grades) 
    else: 
     start, streaks = -1, [] 
     for idx, (x, y) in enumerate(zip(grades, grades[1:])): 
      if x > y: 
       streaks.append(idx - start) 
       start = idx 
     else: 
      streaks.append(idx - start + 1) 
     return max(streaks) 
0

建立在@ M4rtini的想法使用itertools.groupby

def longest_streak(grades): 
    from itertools import groupby  
    if len(grade) > 1: 
     streak = [x <= y for x, y in zip(grades,grades[1:])] 
     return max([sum(g, 1) for k, g in groupby(streak) if k]) 
    else: 
     return len(grades) 
1

我會解決這個問題是這樣的:

from itertools import groupby 
from funcy import pairwise, ilen 

def streak(grades): 
    if len(grades) <= 1: 
     return len(grades) 
    orders = (x <= y for x, y in pairwise(grades)) 
    return max(ilen(l) for asc, l in groupby(orders) if asc) + 1 

非常明確:ordersTrue S表示升序對和False S表示降序者的迭代器。然後,我們需要找到一個最長的升序列表並添加1.

+0

我喜歡它:)非常好的想法! –