Number Place(数独)とSwift 3 (3)

backtrack

グラフは、再帰的関数dropNum(index: Int)が呼ばれたときのindexの値を示しています。初期状態では、52個の埋めるべき空白があることに注意して下さい。

    func dropNum(index: Int) {
        var place = emptyPlaces[index]
        for num in 1...9 {
            if isSafeForNum(place: place, num: num) {
                table[place.row][place.col] = num
                putCount += 1
                if putCount == nplaces { return }
                dropNum(index: index+1)
                if putCount != nplaces {
                    place = emptyPlaces[index]
                    table[place.row][place.col] = 0
                    putCount -= 1
                }
            }
        }
    }

あなたは以下の95行をコピー・ペーストして、IBM Swift Sandboxというサイトで、このプログラムを試してみることができます。

backtrack2

struct Place {
    var row: Int = -1
    var col: Int = -1
}

class NumBoard {
    var table       = [[Int]]()
    var emptyPlaces = [Place]()
    var place       = Place()
    let nplaces : Int
    var putCount: Int

    init() {
        table = [[7,0,3, 0,0,0, 0,0,0],
                 [0,5,1, 3,7,0, 4,0,0],
                 [6,0,0, 0,1,0, 0,2,0],
                 [0,0,4, 6,0,0, 0,0,0],
                 [0,0,0, 0,0,7, 0,8,0],
                 [5,0,0, 2,3,1, 9,0,0],
                 [3,0,0, 0,2,4, 0,9,1],
                 [0,0,0, 0,0,0, 8,4,0],
                 [0,0,7, 0,9,0, 2,0,0]]
        for rr in 0...8 {
            for cc in 0...8 {
                if table[rr][cc] == 0 {
                    place.row = rr
                    place.col = cc
                    emptyPlaces.append(place)
                 }
            }
        }
        putCount = 0
        nplaces  = emptyPlaces.count
        myprint(table: table)
        print("nplaces = \(nplaces)")
    }

    func myprint(table: [[Int]]) {
        print("-----------------")
        for rr in 0...8 {
            for cc in 0...8 {
                if table[rr][cc] == 0 {
                    print(".", terminator: " ")
                } else {
                    print(table[rr][cc], terminator: " ")
                }
            }
            print("")
        }
        print("-----------------")
    }
    
    func isSafeForNum(place: Place, num: Int) -> Bool {
        for rr in 0...8 {
            if num == table[rr][place.col] { return false }
        }
        for cc in 0...8 {
            if num == table[place.row][cc] { return false }
        }
        let rowBase = (place.row / 3) * 3
        let colBase = (place.col / 3) * 3
        for rr in 0...2 {
            for cc in 0...2 {
                if num == table[rowBase+rr][colBase+cc] { return false }
            }
        }
        return true
    }

    func dropNum(index: Int) {
        var place = emptyPlaces[index]
        for num in 1...9 {
            if isSafeForNum(place: place, num: num) {
                table[place.row][place.col] = num
                putCount += 1
                if putCount == nplaces { return }
                dropNum(index: index+1)
                if putCount != nplaces {
                    place = emptyPlaces[index]
                    table[place.row][place.col] = 0
                    putCount -= 1
                }
            }
        }
    }

    func play() {
        dropNum(index: 0)
        myprint(table: table)
    }
}

// main program
let myboard = NumBoard()
myboard.play()