【C#】パ研合宿2019 第3日「パ研杯2019」 C - カラオケ をC#で解いてみた【AtCoder】

デリゲートとFunc

Funcという素晴らしい機能がある。

まずC#には、デリゲートという変数にメソッドを格納するというよくわからない機能があるのだが、それを使いやすくしてくれるのがFuncというクラスである。

このクラスの説明はネットの海にいっぱい詳しいものが転がっているので割愛するが、このFuncもといデリゲートの真価は「メソッドの実行を任意に操作できる」という点にあるのではないだろうか。

とある競技プログラミングの問題に投稿されていた解答をもとに自分でコードアナライズをしてみた結果を以下に記す。
Console.ReadLine()を適切なタイミングで実行し、複雑な標準入力の値を見事にコントロールしているのが分かる。

このソースを書いた人は天才だ…!

問題文はこちら↓
atcoder.jp

サンプルプログラム

       static void solve()
        {
            //入力パラメーターなし(引数なし)のデリゲート
            //標準入力を読みとり、Splitしてint型の配列に代入する
            Func<int[]> read = () => Console.ReadLine().Split()
                Select(int.Parse).ToArray();

            //デリゲートを実行し、結果を変数に代入
            //この読み取りでは1ライン目(NとMの値)を読み取る
            var h = read();

            //N(生徒数)とM(選べる曲数)を変数に代入
            int n = h[0], m = h[1];

            //2行目以降を読み取り
            //長さがNの配列を用意し、すべてのコレクションに対し、
          //デリゲートのメソッドを実行する
            var a = new int[n].Select(_ => read()).ToArray();

            //Long型で0を代入する
            var M = 0L;

            //曲数だけループ
            for(int j = 0; j < m; j++)
            {
                //現在の曲+1(次の曲)から曲数だけループ
                for (int k = j + 1; k < m; k++)
                {
                    //0からn(生徒数)までの配列の範囲で、曲の得点を
                    //それぞれ比較し、一番大きい得点を算出
                    //各生徒の最大得点が出揃ったところでSumで合計する。
            //出てきた値はMに代入
                    //i = Rangeのループ数 j = 曲1 k = 曲2
                    M = Math.Max(M, Enumerable.Range(0, n)
                .Sum(i => (long)Math.Max(a[i][j], a[i][k])));
                }
            }
        }