acokikoy's notes

{"勉強中":"Python","注目":"Shopify","LOVE♡":["ABARTH595","TA-GG9","Ukulele","Movable Type","ガーナ ミルクチョコレート"]} なWebディレクター

毎朝Codewars@2019.06.25(火): Sums of Parts

毎朝ちびちびCodewars。

[6 kyu] Sums of Parts www.codewars.com

今日のお題:

"""
リストの各要素について、自分と自分より後ろの要素の和をリストにして返す

例:  ls = [0, 1, 3, 6, 10]

自分より後ろの要素は、前から順に
[0, 1, 3, 6, 10] ->  和は 20
    [1, 3, 6, 10] ->  和は 20
        [3, 6, 10] ->  和は 19
            [6, 10] ->  和は 16
                [10] ->  和は 10
                    [] ->  和は  0

従って [20, 20, 19, 16, 10, 0] を返す

def Sums of Parts(ls):
Args:  
    ls (list):  整数のリスト
Returns:  
     (int):  和のリスト
"""

コード

mine

def parts_sums(ls):
    s, result = 0, [0]
    for x in ls[::-1]:
        s += x
        result.append(s)
    return result[::-1]
  • リストをひっくり返して後ろから順に足していく方式。
  • 最初に全要素の和を求めて、そこから一要素ずつ引く人が多かったけど、たぶん後ろから足す方が計算量が少ないから速い。

文法、関数・メソッドnote

itertools.accumulate(p [,func])

itertools --- 効率的なループ実行のためのイテレータ生成関数 — Python 3.7.4rc1 ドキュメント

  • p0, p0+p1, p0+p1+p2, ...を返す。 例: accumulate([1,2,3,4,5]) --> 1 3 6 10 15

むむ、そのまま使えるモジュールがあるじゃないか ^^;

以下、Darshan97 (他ユーザ)のコード。簡潔で最速。 https://www.codewars.com/kata/reviews/5cff429c2ad4650001bf1590/groups/5cff4dd10310c200010520cc

from itertools import accumulate

def parts_sums(ls):
    return [*accumulate(ls[::-1])][::-1]+[0]
  • func(2つの引数を取る関数)を与えるとさまざまな累積結果が求められる
accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
accumulate([3, 4, 6, 2, 1, 9, 0, 7, 5, 8], max))   --> 3 4 6 6 6 9 9 9 9 9