Skip to content

Instantly share code, notes, and snippets.

@shekeru
Last active October 7, 2021 01:07
Show Gist options
  • Save shekeru/3df755dce973be539abac82090f2aa68 to your computer and use it in GitHub Desktop.
Save shekeru/3df755dce973be539abac82090f2aa68 to your computer and use it in GitHub Desktop.
Sudoku Solver v1
from collections import defaultdict
class Sudoku:
def __init__(s, board):
s.board = board
def __repr__(s):
return "\n".join(" ".join(map(str, xs)) for xs in s.board)
def gen_dict(s):
sq = lambda xs, i: xs[3 * (i//3) : 3 * (1 + i//3)]
s.opts = defaultdict(lambda: {*range(1, 10)})
# Rows & Columns & Squares
for x in range(9):
column = {row[x] for row in s.board}
for y in range(9):
if not s.board[y][x]:
s.opts[y, x] -= column
s.opts[y, x] -= {*s.board[y]}
s.opts[y, x] -= {n for row in
sq(s.board, y) for n in sq(row, x)}
return s.opts
def apply_singles(s):
flip = False
for (y, x), opts in s.opts.items():
if len(opts) == 1:
s.board[y][x] = opts.pop()
flip = True
return flip
def reduce_1(s):
flip = True
while flip:
s.gen_dict()
flip = s.apply_singles()
from collections import defaultdict
nby = lambda y, x: (y // 3, x // 3)
class Sudoku:
def __init__(s, board):
s.board = board
def __repr__(s):
return "\n".join(" ".join(map(str, xs)) for xs in s.board)
def gen_dict(s):
sq = lambda xs, i: xs[3 * (i//3) : 3 * (1 + i//3)]
s.opts = defaultdict(lambda: {*range(1, 10)})
# Rows & Columns & Squares
for x in range(9):
column = {row[x] for row in s.board}
for y in range(9):
if not s.board[y][x]:
s.opts[y, x] -= column
s.opts[y, x] -= {*s.board[y]}
s.opts[y, x] -= {n for row in
sq(s.board, y) for n in sq(row, x)}
return s.opts
def apply_singles(s):
flip = False
for (y, x), opts in s.opts.items():
if len(opts) == 1:
s.board[y][x] = opts.pop()
flip = True
return flip
def reduce_1(s):
flip = True
while flip:
s.gen_dict()
flip = s.apply_singles()
if not flip:
s.group_dicts()
flip = s.reduce_2()
def group_dicts(s):
s.rows = defaultdict(list)
s.cols = defaultdict(list)
s.blocks = defaultdict(list)
for (y, x), opts in s.opts.items():
s.blocks[nby(y, x)] += opts
s.rows[y] += opts
s.cols[x] += opts
def reduce_2(s):
flip = False
for (y, x), opts in s.opts.items():
for value in opts:
if (s.blocks[nby(y,x)].count(value) == 1 or
s.rows[y].count(value) == 1 or
s.cols[x].count(value) == 1):
s.board[y][x] = value
flip = True
return flip
puzzle = [[0,9,4,0,0,0,0,8,5],
[5,0,7,0,0,1,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,9,4,0,0,0,6],
[0,7,0,0,2,5,0,4,0],
[0,0,9,0,6,0,0,0,8],
[0,5,0,0,0,3,8,9,0],
[0,0,0,0,0,0,0,6,3],
[0,2,0,0,9,0,7,0,0]]
a = Sudoku(puzzle)
a.reduce_1()
a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment