from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC
board = [] for tr in table.find_elements_by_xpath(".//tr"): row = [] for input_e in tr.find_elements_by_xpath(".//input[@class='i3']"): cell = input_e.get_attribute("value") row.append(cell if cell else".") board.append(row) board
line = [0] * 9 column = [0] * 9 block = [[0] * 3 for _ in range(3)] valid = False spaces = list()
for i in range(9): for j in range(9): if board[i][j] != ".": digit = int(board[i][j]) - 1 flip(i, j, digit)
while True: modified = False for i in range(9): for j in range(9): if board[i][j] == ".": mask = ~(line[i] | column[j] | block[i // 3][j // 3]) & 0x1ff if not (mask & (mask - 1)): digit = bin(mask).count("0") - 1 flip(i, j, digit) board[i][j] = str(digit + 1) modified = True if not modified: break
for i in range(9): for j in range(9): if board[i][j] == ".": spaces.append((i, j))
dfs(0)
再次运行:
solveSudoku(board) board
耗时仅3.2秒,性能提升不少。
优化思路:如果一个空白格只有唯一的数可以填入,也就是其对应的 b 值和 b-1 进行按位与运算后得到 0(即 b 中只有一个二进制位为 1)。此时,我们就可以确定这个空白格填入的数,而不用等到递归时再去处理它。
下面我们需要做的就是将结果填入到相应的位置中,毕竟自己手敲也挺费劲的。
写结果回写到网页
对于Selenium,我们可以模拟人工点击按钮并发送键盘操作。
下面我们重新遍历table标签,并使用click和send_keys方法:
for i, tr in enumerate(table.find_elements_by_xpath(".//tr")): for j, input_e in enumerate(tr.find_elements_by_xpath(".//input[@class='i3']")): if input_e.get_attribute("readonly") == "true": continue input_e.click() input_e.clear() input_e.send_keys(board[i][j])