1

月の順序付けられていないリストで最大のセットを見つけることに興味があります。これは、連続した別個の月の順序付けられたリストとして返すことができます。

例えば:

consecutive_months(["December", "January", "February", "April"])

出力します:

"December", "January", "February"

と:

consecutive_months(["February", "December", "January"])

出力します:

"December", "January", "February"

以下は機能しますが、よりエレガントな方法のアイデアがあるかどうか知りたいです:

MONTHS = ["January", "February", "March", 
          "April", "May", "June",
          "July", "August", "September", 
          "October", "November", "December"] 

def consecutive_months(lst_of_months):
    # create two years of months to handle going from Dec to Jan        
    results = []
    for m in set(lst_of_months):
        results.append((m,MONTHS.index(m)))
        results.append((m,MONTHS.index(m)+12))            
    results = sorted(results, key=lambda x: x[1])
    
    # find the longest series of consecutive months
    this_series = []    
    longest_series = []
    for this_month in results:
        if len(this_series) > 0:
            last_month = this_series[-1]
            if last_month[1] + 1 == this_month[1]:
                this_series.append(this_month)
            else:
                this_series = [this_month]
        else:
            this_series = [this_month]           
        if len(this_series) > len(longest_series):
            longest_series = [m for (m,i) in this_series]

    return longest_series

これは、サンプル入力と予想される出力を含むペーストビンです。

4

3 に答える 3

2

あなたのコードには 1 つの問題があります。入力に 12 か月すべてが表示されると、出力にはすべての月が 2 回表示されます。これは簡単に修正できます。

return longest_series[:12]

入力が12ビットの一種の「ビットマップ」に変換されるソリューションを探します。1は対応する月が入力にあることを示し、0はそうでないことを示します。

12 文字の文字列として表される場合、正規表現を使用して「1」のシーケンスを簡単に識別できます。

月のリストの前処理も行うので、リストとその辞書バージョンの両方を取得し、リストを 2 倍にして、12 境界を越えてスライスできるようにします。

提案されたコードは次のとおりです。

import re

months = ["January", "February", "March", 
          "April", "May", "June",
          "July", "August", "September", 
          "October", "November", "December"]

# Also create a dictionary to get a month's index
month_nums = { month: num for num, month in enumerate(months) }
# ... and double the months list, to ease slicing across the 12-boundary
months += months

def consecutive_months(given_months):
    # Deal with boundary case
    if not given_months:
        return []

    # Convert input to 12 bits in string format
    lst = ["0"] * 12
    for m in given_months:
        lst[month_nums[m]] = "1"
    bits = "".join(lst)
    
    # Identify the longest chunk of consecutive "1" in that doubled string
    _, start, end = max((j-i, i, j) 
        for i, j in (match.span(0)
            for match in re.finditer("1+", bits + bits)
        )
    )
 
    # Using the found span, extract the corresponding month names
    return months[start:end][:12]
于 2021-05-22T08:15:05.283 に答える