質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

5回答

2872閲覧

Excel VBA で テスト受験者のグループ分け

access

総合スコア9

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

1クリップ

投稿2020/09/22 02:16

編集2020/09/22 04:01

Excel VBA で テスト受験者のグループ分けを行いたいです。

約10~20人程度のテスト受験者に対して、3回のグループ分けを行いたいです。
例えば16人をグループ分けする場合、
1回目 8人2グループ
2回目 4人4グループ
3回目 3人5グループ(1人余るので1グループのみ4人)
のような感じです。
難しいところは、「1回目で被った受験者とは2回目、3回目はできるだけ当たらないようにしたい」
ことです。

[やったこと] 上記の16人をグループ分けする場合

Excelファイルに、以下のようなデータを用意しておきます。

インデックス番号  氏名
1          テスト1
2          テスト2
3          テスト3
・           ・
・           ・
・           ・
16         テスト16

VBAで、option base 1 を宣言しておき、
①配列Aにインデックス番号を代入します。インデックス番号の最大値は、グループ分けしたい受験者数です。(A[1] = 1 , A[2] = 2 ・・・・A[16] = 16 みたいな感じ)
②配列Aの中身をシャッフルします。
(A[1] = 6 , A[2] = 2 ・・・・A[16] = 11 みたいな感じ)
③ A[1]からA[8] をグループA 、 A[9]からA[16] をグループBとして1回目のグループ分けが完了。

ここまでコード化できたのですが、2回目以降のグループ分けで、「1回目で被った受験者とは2回目、3回目はできるだけ当たらないようにしたい」というアルゴリズムが考え付きません。
どのような考え方で実現できそうでしょうか。
よろしくお願い致します。

【背景】
テスト受験者のグループ分けを毎回手作業でやっておりました。
方法などはなく、「ただ何となくこれでメンバーが被らず分散されているのではないか」という程度の精度です。(最大人数でも20人なので、目でみて確認しておりました)
しかし、やはりミスや精度に不安がある、加えて何よりも時間がかかるという理由があり、Excel VBAで作れないかとなりました。

【要件について追記】
質問の仕方が慣れておらず申し訳ありません。
要件について以下を追記させて頂きます。

・10人~20人程度で受験者の人数は変化します。(但し、1回目~3回目のグループ分けの間に受験者が変化することはありません。)

・グループ分けの回数は必ず2回以上3回未満です。

・1グループの人数は変化することもあります。
●受験者12人 1回目3人4グループ 2回目4人3グループ
でグループ分けすることもあれば、
●受験者18人 1回目2人9グループ 2回目2人9グループ 3回目3人6グループ
で分けることもあります。

・2回目のグループ分けでは、1回目のメンバーとできるだけ被らないように。
3回目のグループ分けでは、1回目、2回目のメンバーとできるだけ被らないようにしたい。

・「できるだけ被らない」というのは、「被りがどうしようもない」場合は被ることを許可する
というのが理想ですが・・・まさにこの部分のアルゴリズムが考え付きもしません。

・Excel VBA で実現したく思っております。素人目ですが数式では難しいのではと考えております。
(Excel VBA は Excel VBA エキスパートの資格をもっている程度の知識ですが、実務で簡単なマクロなどは作成しております。VBA以外のプログラミング知識はありません。)

要件の記載が足りず申し訳ございませんでした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kitasue

2020/09/22 02:45

「1回目で被った受験者とは2回目、3回目はできるだけ当たらないようにしたい」 とのことですが、加えて、 「2回目で被った受験者とは3回目はできるだけ当たらないようにしたい」 という要件はありますか?
kuma_kuma_

2020/09/22 03:04

この答え私の場合だとVBAにしたほうが早いんだけどそれでいい?
meg_

2020/09/22 03:05

どの受験者数であっても、 1回目 2グループ 2回目 4グループ 3回目 5グループ に分けるのですか?
access

2020/09/22 03:46

皆様、こんなに回答いただけるとは思ってもみませんでした。 本当に有難うございます。 ご指摘の通り、要件の記載が足りなさすぎましたので 追記をさせて頂きました。 お手数をおかけして申し訳ございません。
kuma_kuma_

2020/09/22 03:51

1グループ1人にならないように 2分割づつしていけばいいんだよね? (前あった人とは被らないように) あとでVBAで書いておくけどキーワードは 「値が被らないランダムな抽出」と「対戦表」(下半分を略さない)だよ
access

2020/09/22 03:54

kuma_kuma_様 >>1グループ1人にならないように 2分割づつしていけばいいんだよね? この部分について用件が足りなかったので再び追記させて頂きます。 申し訳ございません。
access

2020/09/22 04:04

要件に以下を追記しました。 ・1グループの人数は変化することもあります。 ●受験者12人 1回目3人4グループ 2回目4人3グループ でグループ分けすることもあれば、 ●受験者18人 1回目2人9グループ 2回目2人9グループ 3回目3人6グループ で分けることもあります。 後だしばかりで申し訳ございません。 もっとしっかり質問するべきでした。
guest

回答5

0

文字数オーバの為テスト処理はこちらに書いておきます

  • テストパターン1

VBA

1Public Function test1() 2 3 Dim strTestTaker() As String 4 Dim objGrpups As Object 5 Dim varKeys As Variant 6 Dim varKey As Variant 7 Dim intIndex As Integer 8 9 ReDim strTestTaker(0 To 19) 10 strTestTaker(0) = "Aさん" 11 strTestTaker(1) = "Bさん" 12 strTestTaker(2) = "Cさん" 13 strTestTaker(3) = "Dさん" 14 strTestTaker(4) = "Eさん" 15 strTestTaker(5) = "Fさん" 16 strTestTaker(6) = "Gさん" 17 strTestTaker(7) = "Hさん" 18 strTestTaker(8) = "Iさん" 19 strTestTaker(9) = "Jさん" 20 strTestTaker(10) = "Kさん" 21 strTestTaker(11) = "Lさん" 22 strTestTaker(12) = "Mさん" 23 strTestTaker(13) = "Nさん" 24 strTestTaker(14) = "Oさん" 25 strTestTaker(15) = "Pさん" 26 strTestTaker(16) = "Qさん" 27 strTestTaker(17) = "Rさん" 28 strTestTaker(18) = "Sさん" 29 strTestTaker(19) = "Tさん" 30 31 '----- テスト受験者グループ分け初期化 32 Call initTestTakerGaoups(strTestTaker()) 33 34 '----- テスト受験者グループ分け3分割 35 Call getTestTakerGaoups(objGrpups, 3) 36 Debug.Print "グループ分け3分割" 37 For Each varKey In objGrpups.keys 38 Debug.Print "" & varKey & "" 39 For intIndex = 0 To UBound(objGrpups.Item(varKey)) 40 Debug.Print "[" & objGrpups.Item(varKey)(intIndex) & "]"; 41 Next intIndex 42 Debug.Print 43 Next varKey 44 Debug.Print 45 46 '----- テスト受験者グループ分け3分割後5分割 47 Call getTestTakerGaoups(objGrpups, 5) 48 Debug.Print "グループ分け5分割" 49 For Each varKey In objGrpups.keys 50 Debug.Print "" & varKey & "" 51 For intIndex = 0 To UBound(objGrpups.Item(varKey)) 52 Debug.Print "[" & objGrpups.Item(varKey)(intIndex) & "]"; 53 Next intIndex 54 Debug.Print 55 Next varKey 56 Debug.Print 57 58 '----- テスト受験者グループ分け3分割,5分割後8分割 59 Call getTestTakerGaoups(objGrpups, 8) 60 Debug.Print "グループ分け8分割" 61 For Each varKey In objGrpups.keys 62 Debug.Print "" & varKey & "" 63 For intIndex = 0 To UBound(objGrpups.Item(varKey)) 64 Debug.Print "[" & objGrpups.Item(varKey)(intIndex) & "]"; 65 Next intIndex 66 Debug.Print 67 Next varKey 68 Debug.Print 69 70End Function
  • テストパターン2

VBA

1Public Function test2() 2 3 Dim strTestTaker() As String 4 Dim objGrpups As Object 5 Dim varKeys As Variant 6 Dim varKey As Variant 7 Dim intIndex As Integer 8 9 ReDim strTestTaker(0 To 24) 10 strTestTaker(0) = "Aさん" 11 strTestTaker(1) = "Bさん" 12 strTestTaker(2) = "Cさん" 13 strTestTaker(3) = "Dさん" 14 strTestTaker(4) = "Eさん" 15 strTestTaker(5) = "Fさん" 16 strTestTaker(6) = "Gさん" 17 strTestTaker(7) = "Hさん" 18 strTestTaker(8) = "Iさん" 19 strTestTaker(9) = "Jさん" 20 strTestTaker(10) = "Kさん" 21 strTestTaker(11) = "Lさん" 22 strTestTaker(12) = "Mさん" 23 strTestTaker(13) = "Nさん" 24 strTestTaker(14) = "Oさん" 25 strTestTaker(15) = "Pさん" 26 strTestTaker(16) = "Qさん" 27 strTestTaker(17) = "Rさん" 28 strTestTaker(18) = "Sさん" 29 strTestTaker(19) = "Tさん" 30 strTestTaker(20) = "Uさん" 31 strTestTaker(21) = "Vさん" 32 strTestTaker(22) = "Wさん" 33 strTestTaker(23) = "Xさん" 34 strTestTaker(24) = "Yさん" 35 36 '----- テスト受験者グループ分け初期化 37 Call initTestTakerGaoups(strTestTaker()) 38 39 '----- テスト受験者グループ分け2分割 40 Call getTestTakerGaoups(objGrpups, 2) 41 Debug.Print "グループ分け2分割" 42 For Each varKey In objGrpups.keys 43 Debug.Print "" & varKey & "" 44 For intIndex = 0 To UBound(objGrpups.Item(varKey)) 45 Debug.Print "[" & objGrpups.Item(varKey)(intIndex) & "]"; 46 Next intIndex 47 Debug.Print 48 Next varKey 49 Debug.Print 50 51 '----- テスト受験者グループ分け2分割後4分割 52 Call getTestTakerGaoups(objGrpups, 4) 53 Debug.Print "グループ分け5分割" 54 For Each varKey In objGrpups.keys 55 Debug.Print "" & varKey & "" 56 For intIndex = 0 To UBound(objGrpups.Item(varKey)) 57 Debug.Print "[" & objGrpups.Item(varKey)(intIndex) & "]"; 58 Next intIndex 59 Debug.Print 60 Next varKey 61 Debug.Print 62 63 '----- テスト受験者グループ分け2分割,4分割後8分割 64 Call getTestTakerGaoups(objGrpups, 8) 65 Debug.Print "グループ分け8分割" 66 For Each varKey In objGrpups.keys 67 Debug.Print "" & varKey & "" 68 For intIndex = 0 To UBound(objGrpups.Item(varKey)) 69 Debug.Print "[" & objGrpups.Item(varKey)(intIndex) & "]"; 70 Next intIndex 71 Debug.Print 72 Next varKey 73 Debug.Print 74 75 '----- テスト受験者グループ分け2分割,4分割,8分割後16分割 76 Call getTestTakerGaoups(objGrpups, 16) 77 Debug.Print "グループ分け16分割" 78 For Each varKey In objGrpups.keys 79 Debug.Print "" & varKey & "" 80 For intIndex = 0 To UBound(objGrpups.Item(varKey)) 81 Debug.Print "[" & objGrpups.Item(varKey)(intIndex) & "]"; 82 Next intIndex 83 Debug.Print 84 Next varKey 85 Debug.Print 86 87End Function

投稿2020/09/22 15:42

kuma_kuma_

総合スコア2506

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

とりあえず

  • 登録人数は任意
  • 分割数も任意
  • 分割処理を繰り返すので以前に一度でも同じグループになった人にならないようにする

で作りました

使い方はテストを見てもらえばわかると思いますが

VBA

1 Call initTestTakerGaoups(strTestTaker())

でテスト受験者を登録

VBA

1 Call getTestTakerGaoups(objGrpups, 8)

で結果を連想配列で取得します。
連想配列からの値の取得方法もテストを見てもらえばわかると思います
(本当はふつうの配列でも良かったんですがデバッグで何の数値か判らなくなる為)

注意点
一定以上「結果を連想配列」で取得すると「同じになった事がない人」が無くなります。
(条件にもよりますが4,5回程度)
その場合は再度「テスト受験者を登録」でリセットしてください。
※わかりずらくなるので処理入れていません。

簡単に説明すると対戦表(objBattleTable)を作ってそこに同じになったかを記録します
普通対戦表は斜めで分けますが検索しやすい様に両側に設定しておく事です。
これはグループ分けの時の判断材料となります。

グループ分けは「余り人数振り分け」で見てもらうと判りやすいですが考え方が
質問者様の内容から変更しています
例として10人を4グループの場合
0. 3,3,4 の3グループ

  1. 3,3,2,2の4グループ

の考え方ができますが今回後者を使用しました。
(10人を6グループなどにも対応可能にする為)

あとはテスト受験者抽出ですが条件はあくまでグループ分け処理1回の間に「同じ人が選ばれない」事
ですのでそれだけに気を付ければ良いだけです。

作って動かして確認しているのですが
デバッグが大変ですみませんが検証お願いします。
なにかありましたら対応します。

  • メイン処理になります

VBA

1Private objBattleTable As Object '対戦テーブル 2Private strTestTakersBuffer() As String 'テスト受験者バッファ 3 4Public Sub initTestTakerGaoups(ByRef strTestTakers() As String) 5'------------------------------------------------------------------------------- 6' initTestTakerGaoups 7' 説明 8' テスト受験者グループ分け初期化 9' パラメータ 10' strTestTakers :テスト受験者一覧 11' 戻り値 12' なし 13'------------------------------------------------------------------------------- 14 15 Dim intTTFIndex As Integer 'テスト受験者バッファインデックス 16 Dim intTTFIndexA As Integer 'テスト受験者バッファインデックスA 17 Dim intTTFIndexB As Integer 'テスト受験者バッファインデックスB 18 Dim strBTKeyA As String '対戦テーブルキーA 19 Dim strBTKeyB As String '対戦テーブルキーB 20 21On Error GoTo initTestTakerGaoups_Error: 22 23 '----- テスト受験者のバッファと対戦表作成 24 ReDim strTestTakersBuffer(0 To UBound(strTestTakers)) 25 Set objBattleTable = CreateObject("Scripting.Dictionary") 26 For intTTFIndex = 0 To UBound(strTestTakers) 27 '----- テスト受験者のバッファ 28 strTestTakersBuffer(intTTFIndex) = strTestTakers(intTTFIndex) 29 '----- 対戦表作成(列) 30 strBTKeyA = strTestTakers(intTTFIndex) 31 objBattleTable.Add strBTKeyA, CreateObject("Scripting.Dictionary") 32 For intTTFIndexB = 0 To UBound(strTestTakers) 33 '----- 対戦表作成(行) 34 strBTKeyB = strTestTakers(intTTFIndexB) 35 objBattleTable.Item(strBTKeyA).Add strBTKeyB, 0 36 Next intTTFIndexB 37 Next intTTFIndex 38 39 '----- 行列同じ場合、(自分同士)の何回同じになったか設定 40 For intTTFIndexA = 0 To UBound(strTestTakersBuffer) 41 strBTKeyA = strTestTakersBuffer(intTTFIndexA) 42 objBattleTable.Item(strBTKeyA).Item(strBTKeyA) = 9999 'Max値 43 Next intTTFIndexA 44 45initTestTakerGaoups_End: 46On Error Resume Next 47Exit Sub 48 49'----- エラー処理 50initTestTakerGaoups_Error: 51Resume initTestTakerGaoups_End: 52End Sub 53 54Public Sub getTestTakerGaoups(ByRef objGrpups As Object, DivisionNumber As Integer) 55'------------------------------------------------------------------------------- 56' getTestTakerGaoups 57' 説明 58' テスト受験者グループ分け 59' パラメータ 60' objGrpups : テスト受験者グループ一覧(連想配列) 61' DivisionNumber : 分割数(グループ数) 62' 戻り値 63' objGrpups : テスト受験者グループ一覧(連想配列) 64'------------------------------------------------------------------------------- 65 66 Dim strTestTakersTemp() As String 'テスト受験者一時保管 67 Dim intTTTIndex As Integer 'テスト受験者一時保管インデックス 68 Dim intGroupsMax() As Integer '各グループ毎の最大人数設定 69 Dim intGroupNumber As Integer 'グループの人数 70 Dim intGroupNumberMod As Integer 'グループの人数(あまり) 71 72 Dim strTestTakers() As String 'グループ内のテスト受験者一覧 73 Dim intTTIndex As Integer 'テスト受験者インデックス 74 Dim intTTIndexBef As Integer 'テスト受験者インデックス(前) 75 Dim intGroupNo As Integer 'グループNo 76 Dim strGroupName As String 'グループ名 77 Dim strTestTaker As String 'テスト受験者 78 Dim strTestTakerBef As String 'テスト受験者 79 Dim blnInTheSame As Boolean '同じになったか 80 Dim blnInLoopEnd As Boolean 'ループの終わり 81 82On Error GoTo getTestTakerGaoups_Error: 83 84 Set objGrpups = CreateObject("Scripting.Dictionary") 85 86 '----- バッファから一時保管へコピー 87 ReDim strTestTakersTemp(0 To UBound(strTestTakersBuffer)) 88 For intTTTIndex = 0 To UBound(strTestTakersTemp) 89 strTestTakersTemp(intTTTIndex) = strTestTakersBuffer(intTTTIndex) 90 Next intTTTIndex 91 92 '----- グループ数計算 93 intGroupNumber = (UBound(strTestTakersTemp) + 1) \ DivisionNumber 94 If intGroupNumber <= 0 Then 95 Call MsgBox("引数エラー:分割数がテスト受験者を超えています。", vbInformation + vbOKOnly) 96 Exit Sub 97 End If 98 99 '----- 各グループ毎の最大人数設定 100 intGroupNumberMod = (UBound(strTestTakersTemp) + 1) Mod DivisionNumber 101 ReDim intGroupsMax(0 To DivisionNumber - 1) 102 For intDivisionIndex = 0 To UBound(intGroupsMax) 103 intGroupsMax(intDivisionIndex) = intGroupNumber 104 Next intDivisionIndex 105 '----- 余り人数振り分け 106 For intDivisionIndex = 0 To intGroupNumberMod - 1 107 intGroupsMax(intDivisionIndex) = intGroupsMax(intDivisionIndex) + 1 108 Next intDivisionIndex 109 110 '----- グループ毎の処理 111 For intGroupNo = 0 To UBound(intGroupsMax) 112 '----- グループ内のテスト受験者一覧初期化 113 ReDim strTestTakers(0 To intGroupsMax(intGroupNo) - 1) 114 strGroupName = "グループ" & (intGroupNo + 1) 115 116 For intTTIndex = 0 To UBound(strTestTakers) 117 118 blnInLoopEnd = False 119 Do Until blnInLoopEnd 120 '----- 一定範囲のランダム数取得 121 'Int((最大値 - 最小値 +1) * Rnd + 最小値) 122 intTTTIndex = Int((UBound(strTestTakersTemp) - 0 + 1) * Rnd + 0) 123 strTestTaker = strTestTakersTemp(intTTTIndex) 'ランダムで選ばれたテスト受験者 124 125 Select Case intTTIndex 126 Case 0 127 '----- 初回は無判定で登録 128 blnInTheSame = False 129 strTestTakers(intTTIndex) = strTestTaker 130 131 '----- テスト受験者一時保管から選んだテスト受験者を削除 132 If UBound(strTestTakersTemp) = 0 Then 133 Erase strTestTakersTemp 134 Else 135 strTestTakersTemp(intTTTIndex) = strTestTakersTemp(UBound(strTestTakersTemp)) 136 ReDim Preserve strTestTakersTemp(0 To UBound(strTestTakersTemp) - 1) 137 End If 138 139 blnInLoopEnd = True 'ループ終了 140 141 Case Else 142 '----- グループに登録されている人と一度も同じになったことが無いか判定 143 blnInTheSame = False 144 For intTTIndexBef = 0 To intTTIndex - 1 145 strTestTakerBef = strTestTakers(intTTIndex) 'グループ登録済みテスト受験者 146 If objBattleTable.Item(strTestTaker).Item(strTestTakerBef) > 0 Then 147 blnInTheSame = True 148 Exit For 149 End If 150 Next intTTIndexBef 151 152 If blnInTheSame = False Then 153 '----- グループに登録されている全員と一度も同じになったことが無い場合 154 strTestTakers(intTTIndex) = strTestTaker 155 156 '----- 対戦表の更新 157 For intTTIndexBef = 0 To intTTIndex - 1 158 strTestTakerBef = strTestTakers(intTTIndex) 'グループ登録済みテスト受験者 159 objBattleTable.Item(strTestTaker).Item(strTestTakerBef) = objBattleTable.Item(strTestTaker).Item(strTestTakerBef) + 1 160 objBattleTable.Item(strTestTakerBef).Item(strTestTaker) = objBattleTable.Item(strTestTakerBef).Item(strTestTaker) + 1 161 Next intTTIndexBef 162 163 '----- テスト受験者一時保管から選んだテスト受験者を削除 164 If UBound(strTestTakersTemp) = 0 Then 165 Erase strTestTakersTemp 166 Else 167 strTestTakersTemp(intTTTIndex) = strTestTakersTemp(UBound(strTestTakersTemp)) 168 ReDim Preserve strTestTakersTemp(0 To UBound(strTestTakersTemp) - 1) 169 End If 170 blnInLoopEnd = True 'ループ終了 171 172 End If 173 End Select 174 Loop 175 Next intTTIndex 176 177 '----- グループ登録   178 objGrpups.Add strGroupName, strTestTakers 179 180 Next intGroupNo 181 182getTestTakerGaoups_End: 183On Error Resume Next 184Exit Sub 185 186'----- エラー処理 187getTestTakerGaoups_Error: 188 Call MsgBox("ErrNo:" & Err & vbNewLine & Error, vbOKOnly) 189Resume getTestTakerGaoups_End: 190End Sub 191

投稿2020/09/22 15:41

編集2020/09/23 14:26
kuma_kuma_

総合スコア2506

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

access

2020/09/23 13:05

こんなにも力を貸して下さいまして本当に有難うございます。 理解に時間がかかるかもしれませんが、じっくり読んで勉強させて頂きます。 取り急ぎお礼申し上げます。
kuma_kuma_

2020/09/23 14:15

いや本当にこの内容説明しずらいと思いますよ。 今回やりたいことの理由を書かれていなかったら理解できませんでした。 私が勝手に考えた方式なので基本となるアルゴリズムはたぶんないです。 読まれておかしいと思ったら質問してください。 後テスト丸投げですみません。 ランダムな結果なので確認が追い付きませんでした。 あと注意点が抜けていたので追記します。
guest

0

1回目と2回目と3回目のグルーピングするマクロは、別々に書くことをおススメします。
グルーピングも1回目用シート、2回目用シート等に分けて、実行ボタンも分けるイメージです。
でないと、プログラムが煩雑となりアルゴリズムを考えるのが大変です。

そうすると、1回目のシートに誰と誰が一緒だったのかの記録が残っているので
それを利用しましょう。

グループを登録していく際に、毎回重複が無いかチェックするイメージです。
以下のようなイメージです。
グループA
1人目の登録 → 被ることは無いので無条件で登録
2人目の登録 → (重複チェック)
①1人目の1回目のグループを見て2人目と同じグループかチェック
②同じだったら、違う人を探して違うグループが当たるまで繰り返す。
③違うグループの人がもういない場合は仕方ないので重複しても登録。

3回目は、無理して2回目も考慮する必要は無いと思います。
かなり難しくなると思います。

グルーピングのマクロを別々に書くことと、3回目の時に2回目を妥協すると
だいぶハードルが下がるのではないかと思います。

投稿2020/09/22 04:40

Kaiser

総合スコア295

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

アルゴリズム無視の暴論になるのですが、以前に作った表はあるのですよね?
それならその表をそのまま生かせば良いのではないでしょうか?

受験する人が全く同じで、組み合わせも前と同じになる、というのなら
組み合わせ表はそのままで、名前だけシャッフルすれば事足りる気がします。
今までにない人数になった場合は、新しく作らないといけませんが、1回作れば後は問題ないですし。

アルゴリズムは他の方に任せます。私には難しすぎる……。
趣旨が違った場合は申し訳ありません。

投稿2020/09/22 04:14

torisan3

総合スコア50

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こういう入力の時はこう出力して欲しいというinputとoutputの例示が無いから質問が漠然としてしまっていると思います。
このままだと要件が曖昧で未定となることが多く質問には回答がつきにくいと思いました。
なるべく避けるという定義が曖昧だと思いますが質問内容に書かれている今知り得る条件だけで考えるなら・・・

こういう時はまず手作業で分配やってみることです。
1回目8人の2グループで2回目4人の4グループだとどうやっても必ず2人は被ります。
なのでそこは仕方ないと割り切って単純にAで1~8と9~16を2つに分けます。
A→Bは必ず2人被るという結果しか無いと思いますので単純に順番に割り振り。
B→Cは左端と右端から1人づつ選んで1g2だとBの左端の最初の1と右端のgと真ん中の2という具合に
Cの最後5グループ目は残り。

A 12345678 9abcdefg
B 159d 2a6e 37bf 48cg
C 1g2 5ca 986 d4e 2f37

16人固定なら初回Aをシャッフルした後、各配列番号に換算して実装すれば良いかと。
人数不定となると面倒そうですね。

これは一例を示しただけですが、質問者さんも例示したほうが良いかと思います。
質問後に足りない条件や要件が後出しされると回答者は回答しにくいものです。

投稿2020/09/22 03:07

mjk

総合スコア303

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

access

2020/09/22 03:51

ご指摘有難うございます。 質問が慣れておらず、ご迷惑をおかけ致します。 要件について追記をさせて頂きました。 せっかく回答くださいましたのに申し訳ございません。
mjk

2020/09/22 04:59

いえいえ。多分修正依頼のやり取りだけだと埒が明かないと思いましたので。 これで質問の要件が整理されて回答がつきやすくなれば良いですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問