「誰から発表する?」の沈黙、もう終わりにしよう
会議で「今日の発表順、どうする?」と聞いた瞬間に訪れる沈黙。飲み会の幹事決めでなぜか毎回同じ人が手を挙げる光景。30人のクラスを6チームに分ける作業に5分以上かかるあの時間。
こういう場面を一瞬で片づけるために作ったのが、この公平な配置係。名前を入れるだけで順番決め・チーム分け・ルーレット・くじ引きの4モードが使え、Fisher-Yatesアルゴリズムによる数学的に完全な公平性がついてくる。数字ではなく名前をそのまま扱えるから、「3番って誰?」問題が起きない。名簿保存や除外機能で、毎回の入力も最小限に抑えられる。
なぜ公平な配置係を作ったのか
開発のきっかけ
きっかけは職場の会議。毎回「誰から発表する?」で沈黙が流れて、結局いつも同じ人が最初に話す。「ランダムに決めよう」となっても、じゃんけんは時間がかかるし、あみだくじを描く紙がない。
スマホで「乱数 アプリ」と検索すると、出てくるのは数字を生成するだけのツールばかり。「1〜30の乱数」を出されても、「で、3番って誰?」となる。名前を直接扱えるランダムツールが欲しかった。
さらに、チーム分けの場面でも困った。30人のクラスを6チームに分けたいとき、既存ツールだと「1人ずつ引く」形式で、全員分やるのに5分以上かかる。一発で全チームの結果が出るものが必要だった。
こだわった設計判断
- 名前ベースの入出力: 数字ではなく名前を直接入力・表示する設計。「3番: 太郎」ではなく「太郎」がそのまま結果に出る。結果をそのまま共有できるから、変換の手間がない
- 4モードの統合: 順番・チーム分け・ルーレット・くじ引きを1つのアプリに統合した。名簿を1回入力すれば、目的に応じてモードを切り替えるだけ
- 名簿保存: よく使うメンバーリストをブラウザに保存できるようにした。毎回30人分の名前を入力するのは現実的じゃないから、保存・呼び出しは必須機能
ランダム・シャッフル・確率の基礎知識
「ランダムに決める」と一言で言っても、その裏にはきちんとした数学がある。ここではシャッフルや確率の基本を第一原理から押さえておこう。ツールを使わない人でも、知っておくと日常の「公平な決め方」が変わるはず。
ランダム(乱数)とは
乱数とは、次にどの値が出るか予測できない数列のこと。サイコロを振ったとき、次に何の目が出るか分からない――これが乱数の本質。コンピュータで使われるのは「擬似乱数」と呼ばれるもので、数学的なアルゴリズムで生成される。完全な予測不可能性はないが、日常のくじ引きや順番決めには十分すぎる品質が確保されている。
たとえ話で言えば、サイコロは「物理乱数」、コンピュータの乱数は「レシピ通りに作るけど味が毎回微妙に違う料理」のようなもの。レシピ(アルゴリズム)は決まっているが、最初の材料(シード値)が違えば、まったく異なる結果が生まれる。
シャッフル(並べ替え)の確率
n人をランダムに並べ替えるとき、あり得る並び順の総数は n!(nの階乗) 通り。3人なら 3! = 6通り、10人なら 10! = 3,628,800通り、30人なら 30! ≈ 2.65 × 10³² 通りになる。
n人の並べ替え数 = n!
3人: 3! = 3 × 2 × 1 = 6 通り
5人: 5! = 120 通り
10人: 10! = 3,628,800 通り
30人: 30! ≈ 2.65 × 10³² 通り
「公平なシャッフル」とは、これら全ての並び順が等確率で出現すること。つまり3人のシャッフルなら、6通りの並び順がそれぞれ正確に 1/6 の確率で出なければならない。簡単に聞こえるが、アルゴリズムの選び方を間違えると偏りが生じてしまう。
くじ引き・抽選の確率
n人から k人を選ぶ組み合わせの数は「n choose k」(二項係数)で求まる。20人から5人を選ぶ場合、組み合わせは15,504通り。公平な抽選では、各人の当選確率は正確に k/n = 5/20 = 25% になる。
組み合わせ数 C(n,k) = n! / (k! × (n-k)!)
20人から5人: C(20,5) = 15,504 通り
各人の当選確率: 5/20 = 25%
Fisher-Yatesシャッフルとは
Fisher-Yatesシャッフル(別名: Knuthシャッフル)は、配列をランダムに並べ替える標準的なアルゴリズム。1938年にRonald FisherとFrank Yatesが考案し、1964年にDonald Knuthが計算機向けに改良した。配列の末尾から先頭に向かって、各位置でランダムに選んだ要素と交換していく。計算量は O(n) で、全ての並び順が等確率で出現することが数学的に証明されている。この「証明済みの公平性」こそが、くじ引きや当番決めに安心して使える理由。
ランダムの公平性が結果を左右する場面
「ランダムなんて適当でいいでしょ」と思うかもしれないが、公平性が担保されていないランダムは、知らないうちに特定の人を有利・不利にしてしまう。実はこの問題、日常から法的な場面まで幅広く影響する。
偏ったシャッフルが生む不公平
JavaScriptの Array.sort(() => Math.random() - 0.5) という手法でシャッフルすると、見た目はランダムに見えるが、実は各要素の出現位置に偏りが生じることが知られている。たとえば5要素のシャッフルで10万回実験すると、先頭の要素が先頭に残る確率が理論値(20%)より高くなる。日常のくじ引きで「なんか毎回同じ人が当たる」と感じるなら、アルゴリズムの偏りが原因かもしれない。
教育現場での公平性
学校でのグループ分けや発表順の決定は、教育的な観点から公平性が求められる。学校教育法の趣旨に基づき、生徒間で不公平な扱いが生じないよう配慮する必要がある。教員の主観によるグループ分けは「えこひいき」の疑いを招きやすいが、アルゴリズムの公平性が証明されたツールを使えば、その懸念を払拭できる。
抽選・くじ引きにおける透明性
自治会の当番決め、社内イベントの景品抽選、マンションの駐車場割り当て――こうした場面では、結果に対する納得感が重要。消費者契約法では、事業者と消費者の取引における公正さが規定されているが、日常のくじ引きでも同じ原理が当てはまる。全員が「公平だった」と納得できるかどうかは、使用するツールの透明性にかかっている。
n人じゃんけんの非効率性
3人以上のじゃんけんは、決着がつくまでの回数が急激に増える。4人じゃんけんで1回で決まる確率はわずか約25%。10人なら約1.7%。しかも心理学の研究では「最初はグーを出しやすい」という傾向が報告されている。人数が多いほど、コンピュータによるランダム選出の方が圧倒的に速く、かつ公平になる。
活躍する場面
プレゼンや面接の順番決め
会議で「誰から発表する?」の沈黙を回避。全員の名前を入れて順番生成モードを押すだけ。結果をモニターに映せば透明性も確保できる。
グループワークのチーム編成
クラス30人を6チームに分けたい場合。チーム分けモードでチーム数を6に設定して実行するだけ。先生の主観が入らないから、生徒も納得しやすい。
飲み会の幹事・当番決め
ルーレットモードで1人を選出。画面を全員に見せながらやれば透明性も確保。「またお前かよ」感はあるかもしれないけど、少なくとも数学的には公平。
景品抽選会
社内イベントで20人中5人に景品を配りたい場合。くじ引きモードで当たり数を5に設定。一度に全当選者が決まるから、1人ずつ引くより圧倒的に早い。
基本の使い方
名前を入れてモードを選んでボタンを押す。たった3ステップで完了。
Step 1: 名前を入力する
テキストエリアに参加者の名前を入れる。改行区切りでもカンマ区切りでもOK。Excelやスプレッドシートからコピペする場合は、改行区切りが自動認識されるからそのまま貼り付ければいい。
Step 2: モードを選ぶ
4つのモード(順番生成・チーム分け・ルーレット・くじ引き)から目的に合ったものを選択する。チーム分けならチーム数、くじ引きなら当たり数も設定する。
Step 3: 実行して結果を確認する
実行ボタンを押すと、即座に結果が表示される。結果はコピー機能でLINEやチャットに共有できる。コピー形式は3種類: プレーン(名前だけ)、番号付き(1. 太郎)、CSV(カンマ区切り)。
具体的な使用例(検証データ)
ケース1: 学校のグループワーク編成
クラス30人を6チームに分けたい場合。
入力値:
- 名前: 30人分
- モード: チーム分け
- チーム数: 6
結果:
- チーム1〜6にそれぞれ5人ずつ均等配分
- 実行するたびに異なる組み合わせ
→ 解釈: 30÷6=5人/チーム。Fisher-Yatesシャッフルにより、どのチームに入るかは完全に均等な確率。先生の主観が入らないため、生徒間の不公平感が解消される。
ケース2: 飲み会の幹事決め
8人の中から1人を選出。
入力値:
- 名前: 8人分
- モード: ルーレット
結果:
- 8人の中から1人がランダムに選出
- 各人の選出確率: 正確に1/8(12.5%)
→ 解釈: Fisher-Yatesアルゴリズムにより、すべての要素が等確率で先頭に来る。特定の人が有利・不利になることはない。
ケース3: 景品抽選会
20人中5人に景品を配る。
入力値:
- 名前: 20人分
- モード: くじ引き
- 当たり数: 5
結果:
- 20人の中から5人が一度に選出
- 各人の当選確率: 正確に5/20(25%)
→ 解釈: 組み合わせ数 C(20,5) = 15,504 通りのいずれかが等確率で選ばれる。1人ずつ引く方式と異なり、一括抽選なので時間が大幅に短縮される。
ケース4: 会議の発言順
10人の発言順を決定。
入力値:
- 名前: 10人分
- モード: 順番生成
結果:
- 10人の完全ランダムな順番リスト
- すべての並び順が1/3,628,800の等確率
→ 解釈: 10! = 3,628,800通りの並び順がすべて等確率で出現。序盤・終盤の有利不利を気にする必要がなく、「誰から話す?」の沈黙を回避できる。
ケース5: 社内研修のペア組み
12人の新入社員をペアワーク用に2人ずつ組み分けたい場合。
入力値:
- 名前: 12人分
- モード: チーム分け
- チーム数: 6
結果:
- 6ペア(各2人)がランダムに生成
- 実行ごとに異なるペアの組み合わせ
→ 解釈: 12人を6チーム×2人に分けるパターンは膨大な数になるが、Fisher-Yatesシャッフルにより全パターンが等確率で出現する。毎回同じ人同士が組むことなく、研修ごとに多様な交流が生まれる。上司の意図が入らないから「なぜこのペアなのか」という不満も出にくい。
ケース6: マンション自治会の掃除当番ローテーション
15世帯の月別掃除当番の順番を決定。
入力値:
- 名前: 15世帯分(101号室〜115号室)
- モード: 順番生成
結果:
- 15世帯のランダムな順番リスト
- 1月目〜15月目の当番が一括で確定
→ 解釈: 部屋番号順に当番を回すと、毎年同じ月に同じ世帯が担当することになり不満が出やすい。ランダム生成なら「夏の草刈りがいつも自分」という偏りを防げる。結果を掲示板に貼り出せば透明性も確保でき、住民間のトラブル予防にもつながる。
シャッフル手法の比較と採用アルゴリズム
候補手法の比較 — なぜFisher-Yatesを選んだか
配列をランダムに並べ替える方法はいくつかある。開発時に検討した3つの手法を比較する。
| 手法 | 公平性 | 計算量 | 実装の複雑さ | ブラウザ適性 |
|---|---|---|---|---|
| Fisher-Yates(採用) | 証明済み(完全均等) | O(n) | 低い | 最適 |
| sort + Math.random | 偏りあり | O(n log n) | 低い | 非推奨 |
| ランダムサンプリング(reservoir) | 証明済み | O(n) | 中程度 | 用途が限定的 |
sort + Math.random は array.sort(() => Math.random() - 0.5) という一行で書ける手軽さが魅力だが、比較関数が推移律を満たさないため、ソートアルゴリズムによっては特定の要素が特定の位置に偏る。実際にChrome(TimSort)とFirefox(MergeSort)で異なる偏りパターンが報告されている。くじ引きや当番決めのような公平性が必要な用途には使えない。
Reservoir sampling(水貯め法)は、全体の数が不明なストリームから k個を等確率で選ぶアルゴリズム。公平性は証明されているが、「全員の順番を決める」「チームに分ける」といった用途には不向き。大量データのサンプリング向けの手法。
Fisher-Yates を採用した理由は明確で、(1) 全ての並び順が等確率であることが数学的に証明されている、(2) 計算量が O(n) で高速、(3) 実装が簡潔でバグが入りにくい、の3点。30人のシャッフルでも一瞬で完了し、スマホでもストレスなく動作する。
実装の計算フロー
Fisher-Yatesの実装は以下のフローに従う:
入力: 配列 arr[0..n-1]
for i = n-1 downto 1:
j = random(0, i) // 0以上i以下の一様乱数
swap(arr[i], arr[j])
出力: シャッフルされた配列
各ステップで「まだ確定していない要素」の中からランダムに1つ選んで末尾の未確定位置に配置する。これにより、全ての順列が等確率で出現することが帰納法で証明できる。
具体的な計算例
3人「太郎、花子、次郎」のシャッフルをステップごとに追跡する:
初期配列: [太郎, 花子, 次郎] (n=3)
Step 1: i=2(末尾)
j = random(0, 2) → 仮に j=1
swap(arr[2], arr[1])
配列: [太郎, 次郎, 花子] ← 花子と次郎を交換
Step 2: i=1
j = random(0, 1) → 仮に j=0
swap(arr[1], arr[0])
配列: [次郎, 太郎, 花子] ← 太郎と次郎を交換
完了: [次郎, 太郎, 花子]
なぜこれで公平になるか:
- Step 1で3人のうち1人が末尾に入る → 各人が末尾に来る確率 = 1/3
- Step 2で残り2人のうち1人が2番目に入る → 各人が2番目に来る確率 = 1/3 × 1/2 + ... = 1/3
- 最後の1人が先頭に入る → 先頭に来る確率も 1/3
つまりどの人がどの位置に来るかは、すべて正確に 1/n の確率。3人なら 6通り × 1/6、10人なら 3,628,800通り × 1/3,628,800 で、完全に均等。
チーム分け・くじ引きへの応用
チーム分けは「シャッフルした配列を順番にチームに割り当てる」だけで実現できる。6チームなら、シャッフル後の1番目をチーム1、2番目をチーム2、...、7番目をチーム1、と割り振る。シャッフルが公平なら、チーム分けも自動的に公平になる。
くじ引き(n人からk人を選出)は、シャッフル後の先頭k人を取るだけ。Fisher-Yatesの性質により、各人が先頭k人に入る確率は正確に k/n。
他のランダムツール・くじ引きアプリとの違い
名前を直接扱える
多くの乱数ツールは「1〜30の数字を生成」する仕組み。このツールは名前を直接入力・表示するから、「3番って誰だっけ?」問題が起きない。結果をそのまま共有できる。
名簿保存で毎回の入力を省略
よく使うメンバーリストは名簿として保存できる。「クラスA」「営業チーム」のように名前をつけておけば、次回からワンタップで呼び出せる。除外機能で欠席者だけチェックを外せば、名簿を編集せずに運用できる。
4モードを1つのアプリに統合
順番決め・チーム分け・ルーレット・くじ引きがすべて1つのアプリで完結。名簿を1回入力すれば、モードを切り替えるだけで目的に応じた結果が出る。別のアプリを探してまた名前を入力し直す手間がない。
サイコロから乱数生成器まで — ランダムの雑学
人類最古のランダム装置はサイコロ
紀元前3000年頃のメソポタミアで、すでにサイコロが使われていた。古代ローマでは政治的な決定にもくじ引き(Sortitio)が用いられ、古代アテネでは裁判官の選出にランダム抽選が制度化されていた。「公平な決め方」への需要は数千年前から変わらない。参考: サイコロ — Wikipedia
RAND Corporation の「100万個の乱数表」
1955年、RAND Corporationが「A Million Random Digits with 100,000 Normal Deviates」という書籍を出版した。物理的な電子ノイズから生成した100万個の乱数を表にまとめたもので、コンピュータが普及する前の科学者が実験計画やシミュレーションで使っていた。今ではコンピュータが一瞬で生成するものを、当時は本1冊にまとめて流通させていたと思うと感慨深い。参考: RAND Corporation
量子乱数 — 真の予測不可能性
コンピュータの擬似乱数はアルゴリズムで生成されるため、原理的にはシード値が分かれば再現可能。一方、量子力学的な現象(光子の偏光など)を利用した「量子乱数」は、物理法則上、予測が不可能。暗号や国家安全保障の分野で使われているが、日常のくじ引きには擬似乱数で十分。
使い方のコツ・Tips
Excelからのコピペを活用
名簿管理をExcelやGoogleスプレッドシートでやっている場合、名前の列を選択してコピー → テキストエリアに貼り付けるだけ。改行区切りが自動認識されるから、加工の手間がない。
除外機能で欠席者を管理
保存した名簿の横にチェックボックスがある。今日の欠席者をチェックで除外すれば、名簿を毎回編集しなくてOK。「30人中5人欠席」のような運用がスムーズにできる。
コピー形式を使い分ける
LINEで共有するなら「番号付き」、スプレッドシートに貼るなら「CSV」、シンプルに使うなら「プレーン」。場面に応じてコピー形式を切り替えると便利。
履歴を活用する
実行結果は自動的に履歴に保存される(最大10件)。うっかり再実行してしまっても、直前の結果を確認できる。「さっきの結果なんだっけ?」を防げる。
よくある質問
Q: 同じ名前が複数ある場合はどうなる?
それぞれ別の人として扱われる。区別したい場合は「太郎A」「太郎B」のように分けて入力すればOK。内部的には配列のインデックスで管理しているから、同姓同名でも正しく処理される。
Q: 本当にランダム?偏りはない?
Fisher-Yatesアルゴリズムを使用しており、すべての並び順が数学的に等確率で出現することが証明されている。乱数源はブラウザの Math.random() で、暗号学的な強度はないが、日常のくじ引き・順番決めには十分な品質。特定の人が有利・不利になることはない。
Q: チーム分けで人数が割り切れないときはどうなる?
余りの人数は先頭のチームから1人ずつ追加される。例えば10人を3チームに分ける場合、4人・3人・3人になる。どのチームが4人になるかもランダムに決まる。
Q: 履歴はいつまで残る?
実行履歴はブラウザのセッション中のみ保持される(最大10件)。ブラウザのタブを閉じるとリセットされる。一方、名簿データはローカルストレージに保存されるため、同じブラウザなら次回以降も呼び出せる。
まとめ
名前を入れてボタンを押すだけ。順番決め、チーム分け、ルーレット、くじ引きの4モードで、日常のランダム選出をカバーできる。名簿保存と除外機能で毎回の入力も省略可能。Fisher-Yatesアルゴリズムによる証明済みの公平性つき。
テニスの対戦組み合わせを決めたいならテニス組み合わせ職人を試してみて。飲み会の割り勘なら不平等割り勘マスターで、負担割合が違う人がいるときの金額もサクッと出せる。
不具合や要望があれば、X (@MahiroMemo)から気軽に教えてほしい。