免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2209 | 回复: 1
打印 上一主题 下一主题

python求解數獨 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-11-15 06:29 |只看该作者 |倒序浏览
業餘時間用python寫了個求解數獨的小程序。
方法很直接,就是根據每個空可能出現的數字來逐個試填,直到找到解。
有興趣可以看看……

CS群:329355400
点击链接加入群【Computer Science】:http://jq.qq.com/?_wv=1027&k=STufuA
  1. #!/usr/bin/python
  2. #
  3. # Useage: ./sudoku.py
  4. #

  5. # import packages
  6. import array
  7. import numpy

  8. # define functions
  9. def init_possible_element( s, p_list, i, j):
  10.     p_list[i][j] = range(1,10)
  11.     for k in range(1,10):
  12.         if k != j and s[i][k] != 0 and s[i][k] in p_list[i][j]:
  13.             p_list[i][j].remove(s[i][k])
  14.         if k != i and s[k][j] != 0 and s[k][j] in p_list[i][j]:
  15.             p_list[i][j].remove(s[k][j])
  16.     for ki in range((i-1)/3*3+1, (i-1)/3*3+4):
  17.         for kj in range((j-1)/3*3+1, (j-1)/3*3+4):
  18.             if (ki != i or kj != j) and s[ki][kj] != 0 and s[ki][kj] in p_list[i][j]:
  19.                 p_list[i][j].remove(s[ki][kj])
  20.     return 0

  21. def init_possible_list( s, p_list):
  22.     empty_box = 0
  23.     for i in range(1,10):
  24.         for j in range(1,10):
  25.             if s[i][j] == 0:
  26.                 empty_box += 1
  27.             else:
  28.                 p_list[i][j] = s[i][j]
  29.                 for k in range(1,10):
  30.                     if k != j and s[i][k] == 0 and s[i][j] in p_list[i][k]:
  31.                         p_list[i][k].remove(s[i][j])
  32.                     if k != i and s[k][j] == 0 and s[i][j] in p_list[k][j]:
  33.                         p_list[k][j].remove(s[i][j])
  34.                 for ki in range((i-1)/3*3+1, (i-1)/3*3+4):
  35.                     for kj in range((j-1)/3*3+1, (j-1)/3*3+4):
  36.                         if (ki != i or kj != j) and s[ki][kj] == 0 and s[i][j] in p_list[ki][kj]:
  37.                             p_list[ki][kj].remove(s[i][j])
  38.     return empty_box

  39. def update_possible_list( s, p_list, i, j, flag):
  40.     if flag != 0:       # s[i][j] turn back to zero, it original value now is in flag
  41.         init_possible_element(s, p_list, i, j)
  42.         for k in range(1,10):
  43.             if k != j and s[i][k] == 0:
  44.                 init_possible_element(s, p_list, i, k)
  45.             if k != i and s[k][j] == 0:
  46.                 init_possible_element(s, p_list, k, j)
  47.         for ki in range((i-1)/3*3+1, (i-1)/3*3+4):
  48.             for kj in range((j-1)/3*3+1, (j-1)/3*3+4):
  49.                 if ki != i and kj != j and s[ki][kj] == 0:
  50.                     init_possible_element(s, p_list, ki, kj)
  51.     else:               # set s[i][j] a value in possible list
  52.         for k in range(1,10):
  53.             if k != j and s[i][k] == 0 and s[i][j] in p_list[i][k]:
  54.                 p_list[i][k].remove(s[i][j])
  55.             if k != i and s[k][j] == 0 and s[i][j] in p_list[k][j]:
  56.                 p_list[k][j].remove(s[i][j])
  57.         for ki in range((i-1)/3*3+1, (i-1)/3*3+4):
  58.             for kj in range((j-1)/3*3+1, (j-1)/3*3+4):
  59.                 if (ki != i or kj != j) and s[ki][kj] == 0 and s[i][j] in p_list[ki][kj]:
  60.                     p_list[ki][kj].remove(s[i][j])
  61.     return 0
  62.    
  63. def find_min_posibble( p_list ):
  64.     min_p = 9
  65.     min_i = 0
  66.     min_j = 0
  67.     for i in range(1,10):
  68.         for j in range(1,10):
  69.             if s[i][j] == 0 and len(p_list[i][j]) < min_p:
  70.                 min_p = len(p_list[i][j])
  71.                 (min_i, min_j) = (i, j)
  72.     return (min_i, min_j, min_p)

  73. def solve_sudoku( s, p_list, empty_box ):
  74.     if empty_box == 0:
  75.         for i in range(1,10):
  76.             for j in range(1,9):
  77.                 print s[i][j],
  78.             print s[i][9]
  79.         return 0
  80.    
  81.     (i, j, p) = find_min_posibble(p_list)
  82.     if p == 0:
  83.         return 1
  84.    
  85.     for t in range(0, p):
  86.         s[i][j] = p_list[i][j][t]
  87.         update_possible_list( s, p_list, i, j, 0)
  88.         try_failed = solve_sudoku( s, p_list, empty_box-1 )
  89.         if try_failed == 1:
  90.             flag = s[i][j]
  91.             s[i][j] = 0
  92.             update_possible_list( s, p_list, i, j, flag)
  93.         else:
  94.             return 0
  95.     return 1
  96. ####################################################################################################

  97. # keep current sudoku status
  98. s = numpy.zeros([10,10], int)

  99. # initial status
  100. s[1][4] = 3
  101. s[1][7] = 6
  102. s[2][2] = 2
  103. s[2][7] = 4
  104. s[2][8] = 7
  105. s[3][2] = 7
  106. s[3][3] = 6
  107. s[3][4] = 4
  108. s[4][1] = 3
  109. s[4][2] = 1
  110. s[4][6] = 9
  111. s[4][8] = 6
  112. s[5][4] = 2
  113. s[5][6] = 6
  114. s[6][2] = 8
  115. s[6][4] = 5
  116. s[6][8] = 2
  117. s[6][9] = 7
  118. s[7][6] = 1
  119. s[7][7] = 5
  120. s[7][8] = 3
  121. s[8][2] = 4
  122. s[8][3] = 1
  123. s[8][8] = 8
  124. s[9][3] = 9
  125. s[9][6] = 4

  126. p_list = [[range(1,10) for i in range(0,10)] for j in range(0,10)]
  127. empty_box = init_possible_list(s, p_list)
  128. solve_sudoku( s, p_list, empty_box )
复制代码

论坛徽章:
3
天秤座
日期:2014-10-29 11:37:572015元宵节徽章
日期:2015-03-06 15:50:39NBA常规赛纪念章
日期:2015-05-04 22:32:03
2 [报告]
发表于 2014-11-15 15:41 |只看该作者
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP