圓州率
🌐

Feature Image

數獨求解器

數學, 演算法, 作品集, Python
用演算法解數獨問題。

解法簡介

就不贅述數獨的規則了,詳見數獨介紹。以此圖為例

Sudoku Example

定義座標

Coordinate

已知每個格子能填入1到9,而填入時需要驗證3個唯一性

  1. 列唯一性

    Unique_1

    例:(0, 2)不能填入3,會和(0, 1)的3產生衝突

  2. 行唯一性

    Unique_2

    例:(0, 2)不能填入8,會和(2, 2)的8產生衝突

  3. 區唯一性

    Unique_3

    例:(0, 2)不能填入5,會和(0, 0)的5產生衝突

範例

仍用同一張圖做為範例,將未知格視為0

Sudoku Example

將由上至下,由左至右找出未知格的位置

座標\數值0123456789
(0, 2)v
(0, 3)v
(0, 5)v
(8, 6)v

首先在第一個未知格(0, 2),往後選取一個元素,也就是填入1,發現能通過唯一性驗證。

Try_1

座標\數值0123456789
(0, 2)v
(0, 3)v
(0, 5)v

接著在下一個未知格(0, 3),往後選取一個元素,也就是填入1,發現列唯一性不通過

Check_1

再繼續往後選取一個元素,也就是填入2,發現能通過唯一性驗證。

Try_2

座標\數值0123456789
(0, 2)v
(0, 3)v
(0, 5)v

接著在下一個未知格(0, 5)重複上述動作,會發現1, 2, 3都不通過唯一性驗證,因此填入4。

Try_3

座標\數值0123456789
(0, 2)v
(0, 3)v
(0, 5)v

重複上述步驟,依序對每個未知格操作

每次都填入第一個能滿足唯一性的驗證的元素

Try_4

座標\數值0123456789
(0, 2)v
(0, 3)v
(0, 5)v
(0, 6)v
(0, 7)v
(0, 8)v

接著在(0, 8)這格,會發現所有元素皆無法通過唯一性驗證,這表示前面的未知格一定存在錯誤。回到上一個未知格,試著填入下一個可行的元素。

但此時(0, 7)的元素是9,已經是最後一個元素,這依舊表示前面的未知格一定存在錯誤。將(0, 7)歸零後,再繼續回到上一個未知格(0, 6),試著填入下一個可行的元素,也就是填入9。

Try_5

座標\數值0123456789
(0, 2)v
(0, 3)v
(0, 5)v
(0, 6)v
(0, 7)v
(0, 8)v

藉由上述規則 ,我們可以遍歷所有可能的選項。簡言而之,基本概念是

一步一步對未知格填入內容,若無法填入即表示存在錯誤,把當前未知格歸零後,往後退回一步再次嘗試下一個元素。

演算法

我們可以藉由下列方式快速遍歷所有可能的選項

  1. 移動到下一個未知格
  2. 查看此格內容
    1. 若此格內為0~8,填入下一個元素(0的下一個元素是1,1的下一個元素是2,以此類推)
    2. 若此格內為9,將此格設為0,移動到上一個未知格,重新執行第2步
  3. 驗證三個唯一性
    1. 若通過,則回到第1步
    2. 若不通過,則回到第2步

第2步的查看內容,就是驗證是否為最後一個元素。可以將此方式擴展開,一般的數獨為9x9的大小,我們可以擴展成16x16的數獨,用相同的邏輯來處理

  1. 查看此格內容
    1. 若此格內為0~15,填入下一個元素(0的下一個元素是1,1的下一個元素是2,以此類推)
    2. 若此格內為16,將此格設為0,移動到上一個未知格,重新執行第2步

等價於

  1. 驗證是否為最後一個元素
    1. 若否,則填入下一個元素
    2. 若是,則將此格歸零,移動到上一個未知格,重新執行第2步

最後再加上完成與無解檢測。

完整的演算法為

  1. 移動到下一個未知格。若無下一個未知格,即表示完成
  2. 驗證是否為最後一個元素
    1. 若否,則填入下一個元素
    2. 若是,則將此格歸零,移動到上一個未知格,重新執行第2步。若無上一個未知格,即表示無解
  3. 驗證三個唯一性
    1. 若不通過,則回到第2步
  4. 若通過,則回到第1步

成果