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 となっているので、[]は考慮しなくてもいいかもしれないが、まあ、実践でのプログラムであれば考慮すべき点だろう。
今回は簡単だったかな。では次の問題へ。