ツイッター出題回答
ジャグ配列から順列を作成する

ExcelマクロVBAとエクセル関数についての私的雑感
最終更新日:2022-07-07

ジャグ配列から順列を作成する


ツイッターで会話したので、それを実際にVBAで書いてみました。


ジャグ配列(配列の要素に配列が入っている)から、要素を1つずつ取り出して全順列を作成します。
競馬で言ったら、
1列目、2列目、3列目を指定した3連単のようなものです。

実際にVBAを書こうと思って、ふと考えたら、VBA練習問題でほぼ同じ問題を出していました。

練習問題24(再帰呼出し)
マクロVBA練習問題 ・以下の表の全組み合わせを作成して下さい。サンプルデータでは、組み合わせの数は、8*3*6*5=720通りです。・各項目はカンマ(,)で区切って下さい。・出力先は、新規シートを追加し、1行目に見出しとして"組み合わせ文字"と入れ、2行目より出力して下さい。
こちらでは、シートのデータをもとにシートに出力しているところが違うだけです。
以下のVBAは、ここの解答VBAのコードと基本的には同じやり方にしました。


出題ツイート

n次元の配列があり、各要素はランダム要素数の配列、つまりジャグ配列。
n次元の要素から1つずつ取り出す組み合わせ
まあつまり、3つなら3連単w
(1)1,2,3
(2)4,5
(3)6,7,8
なら
1,4,6
1,4,7
1,4,8
1,5,6
・・・
これだと結構難しいですかね。

Excel エクセル VBA問題
https://twitter.com/yamaoka_ss/status/1543923471087898626


作成したVBA

イミィディエイト ウィンド に順次出力



Sub test()
  'ジャグ配列を作成する。
  Dim inAry, tAry, i, j, v, dic As Dictionary
  ReDim inAry(1 To 3) 'とりあえず3次元で
  Debug.Print "入力ジャグ配列"
  For i = LBound(inAry) To UBound(inAry)
    Randomize
    ReDim tAry(1 To Int(4 * Rnd + 2)) 'とりあえず要素数は2~5で
    Set dic = New Dictionary
    For j = LBound(tAry) To UBound(tAry)
      Do
        v = Int(9 * Rnd + 1) 'とりあえず数値は1桁で
        If Not dic.Exists(v) Then Exit Do
      Loop
      tAry(j) = v
      dic.Add v, v
    Next
    inAry(i) = tAry
    Debug.Print Join(tAry, ",")
  Next
  
  'ジャグ配列から順列を作成する
  Debug.Print "出力組み合わせ"
  Dim tmpAry
  ReDim tmpAry(1 To UBound(inAry))
  Call func(inAry, tmpAry, 1)
End Sub

'再帰プロシージャー
Private Sub func(ByRef inAry, ByRef tmpAry, ByVal n As Long)
  Dim i As Long, v
  v = inAry(n)
  For i = LBound(v) To UBound(v)
    tmpAry(n) = v(i)
    If n >= UBound(tmpAry) Then
      Debug.Print Join(tmpAry, ",")
    Else
      Call func(inAry, tmpAry, n + 1)
    End If
  Next
End Sub

Excel エクセル VBA問題


全ての順列を配列で返す



Sub test()
  'ジャグ配列を作成する。
  Dim inAry, tAry, i, j, v, dic As Dictionary
  ReDim inAry(1 To 3) 'とりあえず3次元で
  Debug.Print "入力ジャグ配列"
  For i = LBound(inAry) To UBound(inAry)
    Randomize
    ReDim tAry(1 To Int(4 * Rnd + 2)) 'とりあえず要素数は2~5で
    Set dic = New Dictionary
    For j = LBound(tAry) To UBound(tAry)
      Do
        v = Int(9 * Rnd + 1) 'とりあえず数値は1桁で
        If Not dic.Exists(v) Then Exit Do
      Loop
      tAry(j) = v
      dic.Add v, v
    Next
    inAry(i) = tAry
  Next
  
  'ジャグ配列から順列を作成する
  Debug.Print "出力組み合わせ"
  Dim outAry
  Call func(inAry, outAry)
  
  'シートに出力
  For i = LBound(inAry) To UBound(inAry)
    Cells(i, 1) = Join(inAry(i), ",")
  Next
  For i = LBound(outAry) To UBound(outAry)
    Cells(i, 2) = outAry(i)
  Next
End Sub

'再帰プロシージャー
Private Sub func(ByRef inAry, ByRef outAry, _
         Optional ByRef n As Long = 1, _
         Optional ByRef tmpAry)
  If Not IsArray(tmpAry) Then ReDim tmpAry(1 To UBound(inAry))

  Dim i As Long, v
  v = inAry(n)
  For i = LBound(v) To UBound(v)
    tmpAry(n) = v(i)
    If n >= UBound(tmpAry) Then
      If IsArray(outAry) Then
        ReDim Preserve outAry(1 To UBound(outAry) + 1)
      Else
        ReDim outAry(1 To 1)
      End If
      outAry(UBound(outAry)) = Join(tmpAry, ",")
    Else
      Call func(inAry, outAry, n + 1, tmpAry)
    End If
  Next
End Sub

Excel エクセル VBA問題




同じテーマ「ツイッター出題回答 」の記事

オブジェクトのByRef、ByVal、Variant
「マクロの登録」で登録できないプロシージャーは?
抜けている数値を探せ
15桁を超える数値の足し算
ジャグ配列から順列を作成する
m/d/yyyy形式文字列を日付シリアル値に変換
成績表(ネ申エクセル)を別表に集計
シート内の全テーブルを1つに統合
VBA穴埋め問題「On Error GoToの挙動」
年月に対して有効な日だけの入力規則のリスト作成
8桁数値が日付として不適切なら赤にする条件付き書式


新着記事NEW ・・・新着記事一覧を見る

8桁数値が日付として不適切なら赤にする条件付き書式|ツイッター出題回答 (2022-08-10)
年月に対して有効な日だけの入力規則のリスト作成|ツイッター出題回答 (2022-08-10)
VBA穴埋め問題「On Error GoToの挙動」|ツイッター出題回答 (2022-08-09)
シート内の全テーブルを1つに統合|ツイッター出題回答 (2022-08-01)
VBAで漢数字を算用数字に変換|ツイッター出題回答 (2022-07-12)
成績表(ネ申エクセル)を別表に集計|ツイッター出題回答 (2022-07-09)
m/d/yyyy形式文字列を日付シリアル値に変換|ツイッター出題回答 (2022-07-07)
ジャグ配列から順列を作成する|ツイッター出題回答 (2022-07-05)
15桁を超える数値の足し算|ツイッター出題回答 (2022-07-01)
抜けている数値を探せ|ツイッター出題回答 (2022-07-01)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
6.マクロって何?VBAって何?|VBA入門
7.Excelショートカットキー一覧|Excelリファレンス
8.並べ替え(Sort)|VBA入門
9.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
10.エクセルVBAでのシート指定方法|VBA技術解説




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ