【VBAリファレンス】VBAで数独を攻略する:バックトラッキングアルゴリズムの極意と最適化戦略

スポンサーリンク

概要

数独(ナンプレ)は論理パズルの一種であり、9×9のグリッドを1から9の数字で埋めるシンプルなルールを持ちながら、その計算複雑性は非常に奥深いものです。VBA(Visual Basic for Applications)を用いて数独を解くことは、再帰呼び出しとアルゴリズムの効率性を学ぶ絶好の教材となります。本稿では、前回に引き続き、数独ソルバーの心臓部である「バックトラッキング(Backtracking)」アルゴリズムの論理的要点を深掘りし、VBA特有のメモリ管理とパフォーマンスを最大化するための実装テクニックを解説します。

詳細解説:バックトラッキングの本質

バックトラッキングとは、いわゆる「深さ優先探索」の一種です。空いているセルに対して、「1から9の数字を順に試す」→「その数字がルール(行・列・3×3ブロック内での重複禁止)を満たすか確認する」→「満たせば次のセルへ進む」というプロセスを繰り返します。

もし、あるセルでどの数字も当てはまらない(行き止まり)が発生した場合、一つ前のセルに戻り、別の数字を試します。この「戻る」というプロセスが、人間が直感的に行っている試行錯誤を数学的に再現したものです。VBAでこれを実装する際、最も重要なのは「現在の状態の保持」と「探索の終了条件」の明確化です。

再帰関数を用いる際、VBAのスタック領域には制限があるため、過度な再帰呼び出しは「スタックオーバーフロー」を引き起こすリスクがあります。しかし、数独の最大深さは81(全セル)であるため、適切に実装すればVBAの標準的なスタックサイズで十分に対応可能です。

サンプルコード:高速化されたバックトラッキング実装

以下のコードは、数独の盤面を配列として扱い、論理チェックを最小化する工夫を凝らした実装例です。


Option Explicit

' 9x9の数独盤面を保持するグローバル配列
Dim Board(1 To 9, 1 To 9) As Integer

' メイン処理:再帰的に解を探す
Function SolveSudoku() As Boolean
    Dim r As Integer, c As Integer
    Dim num As Integer
    
    ' 空いているセルを探す
    If Not FindEmptyCell(r, c) Then
        SolveSudoku = True ' 解が見つかった
        Exit Function
    End If
    
    ' 1から9まで試行
    For num = 1 To 9
        If IsValid(r, c, num) Then
            Board(r, c) = num
            
            ' 再帰呼び出し
            If SolveSudoku() Then
                SolveSudoku = True
                Exit Function
            End If
            
            ' バックトラック:解けなければリセット
            Board(r, c) = 0
        End If
    Next num
    
    SolveSudoku = False
End Function

' ルールチェック:行・列・3x3ブロックの確認
Function IsValid(row As Integer, col As Integer, num As Integer) As Boolean
    Dim i As Integer, j As Integer
    Dim startRow As Integer, startCol As Integer
    
    ' 行と列のチェック
    For i = 1 To 9
        If Board(row, i) = num Or Board(i, col) = num Then
            IsValid = False
            Exit Function
        End If
    Next i
    
    ' 3x3ブロックのチェック
    startRow = ((row - 1) \ 3) * 3 + 1
    startCol = ((col - 1) \ 3) * 3 + 1
    For i = startRow To startRow + 2
        For j = startCol To startCol + 2
            If Board(i, j) = num Then
                IsValid = False
                Exit Function
            End If
        Next j
    Next i
    
    IsValid = True
End Function

パフォーマンス向上のための実務アドバイス

VBAで数独ソルバーを開発する際、避けて通れないのが「速度」の問題です。セルに書き込むたびにワークシートのセルを操作(Range(“A1”).Value = numなど)すると、画面更新や再計算処理が走り、計算時間が指数関数的に増加します。

1. メモリ内で完結させる:
盤面データは必ずVBA内の配列(Long型やInteger型の二次元配列)で保持してください。ワークシートへの書き出しは、全探索が完了した後の「最後の一回のみ」に限定します。

2. 制約伝播(Constraint Propagation)の導入:
単なるバックトラッキングは「しらみつぶし」に近いですが、探索前に「そのセルに置ける可能性がある数字はどれか」という候補集合を動的に管理する手法(Dancing Linksアルゴリズムの概念など)を組み合わせると、探索回数を劇的に減らせます。

3. 早期終了の活用:
再帰関数内で解が見つかった瞬間に「True」を返し、他の不要な探索をすべて中断させるフラグ管理を徹底してください。

4. APIの活用と画面更新の停止:
もしワークシート上のビジュアルを更新しつつ解く必要がある場合は、`Application.ScreenUpdating = False`を必ず冒頭で設定してください。これだけで描画負荷が劇的に下がります。

まとめ

VBAによる数独ソルバーは、単なるパズル解き以上の価値があります。再帰アルゴリズムの習得、配列操作の最適化、そして論理的思考のコード化という、プログラミングに必要な要素がすべて凝縮されているからです。

今回紹介したバックトラッキングアルゴリズムは、数独の解法としては最も基礎的かつ強力なものです。まずはこのコードをベースに、より複雑なパズルをいかに速く解けるか、試行回数をカウントする変数を追加したり、より高度な「候補数絞り込み」ロジックを実装したりして、自身のスキルを磨いてみてください。VBAという言語の特性を理解すれば、Excelは単なる表計算ソフトから、強力な計算エンジンへとその姿を変えるはずです。次回の記事では、さらに高速な「Dancing Links」アルゴリズムのVBA実装へのアプローチについて解説する予定です。

タイトルとURLをコピーしました