In [1]:
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
from random import sample
In [2]:
def generate_random_sudoku(n):
    base  = n
    side  = base*base
    def pattern(r,c): return (base*(r%base)+r//base+c)%side
    def shuffle(s): return sample(s,len(s)) 
    rBase = range(base) 
    rows  = [ g*base + r for g in shuffle(rBase) for r in shuffle(rBase) ] 
    cols  = [ g*base + c for g in shuffle(rBase) for c in shuffle(rBase) ]
    nums  = shuffle(range(1,base*base+1))
    board = [ [nums[pattern(r,c)] for c in cols] for r in rows ]
    board = np.asarray(board)
    return board
In [3]:
def empty_sudoku_graph(n):
    blank_board = np.arange(n*n*n*n).reshape(n*n,n*n)
    def get_edges(nodes):
        edges = [(a, b) for idx, a in enumerate(nodes) for b in nodes[idx + 1:]]
        return edges
    box_edges=[]
    row_edges=[]
    column_edges=[]
    for iteration in range(n*n):
        i = iteration//n
        j = iteration%n
        column = np.asarray(blank_board)[:,iteration]
        row = np.asarray(blank_board)[iteration,:]
        box=blank_board[(i)*n:(i+1)*n,(j)*n:(j+1)*n].flatten()
        box_edges += get_edges(box)
        row_edges += get_edges(row)
        column_edges += get_edges(column)
    return box_edges, row_edges, column_edges
In [4]:
def draw_networkx_graph(n, board, box_edges, row_edges, column_edges, layout='grid'):
    G = nx.empty_graph(n*n*n*n)
    if layout=='circular':
        pos=nx.circular_layout(G)
    if layout=='spring':
        pos=nx.spring_layout(G)
    if layout=='grid':
        pos = dict(zip(list(G.nodes()), nx.grid_2d_graph(n*n,n*n)))
        
    mapping = dict(zip(G.nodes(), board.flatten()))
    plt.figure(1,figsize=(12,12)) 
    nx.draw(G, pos, labels=mapping, with_labels=True, node_color='white')
    nx.draw_networkx_edges(G,pos,edgelist=box_edges,width=2, alpha=0.5, edge_color="tab:red")
    nx.draw_networkx_edges(G,pos,edgelist=row_edges,width=2, alpha=0.5, edge_color="tab:green")
    nx.draw_networkx_edges(G,pos,edgelist=column_edges,width=2, alpha=0.5, edge_color="tab:blue")
    plt.show()
    
In [5]:
def sudoku(n, layout):
    board = generate_random_sudoku(n)
    box_edges, row_edges, column_edges = empty_sudoku_graph(n)
    draw_networkx_graph(n, board, box_edges, row_edges, column_edges, layout)
In [6]:
sudoku(3, 'grid')
In [7]:
sudoku(3, 'circular')