import unittest
import sudoku_solver


board_1 = [
    ".1.82....",
    "...3.6...",
    "54..7....",
    "..2...95.",
    "7.52..1.4",
    ".89...2..",
    "....8..79",
    "...5.3...",
    "...792.3."
]

solution_1 = [
    '317825496',
    '298346715',
    '546971328',
    '432618957',
    '765239184',
    '189457263',
    '623184579',
    '971563842',
    '854792631'
]

board_2 = [
    "16...7.9.",
    ".281.967.",
    ".....82..",
    "...7....4",
    "....6....",
    "5....3...",
    "..75.....",
    ".869.173.",
    ".4.3...86"
]

solution_2 = [
    '163427598',
    '428159673',
    '759638241',
    '632795814',
    '891264357',
    '574813962',
    '317586429',
    '286941735',
    '945372186'
]

board_3 = [
    '..1..8763',
    '8..9.....',
    '....1..5.',
    '.8....4..',
    '1.54.3...',
    '.6....2..',
    '....6..2.',
    '4..8.....',
    '..6..1378'
]

solution_3 = [
    '941258763',
    '857936142',
    '632714859',
    '789625431',
    '125483697',
    '364179285',
    '518367924',
    '473892516',
    '296541378'
]

empty = ['.' * 9 for i in range(9)]


class test_sudoku_solver(unittest.TestCase):
    def test_simple(self):
        board = sudoku_solver.Board()
        board.set_initial(board_1)
        row = board.get_row(0)
        self.assertEqual(row, board_1[0])
        col = board.get_col(0)
        self.assertEqual(col, "..5.7....")
        block = board.get_block(0, 0)
        self.assertEqual(block, [".1.", "...", "54."])
        block = board.get_block(4, 6)
        self.assertEqual(block, ["95.", "1.4", "2.."])

    def test_simple_set(self):
        board = sudoku_solver.Board()
        board.set_initial(board_1)
        board.set_cell(5, 7, '6')
        row = board.get_row(5)
        self.assertEqual(row, ".89...26.")

    def test_possibilities(self):
        board = sudoku_solver.Board()
        board.set_initial(board_1)
        p = board.get_possibilities(1, 4)
        self.assertEqual(p, {'1', '4', '5'})

    def test_all_possibilities(self):
        board = sudoku_solver.Board()
        board.set_initial(board_1)
        p = board.get_all_possibilities()
        self.assertEqual(p[1][4], {'1', '4', '5'})

    def test_unique_cell(self):
        board = sudoku_solver.Board()
        board.set_initial(board_1)
        solving_steps = [
            (5, 7, '6'),
            (4, 7, '8'),
            (4, 5, '9'),
            (2, 5, '1'),
            (2, 3, '9'),
            (2, 7, '2'),
            (6, 5, '4'),
            (0, 5, '5'),
            (1, 4, '4')
        ]
        for x, y, v in solving_steps:
            cell = board.get_unique_cell()
            self.assertEqual(cell, (x, y))
            board.set_cell(x, y, v)

    def test_solve(self):
        board = sudoku_solver.Board()
        board.set_initial(board_2)
        b = board.solve()
        self.assertEqual(b, solution_2)

        board = sudoku_solver.Board()
        board.set_initial(board_1)
        b = board.solve()
        self.assertEqual(b, solution_1)

        board = sudoku_solver.Board()
        board.set_initial(board_3)
        b = board.solve()
        self.assertEqual(b, empty)


if __name__ == '__main__':
    unittest.main()