どうやって分けるの?
入力した名簿をフィッシャー–イェーツ法でシャッフルし、並んだ順にチーム1、チーム2、……、チームkへ1人ずつ トランプを配るように割り当てます。最後にチームの順番そのものをもう一度シャッフルします。端数の人が いつも番号の小さいチームにだけ加わると「1チーム目がいつも1人多い」という偏りが生まれるため、どのチームが 1人多くなるかも無作為にするためです。乱数にはブラウザの crypto.getRandomValues を使い、 剰余による偏りが出ないよう棄却サンプリングで整数を取り出しています(この仕組みが使えない古いブラウザではMath.random() に切り替わります)。遊びや授業の班分けには十分ですが、Math.random()はセキュリティ用途の乱数ではないので、パスワードなど守るべき値の生成にはパスワード生成のような専用ツールを使ってください。
人数が割り切れないときのルール
n 人を k チームに分けるとき、q を n÷k の商、r を余りとすると、r チームが q+1 人、残りの k−r チームが q 人になります。これより均等な分け方はありません。どのチームが1人多くなるかは無作為です。「1チームの人数」 で分ける場合はチーム数を n÷人数の切り上げで求め、同じ規則で分けます。たとえば11人を「1チーム4人」にすると 3チームで、人数は4・4・3人です。最後のチームだけが3人と決まっているのではなく、どのチームが3人になるかも ランダムです。
| 人数 n | チーム数 k | 人数の内訳 | 特定の2人が同じチームになる確率 | (参考)1/k |
|---|---|---|---|---|
| 10人 | 2チーム | 5人 × 2チーム | 44.44% | 50.00% |
| 10人 | 3チーム | 4人 × 1チーム + 3人 × 2チーム | 26.67% | 33.33% |
| 7人 | 3チーム | 3人 × 1チーム + 2人 × 2チーム | 23.81% | 33.33% |
| 17人 | 3チーム | 6人 × 2チーム + 5人 × 1チーム | 29.41% | 33.33% |
| 23人 | 4チーム | 6人 × 3チーム + 5人 × 1チーム | 21.74% | 25.00% |
| 25人 | 5チーム | 5人 × 5チーム | 16.67% | 20.00% |
| 30人 | 4チーム | 8人 × 2チーム + 7人 × 2チーム | 22.53% | 25.00% |
| 100人 | 7チーム | 15人 × 2チーム + 14人 × 5チーム | 13.43% | 14.29% |
確率は、各チームの人数 s について s(s−1) を足し合わせ、n(n−1) で割って求めています。チームの人数が先に 決まっているため、各人が独立にチームを選ぶ場合の 1/k よりわずかに低くなります。先に1人が席に座ると、 そのチームの空き席が1つ減るからです。
検算した例
例1: 23人を4チームに。 q=5、r=3 なので、6人のチームが3つと5人のチームが1つです(6+6+6+5=23)。 特定の2人が同じチームになる確率は (3×6×5 + 1×5×4) ÷ (23×22) = 110/506 = 21.74% です。
例2: 10人を3チームに。 q=3、r=1 なので、4人のチームが1つと3人のチームが2つです(4+3+3=10)。同じ チームになる確率は (1×4×3 + 2×3×2) ÷ (10×9) = 24/90 = 26.67% です。分け方の総数は多項係数で 数えられ、6人を2人ずつ3チーム(チームを区別する場合)に分けるなら 6!/(2!×2!×2!) = 90通り、 10人・3チームなら4,200通りです。公平なチーム分けとは、これらすべての分け方が同じ確率で現れることを いいます。
グループ均等の機能
完全な無作為だと、偶然に経験者や特定の学年が1つのチームに集まることがあります。「グループ均等」にチェックを 入れ、各行を 山田太郎, A のように「名前, グループ」で入力すると、グループごとに別々にシャッフルした うえで、同じ配り順に続けて割り当てます。そのため各グループのチーム別人数差は最大1人、全体のチーム人数差も 最大1人です。A・B・Cが4人ずつ計12人を4チームに分けると、各チームにA・B・Cが1人ずつ入る3人編成になります。 カンマのない行はグループなしとして扱います。均等に散らすことは保証できますが、A・B・Cの評価が妥当かどうかは 評価した人の責任です。
「各自がランダムにチームを選ぶ」方式を使わない理由
実装が簡単な代替案は、1人ずつ 1〜k の乱数を引いて所属を決める方法です。しかしこれでは人数が揃いません。 10人を2チームに独立に振り分けると、5対5になる確率は C(10,5)/210 = 252/1024、約24.6%にすぎず、残りは 6対4や7対3など偏った結果になります。そこで先にチームの人数(q または q+1)を固定し、シャッフルした人を その席に順に埋めていく方式を採っています。また、sort(() => Math.random() - 0.5) という1行の シャッフルも使いません。比較関数が一貫しないため、実行環境の並べ替えアルゴリズムに依存して偏ります。Node.js で3要素を60万回並べ替えた試行では、ある並びが約37%、別の並びが約6%となり(公平なら全6通りが各16.7%)、 結果は環境ごとに異なりますが偏り自体は確かに存在します。
よくある間違い
- チーム数に参加者数より大きい数を入れる: 空のチームができるので受け付けません。人数以下にしてください。
- 「チーム数」と「1チームの人数」の取り違え: 20人を「1チーム4人」にすれば5チーム、「4チーム」にすれば5人ずつ4チームです。
- グループ均等でグループ名の表記ゆれ: 「A」と「A 」は空白除去後に同じですが、「A」と「Aクラス」は別グループです。
- 名前にカンマが含まれる場合(例: "Kim, Jun"): グループ均等をオンにするとカンマ以降がグループとして読まれるため、表記を変えてください。
限界と使うときの注意
- 無作為は戦力の均等ではありません。 手続きが公平でも、結果のチーム力が揃うとは限りません。実力差が大きいときはグループ均等を使ってください。
- 気に入らないからとやり直すと無作為ではなくなります。 結果を見てから引き直すと、その選択が結果を偏らせます。回数を決めておき、確定した結果は「結果をコピー」で記録しましょう。
- 「この2人は別」「この2人は同じ」といった条件指定は未対応です。 手で入れ替える場合は、無作為ではなくなることを前提にルールを共有してください。
- 同姓同名は別人として扱います。 入力欄の下に重複の通知が出るので「田中A/田中B」のように区別してください。
プライバシーと関連ツール
入力した名簿はブラウザ内だけで処理され、サーバーへの送信も保存もされません。乱数の種(シード)は指定できず、 同じ名簿でも押すたびに結果が変わり、再現はできません。記録が必要なら結果をコピーしてください。1人だけ選びたい 場合は乱数生成、くじ引き風に楽しむならあみだくじも向いています。
よくある質問
同じ名簿でもう一度分けると結果は変わりますか?
はい。「チーム分けする」を押すたびに最初からシャッフルするため、同じ名簿でも結果は変わります。好みの結果が出るまで繰り返すと公平さが失われるので、1回で確定することをおすすめします。
空白行や重複した名前はどう処理されますか?
空白行は無視します。重複した名前は別々の人として扱い、入力欄の下に重複の件数を表示します。
人数が割り切れないときはどうなりますか?
チーム間の人数差が最大1人になるように分けます。23人・4チームなら6・6・6・5人で、どのチームが5人になるかも無作為です。
実力が近くなるようにチームを分けられますか?
「グループ均等」にチェックを入れ、各行に「名前, 上/中/下」のような評価を書くと、評価が各チームに均等に散ります。評価自体はご自身で決めてください。
チーム数はいくつまで指定できますか?
2以上、参加者数以下で、最大100チームまでです。「1チームの人数」で分ける場合はチーム数が自動計算され、2チーム未満になるときは案内が出ます。
結果を他の場所に貼り付けられますか?
「結果をコピー」を押すと、チームごとに整理したテキストがクリップボードに入り、チャットや文書にそのまま貼り付けられます。