예제 #1
0
    def setUp(self):
        self.test_solver = solver.Solver()
        self.field1 = TriangleField([[1], [1, 0, 2], [3, 0, 3, 0, 2]])
        self.field2 = TriangleField([[1], [1, 0, 2], [1, 0, 3, 0, 2],
                                     [3, 0, 0, 0, 4, 0, 4]])
        self.field3 = TriangleField([[1], [1, 0, 2]])

        self.graph = Graph(directed=False)
        self.graph.add_edge('a', 'b')
        self.graph.add_edge('a', 'c')
        self.graph.add_edge('c', 'b')
        self.graph.add_edge('b', 'd')
예제 #2
0
class TriangleFieldTest(unittest.TestCase):
    def setUp(self):
        self.field = TriangleField([[1], [1, 0, 2], [1, 0, 3, 0, 2],
                                    [3, 0, 0, 0, 4, 0, 4]])
        self.simple_field = TriangleField([[1], [1, 0, 2], [3, 0, 3, 0, 2]])

    def test_get_neighbours(self):
        expected = {(1, 1)}
        self.assert_neighbours(expected, (0, 0))

        expected = {(0, 0), (1, 2), (1, 0)}
        self.assert_neighbours(expected, (1, 1))

        expected = {(3, 1)}
        self.assert_neighbours(expected, (3, 0))

        expected = {(3, 5)}
        self.assert_neighbours(expected, (3, 6))

        expected = {(2, 1), (3, 3), (2, 3)}
        self.assert_neighbours(expected, (2, 2))

    def assert_neighbours(self, expected, position):
        actual = set(self.field.get_neighbours(*position))
        self.assertSetEqual(expected, actual)

    def test_check_field_when_ok(self):
        assert (self.field.field == TriangleField(self.field.field).field)

    def test_init_when_wrong(self):
        field = [[0, 0], [0, 0, 0], [0, 0, 0, 0, 0, 0]]

        self.assertRaises(ValueError, TriangleField, field)
        self.assertRaises(ValueError, TriangleField, None)

    def test_index_checker(self):
        assert not self.field.is_valid(0, 1)
        assert not self.field.is_valid(5, 0)
        assert not self.field.is_valid(0, 3)

    def test_get_targets(self):
        expected = dict(vertices={(0, 0), (1, 0), (2, 0), (1, 2), (2, 4),
                                  (2, 2)},
                        pairs={
                            frozenset({(0, 0), (1, 0)}),
                            frozenset({(2, 2), (2, 0)}),
                            frozenset({(1, 2), (2, 4)})
                        })
        actual = self.simple_field.get_targets()

        self.assertDictEqual(expected, actual)
예제 #3
0
    def get_field_from_solution(self, field: TriangleField,
                                solution: List[list]) -> List[list]:
        result = TriangleField(Generator.generate_triangle_field(field.size))
        for pair in field.get_targets()['pairs']:
            start, end = tuple(pair)
            number = field[start]

            while start != end:
                for edge in solution:
                    if start in edge:
                        result[start] = number
                        start = self.opposite(start, edge)

            result[end] = number

        return result.field
예제 #4
0
def prepare_data_solve(field: TriangleField) -> str:
    solver = Solver()

    solutions = set(
        TriangleField(solver.get_field_from_solution(field, solution))
        for solution in solver.solve(field))

    if len(solutions) > 0:
        result = f'Count Solutions = {len(solutions)}\n'
        return result + str(solutions.pop())
예제 #5
0
    def solve(self, instance: TriangleField):
        graph = instance.create_graph()
        targets = instance.get_targets()
        vertices = Segment(graph.vertices())
        edges = graph.edges()
        root = Node(edges[0], {v: v for v in vertices.active}, 1)

        def get_node(node_edge: List[tuple],
                     neighbors: dict,
                     name: int) -> Node:
            if node_edge:
                return Node(node_edge, neighbors, name)

            return Node.second_link

        nodes = [root]
        while edges:
            edge = edges.pop(0)
            next_edge = edges[0] if edges else None
            self.update_vertices(vertices, edge, edges)
            new_nodes = []

            for node in nodes:
                links = []
                if self.is_first_inconsistent(node, targets, vertices):
                    links.append(Node.first_second)
                else:
                    new_neighbor = self.update_main_path(
                        node.neighbor, vertices.active)
                    links.append(get_node(next_edge, new_neighbor, 0))
                if self.is_second_inconsistent(node, targets, vertices):
                    links.append(Node.first_second)
                else:
                    new_neighbor = self.update_main_path(
                        self.update_neighbors(node), vertices.active)
                    links.append(get_node(next_edge, new_neighbor, 1))

                new_nodes.extend(n for n in links if not self.is_link(n))
                node.add_link(*links)
            nodes = new_nodes

        return self.create_solutions(root)
예제 #6
0
    def create(self) -> List[List]:
        while True:
            pair = self.try_get_path_start()

            if pair is not None:
                self.add_path(*pair)
            elif (self.covered_cells >= self.cells_amount
                  and self.number <= MAX_NUMBER):
                return self.get_gaming_field()
            else:
                field = self.generate_triangle_field(self.field.size)
                self.__init__(TriangleField(field))
예제 #7
0
    def __init__(self, field, parent):
        super().__init__(parent)
        self.solver = Solver()
        self._field = TriangleField(field)
        self.board_size = self._field.size
        self.cells = []
        self.right_cell = 0
        self.cell_length = 50
        self.init_ui()
        self._current_number = 1
        self.targets = self._field.get_targets()['vertices']
        self.solutions = list(
            set(
                TriangleField(
                    self.solver.get_field_from_solution(self._field, solution))
                for solution in self.solver.solve(self._field)))
        self.when_solved = lambda x: None

        for cell in self.cells:
            if cell.position in self.targets:
                cell.is_static = True
                self.right_cell += 1
예제 #8
0
 def setUp(self):
     self.field = TriangleField([[1], [1, 0, 2], [1, 0, 3, 0, 2],
                                 [3, 0, 0, 0, 4, 0, 4]])
     self.simple_field = TriangleField([[1], [1, 0, 2], [3, 0, 3, 0, 2]])
예제 #9
0
 def test_check_field_when_ok(self):
     assert (self.field.field == TriangleField(self.field.field).field)
예제 #10
0
    def generate_field(size: int = 3) -> List[List]:
        size = max(DEFAULT_FIELD_HEIGHT, size)
        field = Generator.generate_triangle_field(size)
        constructor = Generator(TriangleField(field))

        return constructor.create()
예제 #11
0
 def setUp(self):
     field = generator.Generator.generate_triangle_field(5)
     self.constructor = Generator(TriangleField(field))
     self.field = TriangleField(field)
예제 #12
0
def read_file(name: str):
    filename = Reader.search_file(name)
    reader = Reader(filename)
    field = TriangleField(reader.get_field_from_file(filename))
    return field
예제 #13
0
def prepare_data_generate(size: int):
    field = TriangleField(generator.Generator.generate_field(size))
    return field
예제 #14
0
class TriangleBoard(QWidget):
    def __init__(self, field, parent):
        super().__init__(parent)
        self.solver = Solver()
        self._field = TriangleField(field)
        self.board_size = self._field.size
        self.cells = []
        self.right_cell = 0
        self.cell_length = 50
        self.init_ui()
        self._current_number = 1
        self.targets = self._field.get_targets()['vertices']
        self.solutions = list(
            set(
                TriangleField(
                    self.solver.get_field_from_solution(self._field, solution))
                for solution in self.solver.solve(self._field)))
        self.when_solved = lambda x: None

        for cell in self.cells:
            if cell.position in self.targets:
                cell.is_static = True
                self.right_cell += 1

    def init_ui(self):
        vbox = QVBoxLayout(self)
        vbox.setAlignment(Qt.AlignCenter)

        for i, row in enumerate(self._field):
            hbox = QHBoxLayout(self)
            hbox.setAlignment(Qt.AlignCenter)

            for j, number in enumerate(row):
                cell = FieldButton((i, j), self, self.cell_length,
                                   int(self.cell_length * 2 / 3) if
                                   (j != 0 and j != len(row) - 1)
                                   and j % 2 != 0 else self.cell_length)
                cell.number = number
                cell.on_mouse_click = functools.partial(self.cell_click, cell)
                self.cells.append(cell)
                hbox.addWidget(cell, 0, Qt.AlignCenter)

            vbox.addLayout(hbox)
        self.setLayout(vbox)

    def cell_click(self, cell):
        if cell.position not in self.targets:
            condition = any(cell.number == path[cell.position]
                            for path in self.solutions)
            if condition and self._field[cell.position] != cell.number:
                self.right_cell += 1
            elif any(self._field[cell.position] == path[cell.position]
                     for path in self.solutions) and not condition:
                self.right_cell -= 1

            self._field[cell.position] = cell.number
            if self.check_solution():
                self.when_solved('Головоломка решена!')

    def clear(self):
        for cell in self.cells:
            if cell.position not in self.targets:
                cell.number = 0
                self._field[cell.position] = 0

    def check_solution(self):
        return self.right_cell == self._field.count_cells

    @property
    def field(self):
        return self._field

    @field.setter
    def field(self, field):
        for i, row in enumerate(field):
            for j, cell in enumerate(row):
                self._field[i, j] = cell
        for cell in self.cells:
            cell.number = self._field[cell.position]

    @property
    def current_number(self):
        return self._current_number

    @current_number.setter
    def current_number(self, value: int):
        if 0 < value < MAX_COLORS:
            self._current_number = value