再びトーナメント表作成 ⑦ 式の一般化

前回からかなり時間が空いてしまったが、トーナメント表作成の仕組みを焼き直ししている。
infoment.hatenablog.com

今回は、ずっと以前に作成したクラスモジュールの一般化について。

なぜ前回から時間が空いてしまったか。理由は幾つかあるが、その一つとして
「ずっと以前に作成したクラスモジュールの一般化にてこずった」というのが
ある。前回作成したトーナメントは、実は32人までにしか対応していない。
そこで今回は、まず↓の部分を一般化することにした。

抜き出してみると、こんな感じだ。

        If iMax >= 4 Then
            Dim SetArrayBoundary() As Variant
            ReDim SetArrayBoundary(1 To 2 ^ (iMax - 2) - 1)
                For i = 1 To UBound(SetArrayBoundary)
                    Select Case i
                        Case 1
                            SetArrayBoundary(i) = (2 ^ iMax) / 2
                        Case Is <= 3
                            SetArrayBoundary(i) = (2 ^ iMax) / 4 * (2 * i - 3)
                        Case Is <= 7
                            SetArrayBoundary(i) = (2 ^ iMax) / 8 * (2 * i - 7)
                        Case Is <= 15
                            SetArrayBoundary(i) = (2 ^ iMax) / 16 * (2 * i - 15)
                        Case Is <= 31
                            SetArrayBoundary(i) = (2 ^ iMax) / 32 * (2 * i - 31)
                    End Select
                Next
        End If

Select Case で、小刻みに範囲を変化させている。これを一つに統合することを
試みたのだが、集中して考える時間がなかなか取れず、今に至った訳で。まず、
↓ の部分に変数 i が登場しない。

SetArrayBoundary(i) = (2 ^ iMax) / 2

この部分は切り分けるか?と考えては、思考停止の繰り返し。しかしよく見みれば
この部分、正しくは

SetArrayBoundary(i) = (2 ^ iMax) / 2 * (2 * i - 1)

であることに気が付いた。これに気づいた後は、早かった。

        If iMax >= 4 Then
            Dim SetArrayBoundary() As Variant
            ReDim SetArrayBoundary(1 To 2 ^ (iMax - 2) - 1)
                For i = 1 To UBound(SetArrayBoundary)
                    j = 2 ^ WorksheetFunction.RoundUp(WorksheetFunction.Log(i + 1, 2), 0)
                    SetArrayBoundary(i) = (2 ^ iMax) / j * (2 * i - j + 1)
                    Cells(i, 1) = i
                    Cells(i, 4) = SetArrayBoundary(i)
                Next
        End If

ポイントは、iを直近の2の累乗に切り上げる点にあった。

これで、Select Caseによる場合分けが不要になった。よし、これで先に進める。
そう思ってから、気が付いた。この部分、新しく作っている範囲に含まれてる
から、わざわざ一般化する必要なかった・・・。

というわけで、今日からまた再開です。

参考まで。