woodsja icon

Untitled

woodsja | PRO | 12/18/18 03:25:01 PM UTC | 0 ⭐ | 346 👁️ | Never ⏰ | []
Python |

5.01 KB

|

None

|

0 👍

/

0 👎

#!/usr/bin/env python
# coding: utf-8
 
# In[1]:
 
 
# sections of code borrowed from "You will Never Want to Play Sudoku Again" by Srini Devadas
# https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-s095-programming-for-the-puzzled-january-iap-2018/puzzle-8-you-wont-want-to-play-sudoku-again/sudoku.py
# Whatever license Srini chose applies to the code he or his grad students wrote. Standard MIT license applies to anything else that I wrote.
 
 
# In[2]:
 
 
import numpy as np
import copy
 
 
# In[3]:
 
 
# global to keep track of the number of backtracks necessary
limit = 10000
backtracks = 0
 
 
# In[5]:
 
 
def findNextCellToFill(grid):
    # Takes a 9 by 9 grid and looks row by column for the first zero.
    # Returns either x, y coordinates of first '0' or -1, -1
    for x in range(0, 9):
        for y in range(0, 9):
            if grid[x][y] == 0:
                return x, y
    return -1, -1
 
 
# In[6]:
 
 
def isValid(grid, i, j, e):
    # takes a 9 by 9 grid; i,j coordinates; and a number 'e' then looks row-wise, column-wise, and sector-wise for duplicates of the number 'e''
    # returns True if passes row/column/sector checks.
    # returns False otherwise
    rowOk = all([e != grid[i][x] for x in range(9)])
    if rowOk:
        columnOk = all([e != grid[x][j] for x in range(9)])
        if columnOk:
            # find the top left x, y coordinate of section containing the i,j cell
            secTopX, secTopY = 3*(i//3), 3*(j//3)
            for x in range(secTopX, secTopX+3):
                for y in range(secTopY, secTopY+3):
                    if grid[x][y] == e:
                        return False
            return True
    return False
 
 
# In[7]:
 
 
def makeRandomSudoku(number_of_randoms):
    # generates a random board with no constraints
    # board has number_of_randoms filled in values with all other values as zero
    grid_list = [0]*81
    locations = np.random.choice(81, number_of_randoms, replace=False)
    for location in locations:
            grid_list[location] = int(np.random.randint(1,high=10))
    
    i = 0
    grid = []
    while i < len(grid_list):
        grid.append(grid_list[i:i+9])
        i+=9
    return grid
 
 
# In[8]:
 
 
def solveSudoku(grid, i=0, j=0):
    # fills in missing squares of Sudoku puzzle using rules with a brute-force guess/check
    # takes a grid and starts looking in the top left corner i,j = 0,0
    global limit
    global backtracks
    if backtracks < limit:
        i, j = findNextCellToFill(grid)
        if i == -1:
            # we solved it or there's nothing left to solve
            return True
 
        for e in range (1, 10):
            # try different values in i, j location
            if isValid(grid, i, j, e):
                grid[i][j] = e
                if solveSudoku(grid, i, j):
                    return True
 
                # undo current cell for backtracking
                if backtracks < limit:
                    backtracks += 1
                    grid[i][j] = 0
        else:
            # loop fell through without filling a number
            return False
 
 
 
    else:
        return False
 
        
    
 
 
# In[9]:
 
 
def printSudoku(grid):
    numrow = 0
    for row in grid:
        if numrow % 3 == 0 and numrow != 0:
            print(' ')
        print(row[0:3], ' ', row[3:6], ' ', row[6:9])
        numrow += 1
    return
 
 
# In[10]:
 
 
def process_input(grid):
    # converts a grid into a flat list with one-hot encoding
    onehot_encoded = list()
    flat_grid = [item for sublist in grid for item in sublist]
    for value in flat_grid:
        temp = [0 for _ in range(10)]
        temp[value - 1] = 1
        onehot_encoded.append(temp)
    #flat_onehot_grid = [item for sublist in onehot_encoded for item in sublist]
    return onehot_encoded
 
 
# In[11]:
 
 
def build_dataset(number_of_datapoints, number_of_randoms):
    # takes an int, number_of_datapoints, and builds a dataset of solvable Sudoku grids
    # each test_grid will have number_of_randoms constraints
    test_grid
    test_grid = makeRandomSudoku(number_of_randoms)
    
 
 
# In[12]:
 
 
def generate_pair():
    global backtracks
    # generates an unsolved and solved grid
    backtracks = 0
    solved = makeRandomSudoku(20)
    unsolved = copy.deepcopy(solved)
    if solveSudoku(solved):
        return unsolved, solved
    else:
        backtracks = 0
        return generate_pair()
 
 
# In[ ]:
 
 
import time
data = []
 
start = time.time()
for pair in range(5):
    data1, data2 = generate_pair()
    data.append([data1, data2])
end = time.time()
print(end-start)
 
 
# In[ ]:
 
 
printSudoku(data[0][0])
print('\n')
printSudoku(data[0][1])
 
 
# In[ ]:
 
 
def save_data(data):
    with open("Sudoku_data.txt", 'w') as f:
        for pair in data:
            for grid in pair:
                for row in grid:
                    for column in row:
                        f.write("%i\n" % column)

Comments