diff --git a/hackathons/games/solver.py b/hackathons/games/solver.py new file mode 100644 index 0000000..aa45ef3 --- /dev/null +++ b/hackathons/games/solver.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 + +# Author: Ali Assaf +# Copyright: (C) 2010 Ali Assaf +# License: GNU General Public License + +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) diff --git a/hackathons/games/sudoku.py b/hackathons/games/sudoku.py new file mode 100644 index 0000000..2ec88ae --- /dev/null +++ b/hackathons/games/sudoku.py @@ -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) + +