Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions hackathons/games/solver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/env python3

# Author: Ali Assaf <ali.assaf.mail@gmail.com>
# Copyright: (C) 2010 Ali Assaf
# License: GNU General Public License <http://www.gnu.org/licenses/>

from itertools import product

def solve_sudoku(size, grid):
""" An efficient Sudoku solver using Algorithm X.

>>> grid = [
... [5, 3, 0, 0, 7, 0, 0, 0, 0],
... [6, 0, 0, 1, 9, 5, 0, 0, 0],
... [0, 9, 8, 0, 0, 0, 0, 6, 0],
... [8, 0, 0, 0, 6, 0, 0, 0, 3],
... [4, 0, 0, 8, 0, 3, 0, 0, 1],
... [7, 0, 0, 0, 2, 0, 0, 0, 6],
... [0, 6, 0, 0, 0, 0, 2, 8, 0],
... [0, 0, 0, 4, 1, 9, 0, 0, 5],
... [0, 0, 0, 0, 8, 0, 0, 7, 9]]
>>> for solution in solve_sudoku((3, 3), grid):
... print(*solution, sep='\\n')
[5, 3, 4, 6, 7, 8, 9, 1, 2]
[6, 7, 2, 1, 9, 5, 3, 4, 8]
[1, 9, 8, 3, 4, 2, 5, 6, 7]
[8, 5, 9, 7, 6, 1, 4, 2, 3]
[4, 2, 6, 8, 5, 3, 7, 9, 1]
[7, 1, 3, 9, 2, 4, 8, 5, 6]
[9, 6, 1, 5, 3, 7, 2, 8, 4]
[2, 8, 7, 4, 1, 9, 6, 3, 5]
[3, 4, 5, 2, 8, 6, 1, 7, 9]
"""
R, C = size
N = R * C
X = ([("rc", rc) for rc in product(range(N), range(N))] +
[("rn", rn) for rn in product(range(N), range(1, N + 1))] +
[("cn", cn) for cn in product(range(N), range(1, N + 1))] +
[("bn", bn) for bn in product(range(N), range(1, N + 1))])
Y = dict()
for r, c, n in product(range(N), range(N), range(1, N + 1)):
b = (r // R) * R + (c // C) # Box number
Y[(r, c, n)] = [
("rc", (r, c)),
("rn", (r, n)),
("cn", (c, n)),
("bn", (b, n))]
X, Y = exact_cover(X, Y)
for i, row in enumerate(grid):
for j, n in enumerate(row):
if n:
select(X, Y, (i, j, n))
for solution in solve(X, Y, []):
for (r, c, n) in solution:
grid[r][c] = n
yield grid

def exact_cover(X, Y):
X = {j: set() for j in X}
for i, row in Y.items():
for j in row:
X[j].add(i)
return X, Y

def solve(X, Y, solution):
if not X:
yield list(solution)
else:
c = min(X, key=lambda c: len(X[c]))
for r in list(X[c]):
solution.append(r)
cols = select(X, Y, r)
for s in solve(X, Y, solution):
yield s
deselect(X, Y, r, cols)
solution.pop()

def select(X, Y, r):
cols = []
for j in Y[r]:
for i in X[j]:
for k in Y[i]:
if k != j:
X[k].remove(i)
cols.append(X.pop(j))
return cols

def deselect(X, Y, r, cols):
for j in reversed(Y[r]):
X[j] = cols.pop()
for i in X[j]:
for k in Y[i]:
if k != j:
X[k].add(i)
172 changes: 172 additions & 0 deletions hackathons/games/sudoku.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import random
import solver
import copy
import BaseGame

NAME = "SUDOKU"

class Game(BaseGame.BaseGame):
def run(self):
Wrapper()


class Wrapper():
SET_OF_LETTER = {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9}
SET_COLUMN = {'1':0,'2':1,'3':2,'4':3,'5':4,'6':5,'7':6,'8':7,'9':8}

def __init__(self, name = 'Player 1'):
self.name = name
self.points = 0
self._start_game()

def _start_game(self):
obj_sudoku = Sudoku()
print('От игрока требуется заполнить свободные клетки цифрами от 1 до 9 так, '
'чтобы в каждой строке, в каждом столбце и в каждом малом квадрате 3×3 '
'каждая цифра встречалась бы только один раз. '
'Пример ввода: А 1 8')
print('Игрок: ', self.name)
while not obj_sudoku.check_game():
obj_sudoku.pprint()
obj_sudoku = self.input_element(obj_sudoku)


def input_element(self, obj):
position = input()
position = position.split()
obj.set_value(self.SET_OF_LETTER.get(position[0]), self.SET_COLUMN.get(position[1]), int(position[2]))
return obj


class Grid:
def __init__(self, n=3):
self.size = n
self.table = [[((i * n + i // n + j) % (n * n) + 1) for j in range(n * n)] for i in range(n * n)]

def pprint(self):
for i in self.table:
print(i)

def transporting(self):
self.table = list(map(list, zip(*self.table)))

def swap_rows_small(self):
area = random.randrange(0, self.size, 1)
line1 = random.randrange(0, self.size, 1)

N1 = area * self.size + line1

line2 = random.randrange(0, self.size, 1)

while line1 == line2:
line2 = random.randrange(0, self.size, 1)

N2 = area * self.size + line1

self.table[N1], self.table[N2] = self.table[N2], self.table[N1]

def swap_colums_small(self):
self.transporting()
self.swap_rows_small()
self.transporting()

def swap_rows_area(self):
area1 = random.randrange(0, self.size, 1)
area2 = random.randrange(0, self.size, 1)

while area1 == area2:
area2 = random.randrange(0, self.size, 1)

for i in range(0, self.size):
N1, N2 = area1 * self.size + i, area2 * self.size + i
self.table[N1], self.table[N2] = self.table[N2], self.table[N1]

def swap_colums_area(self):
self.transporting()
self.swap_rows_area()
self.transporting()

def mix(self, amt=10):
mix_func = [
self.transporting,
self.swap_rows_small,
self.swap_colums_small,
self.swap_rows_area,
self.swap_colums_area
]
for i in range(1, amt):
id_func = random.randrange(0, 5, 1)
mix_func[id_func]()

def get(self):
self.mix()
return self.table


class Sudoku:
def __init__(self):
grid = Grid()
self.grid = grid.get()
self.user_grid = copy.deepcopy(self.grid)
self.size = grid.size
self.length = self.size * self.size

self.mix_user_grid()

def mix_user_grid(self):
flook = [[0] * self.length for i in range(self.length)]
iterator = 0
difficult = self.length ** 2
while iterator < difficult:
i, j = random.randrange(0, self.length, 1), random.randrange(0, self.length, 1)
if not flook[i][j]:
iterator += 1
flook[i][j] = 1

temp = self.user_grid[i][j]
self.user_grid[i][j] = 0

difficult -= 1

table_solution = []
for copy_i in range(0, self.length):
table_solution.append(self.user_grid[copy_i][:])

i_solution = 0
for solution in solver.solve_sudoku((self.size, self.size), table_solution):
i_solution += 1

if i_solution != 1:
self.user_grid[i][j] = temp
difficult += 1

def check_game(self):
for i in range(self.length):
for j in range(self.length):
if self.grid[i][j] != self.user_grid[i][j]:
return False
return True

def set_value(self, st, col, value):
self.user_grid[st][col] = value

def pprint(self):
num = ' 1 2 3 4 5 6 7 8 9'
print(num)
print(' ', '-' * 19)
string = "{} |{} {} {}|{} {} {}|{} {} {}|"
aab = 'ABCDEFGHI'

count = 1
for i in range(self.length):
print(string.format(aab[i], *self.user_grid[i]))
if not count % 3:
print(' ', '-' * 19)
count += 1

#if __name__ == '__main__':
# print('Введите имя игрока: ')
# player = input()
# game_start = Wrapper(name = player)