読者です 読者をやめる 読者になる 読者になる

矮小

井の中の蛙

AOJ 1147 ICPC Score Totalizer Software

というものを見ていたら,ICPC・JAG非公式難易度表というのを見つけた.弐寺のDP非公式難易度表的なものらしい.せっかくなので一番上にあるやつを解いてみた.一応読んだことある問題で,面倒そうだしすぐ書けてしまいそうだからと言って飛ばしてしまったんだけど,書いてみるとかなりD言語っぽく綺麗に解けた.

問題

n人の審査員が付けた点数が入力されるので,最高点と最低点を除いた平均点を出力する

やりかた

そのまま.

import std.stdio;
import std.algorithm;
import std.conv;
import std.string;
import std.range;
import std.math;

void main() {
    while (true) {
        int n = readln.chomp.to!int;
        if (n == 0) break;

        int[] s;
        foreach (i; 0..n) {
            s ~= readln.chomp.to!int;
        }

        writeln((s.reduce!("a + b") - s.minPos[0] - s.minPos!("a > b")[0])
                / (n - 2));
    }
}

最初に全部足したあと最高点と最低点を引いて,審査員の人数から2を引いた数で割ることで適切な値が出ます.

foreach (i; 0..n)for (int i = 0; i < n; i++)と等価(のはず)です.ドットを3つにすると右側の値を含むrangeになります.この書き方最近どっかで見て覚えたんだけどどこで見たんだっけ…….

std.algorithm.reduceはそのままの関数です.確かaがアキュムレータ,bが各要素になって,テンプレート引数の評価した値がaにどんどん入っていく仕様のはず.ちなみに初期値を設定したい場合は初期値が第1引数になるので,UFCSするなら100.reduce!("a - b")([1, 2, 3])みたいにしないといけないのがインスタンスメソッドっぽくならなくてちょっとダサいです.テンプレート引数に文字列を指定するときはaとかbが実装で予約されている*1のでこれを使わないとダメですが,ラムダ式を使うときは(x, y) => x + yとか出来ます.Rubyだとinject(:+)で等価になるはず.