summer_tree_home

Check iOでPython3をマスターするぜっ

Median (Check iO > Home)

どんな問題?

2問目は、メディアン(中央値)を求めるというもの。

例を見てみよう。
checkio([1, 2, 3, 4, 5]) == 3
checkio([3, 1, 2, 5, 3]) == 3
checkio([1, 300, 2, 200, 1]) == 2
checkio([3, 6, 20, 99, 10, 15]) == 12.5

全ての要素の中央値を求めればいい。平均値じゃないぞ。

どうやって解くか?

まず、リストを小さい順に並べてから、中央の要素を取り出せばよい。
リストを小さい順に並べるのは、単純にsort()すれば良い。そして、要素数が奇数ならリスト真ん中の要素を取得する。要素数が偶数ならリスト中央の2要素の平均を取る。要素が5個(data[0]~data[4])ならdata[2]、要素が6個(data[0]~data[5])ならdata[2]とdata[3]の平均値となる。
これを素直に書くと、このようになった。

def checkio(data):
    m = len(data) // 2  # 中央のindex
    data.sort()
    if len(data) % 2 == 0:  # 偶数
        return (data[m - 1] + data[m]) / 2
    else:  # 奇数
        return data[m]

いちおう自動テストはクリアしたが、もう少し省略して書けそうだ。

素数が奇数の場合には、data[m]とdata[m]の平均値だと考えれば、ifによる分岐を減らすことができる。

def checkio(data):
    m = len(data) // 2
    data.sort()
    return (data[m - 1 + len(data) % 2] + data[m]) / 2

ちょっと読み辛いか。

また、要素数が奇数でも偶数でも、前からm+1番目の要素(data[m])と、後ろからm+1番目の要素(data[-m-1])の平均値と考えることもできる。

def checkio(data):
    m = len(data) // 2
    data.sort()
    return (data[m] + data[-m-1]) / 2

うん、シンプルにまとまった。でも、ぱっと見たときに、何をしているのかわかりにくいかな。

こんな風に、いくつもの解法を考えるのも楽しいところ。さて、では他の人の解答も見てみますか。

他の人の答え

まあ、だいたいは同じような感じだった。おっと、len(data) == 0 の場合を考慮している人がいた。確かに上の例だと引数が[]だと例外発生してしまう。
問題文を読み返すと、引数は a list of intergers となっているので、[
]は考慮しなくてもいいかもしれないが、まあ、実践でのプログラムであれば考慮すべき点だろう。

今回は簡単だったかな。では次の問題へ。