We define a super sudoku to be a sudoku with extra constraints. If we divide a sudoku board of size 3^2 * 3^2 into “fat rows” and “thin rows” and “fat columns” and “thin columns”, then it takes 4 coordinates to uniquely address a square on the board, so a square’s coordinate will be (fat column, thin column, fat row, thin row).
Using this idea, the regular sudoku constraints can be encoded in a prolog-like way as
for i = 1 .. 3 and j = 1 .. 3
UNIQUE(i, *, j, *) # Every square contains ever number
UNIQUE(i, j, *, *) # Every column contains every number
UNIQUE(*, *, i, j) # Every row contains every number
by symmetry, we can then make three new rules to complete the set:
UNIQUE(*, i, *, j)
UNIQUE(i, *, *, j)
UNIQUE(*, i, j, *)
Note that these 6 rules are all of the possible (4 choose 2) rules for this encoding.
Now, are there any super sudoku squares of size n^2 * n^2 for n = 1,2,3,….? That question was answered in the presentation I learned about the problem as well as (I’m told) in an independent paper written by someone else. If these do exist, how many are there? Well, I wrote code to find this out and preliminary results are:
| n | number of super sudoku of size n^2 * n^2 |
|---|---|
| 1 | 1 |
| 2 | 0 |
| 3 | 104 * 9! |
| 4 | ? |
The code that found these is after the cut, and is O((n2)!n2-1):
#!/usr/bin/env python
# (c) 2007 Peter Boothe (pboothe @gmail.com)
# Offered up to you under the terms of the GPL
# - http://www.fsf.org/licensing/licenses/gpl.html
# This code will count the number of super sudoku on an n^2 * n^2 board. To
# change the value of n, go to line 111
# Already calculated is:
# n count
# 1 1
# 2 0
# 3 104
# 4 >1631
from __future__ import division
class SuperSudoku:
def __init__(self, n):
self.count = 0
self.n = n
self.rows = {}
self.columns = {}
self.squares = {}
self.points = {}
self.minicolumns = {}
self.minirows = {}
self.board = [ [ None for i in range(n*n) ] for i in range(n*n) ]
for i in range(n*n):
self.rows[i] = {}
self.columns[i] = {}
self.squares[i] = {}
self.points[i] = {}
self.minicolumns[i] = {}
self.minirows[i] = {}
def okay_to_add(self, val, x,y):
self.count += 1
if self.count % 10000 == 0:
print self.count, 'boards tested so far...'
if self.board[x][y] != None: return False
fi, fj, i, j = self.twotofour(x,y)
if val in self.rows[fi*self.n + i]: return False
if val in self.columns[fj*self.n + j]: return False
if val in self.squares[fi*self.n + fj]: return False
if val in self.points[i*self.n + j]: return False
if val in self.minicolumns[fi*self.n + j]: return False
if val in self.minirows[i*self.n + fj]: return False
return True
def add(self, val, x, y):
self.board[x][y] = val
fi, fj, i, j = self.twotofour(x,y)
self.rows[fi*self.n + i][val] = None
self.columns[fj*self.n + j][val] = None
self.squares[fi*self.n + fj][val] = None
self.points[i*self.n + j][val] = None
self.minicolumns[fi*self.n + j][val] = None
self.minirows[i*self.n + fj][val] = None
def remove(self, x, y):
val = self.board[x][y]
self.board[x][y] = None
fi, fj, i, j = self.twotofour(x,y)
del self.rows[fi*self.n + i][val]
del self.columns[fj*self.n + j][val]
del self.squares[fi*self.n + fj][val]
del self.points[i*self.n + j][val]
del self.minicolumns[fi*self.n + j][val]
del self.minirows[i*self.n + fj][val]
def twotofour(self, i ,j):
return i // self.n, j // self.n, i%self.n, j%self.n
def __str__(self):
s = ""
for y in range(self.n*self.n):
if y % self.n == 0:
s += '-' * (self.n*self.n*2 + self.n + 1) + '\n'
for x in range(self.n*self.n):
if x % self.n == 0:
s += '|'
if self.board[x][y] != None:
s += '%2d' % (self.board[x][y]+1)
else:
s+= ' .'
s += '|\n'
s += '-' * (self.n*self.n*2 + self.n + 1)
return s
def genAllBoards(board, n, x, y):
if x == n:
y = y+1
x = 0
if y == n:
yield board
return
for potential in range(n):
if board.okay_to_add(potential, x,y):
board.add(potential, x, y)
for b in genAllBoards(board, n, x+1, y):
yield b
board.remove(x, y)
n = 5
board = SuperSudoku(n)
for x in range(n*n):
board.add(x, x, 0)
count = 0
for b in genAllBoards(board, n*n, 0, 1):
print board
print count, "so far..."
count += 1
print count, 'boards are valid - we checked', board.count, 'boards'









