学校でチーム分けの方法を考えていたら脱線した（日記）

まず断っておきますが、これは日記です。日記ですよ。はい。すごく暇なときにどうぞ。ちゃんとプログラムに関する話題は出てきます。

# こんなことがありました

筆者は学生なのですが、今度の学校行事の関係で、クラスを10グループに分けなければいけないのです。そこで、どんなチーム分けの方法がいいかという（無駄な）話し合いをすることになりました。なんでや...😞 

みんなが、どうすれば均等に分けられるか考えている間、私は「しっているぞ　こんなときはプログラムを書いてだな...乱数を使ってウンチャラカンチャラ...ぼくはくわしいんだ」などと考えていたわけです（本当に詳しいだなんて思ってないです）。

そして、発表の時間になって、司会さんがみんなの意見を聞いて行く中で、こんな意見が出たのです。「お財布の中の合計金額を使って分けてみたらいいのではないか（一部脚色）」例えば、Aさんは892円持っていて、Bさんは9980円持っているとします。これらの数値を使って、チーム分けをしようというのです。なかなか斬新な考えですね!?

斬新ですが、合計金額の多い順で、1から10まで順番に番号を振っていって...、という方法でチーム分けをするというのは、教育上あまりいいとは思えません。バッドアイデアです。

# 名案（名案とは言っていない）を思いついた

そこで、私は、合計金額という斬新なアイデアを採用しつつ、チーム分けをする方法を考えました。「合計金額を10で割った余りをグループ番号にすればいいのではないか」と。

お財布を忘れた?人数が均等にならなそう?細けぇこたぁ気にすんな(｀・ω・´)　

ということで(?)この方法を、近くの席のクラスメイトに話してみました。すると、数秒してから、こんな答えが返ってきました。「つまり、下1桁の数字ってこと?」

......確かにそうとも言いますね。その説明の方が、多くの人にとって分かりやすいかも知れません。しかし、偉い人は言いました。「人間にとって分かりやすいことと、コンピューターにとって分かりやすいことは、同じとは限らない（超意訳）」のだと。

# プログラマーとして...

私もプログラマーの端くれです。ここは、10で割った余りスタイル と 下1桁の数字スタイル でどっちの実行速度が速いのか確かめなければなりません（落ち着け）（謎の使命感）。話し合いの結果、合計金額案はボツになったので、みんなの合計金額のデータは手元にありません...ならば、作ればいいのです！

ということで作りました。

```random.cs
using System;
public class Hello{
    public static void Main(){

        var seed = Environment.TickCount;
        
        for(int i = 0; i < 10000; i++)
        {
            //毎回シード値を変更して、
            //1以上100000未満の整数（乱数のようなもの）を生成する
            Random r = new Random(seed++);
            var num = r.Next(1,100000);

            //生成した乱数のようなものを出力して、
            //区切り文字としてスペースも出力する
            Console.Write(num + " ");
        }
        
    }
}
```

追記
random.csによって生成される数字を乱数と表記していましたが、正確には乱数のようなものであり、乱数ではありませんでした。

こんな感じでいいでしょう。実行速度の違いが分かりやすいように、クラスメイトは1万人いることにしました。過密！過密！圧倒的過密！

それでは、このプログラムによって得られた1万人分の所持合計金額のデータを入力値として、10で割った余り VS 下1桁の数字 対決をしましょう。

# たいけつだ！

ルール：入力されたデータを、Split()を使ってstring型の配列に格納するところまでは共通とする。

## 赤コーナー：10で割った余りスタイル

```main1.cs
using System;
public class Hello{
    public static void Main(){

        DateTime start, end;
        
        //string型の配列に1つ1つ格納
        string[] str = Console.ReadLine().Split(' ');
        
        //計測開始
        start = DateTime.Now;
        
        for(int i = 0; i < 10000; i++)
        {
            //配列strの中身をint型に変換してから
            //10で割った余りを出力する
            Console.Write(int.Parse(str[i]) % 10 + " ");
        }
        
        //計測終了
        end = DateTime.Now;
        
        Console.WriteLine();

        //処理にかかった時間を秒単位で出力
        Console.WriteLine((end - start).TotalSeconds);
    }
}
```

説明は、コメント文に書いた通りです。これは勝てそう！（フラグ）

## 青コーナー：下1桁の数字スタイル

```main2.cs
using System;
public class Hello{
    public static void Main(){

        DateTime start, end;
        
        //string型の配列に1つ1つ格納
        string[] str = Console.ReadLine().Split(' ');
        
        //計測開始
        start = DateTime.Now;
        
        for(int i = 0; i < 10000; i++)
        {
            //配列strのi番目の要素の、
            //配列strのi番目の要素の文字列の長さ - 1 番目の文字を出力する
            Console.Write(str[i][str[i].Length - 1] + " ");
            
        }
        
        //計測終了
        end = DateTime.Now;

        Console.WriteLine();

        //処理にかかった時間を秒単位で出力
        Console.WriteLine((end - start).TotalSeconds);
    }
}
```

`str[i][str[i].Length - 1]`のところがヤバい。

# 集計しよう

ということで実行時間を集計していきます。今回は[paiza.io](https://paiza.io/ja) にて計測しました。10回ずつ交互に計測し、平均を取りました。最大値と最小値もあります。結果はこのようになりました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/182851/202f44ff-f391-3f51-da97-ae9aa4ccaf04.png)


# 結果発表

今回の計測では、10で割った余りスタイルよりも、下1桁の数字スタイルの方が処理が速いという結果になりました。確かに、10で割った余りスタイルの「string型からint型に変換して、それを10で割った余りを出力する」よりも、下1桁の数字スタイルの「各配列の要素に直接アクセスする」方が速そうな気がしますね。

# まとめ
【悲報】10で割った余りスタイルさん
人に伝わりにくいだけでなく、実行速度の面でも敗北か／(^o^)＼ ／(^o^)＼

# 感想
今回は[paiza.io](https://paiza.io/ja) さんで計測しましたが、Visual Studioとかで計測してみようと思いました。また、pythonやRubyなどのC#以外の言語でも同じ結果になるのか気になりました。