예제 #1
0
 def testSinglePartition(self):
     g = RectangleGridPuzzle(3, 4, 'testSinglePartition')
     Ishape3Vert = MultiBlock([(0, 0), (0, 1), (0, 2)], 'Ishape3Vert')
     Ishape2Vert = MultiBlock([(0, 0), (0, 1)], 'Ishape2Vert')
     #Ishape3Vert = MultiBlock([(0, 0), (0, 1), (0, 2)], 'Ishape3Vert')
     g.inner_grid[1, 2].set_rule_shape(Ishape2Vert)
     g.inner_grid[1, 1].set_rule_shape(Ishape3Vert)
     g.lower_left().is_entrance = True
     g.upper_right().is_exit = True
     g.generate_paths()
     g.load_paths()
     g.solve()
     for p in g.partitions:
         print('Real Partition', p)
예제 #2
0
    def testRotationShapes(self):
        ''' Put a rotatable TshapeUp in a 3x4 Grid (2x3 Squares) with 2 Singles.
            SS
            SS     T
            SS    TTT
            It would not fit normally, but if rotated on it's side it could        '''

        g = RectangleGridPuzzle(4, 5, 'testRotationShapes')
        '''  X
            XXX '''
        TshapeUp = MultiBlock([(0, 0), (1, 0), (2, 0), (1, 1)],
                              name='TshapeUp',
                              can_rotate=True)
        TshapeDown = MultiBlock([(0, 1), (1, 1), (2, 1), (1, 0)],
                                'TshapeDown',
                                can_rotate=False)
        #         Single0 = MultiBlock([(0, 1)], 'Single0')
        #         Single1 = MultiBlock([(0, 2)], 'Single1')
        ''' X
            X'''
        IshapeHoriz2 = MultiBlock([(0, 0), (1, 0)])
        #Ishape3Vert = MultiBlock([(0, 0), (0, 1), (0, 2)], 'Ishape3Vert')

        g.inner_grid[2, 3].set_rule_shape(TshapeUp)
        g.inner_grid[1, 1].set_rule_shape(TshapeDown)

        g.inner_grid[0, 3].set_rule_shape(IshapeHoriz2)

        g.lower_left().is_entrance = True
        g.upper_right().is_exit = True
        g.generate_paths()
        g.load_paths()
        g.solve()

        expected_solutions = [[(0, 0), (0, 1), (1, 1), (1, 2), (1, 3), (0, 3),
                               (0, 4), (1, 4), (2, 4), (3, 4)],
                              [(0, 0), (1, 0), (2, 0), (3, 0), (3, 1), (2, 1),
                               (2, 2), (2, 3), (3, 3), (3, 4)]]
        expected_solutions = set(frozenset(p) for p in expected_solutions)
        #print('expected_solutions:',len(expected_solutions))
        actual_solutions = set(frozenset(p) for p in g.solutions)
        missing_solutions = expected_solutions - actual_solutions
        extra_solutions = actual_solutions - expected_solutions
        self.assertTrue(
            len(missing_solutions) == 0,
            'Missing solutions:' + ','.join(str(s) for s in missing_solutions))
        self.assertTrue(
            len(extra_solutions) == 0,
            'Extra solutions:' + ','.join(str(s) for s in extra_solutions))
예제 #3
0
    def testTreehouse0(self):

        # 4x4 Grid with a 3-block "I" shape in the center and one on the left
        g = RectangleGridPuzzle(6, 6, 'testTreehouse0')
        Ishape2Vert = MultiBlock([(0, 0), (0, 1)], 'Ishape2Vert')
        '''   X
                XXX'''
        LshapeUpRight = MultiBlock([(0, 0), (1, 0), (2, 0), (2, 1)],
                                   name='LshapeUpRight',
                                   can_rotate=True)
        ''' X  
                XXX'''
        LshapeUpLeft = MultiBlock([(0, 0), (1, 0), (2, 0), (0, 1)],
                                  name='LshapeUpLeft',
                                  can_rotate=True)

        g.inner_grid[3, 0].set_rule_shape(Ishape2Vert)
        g.inner_grid[1, 1].set_rule_shape(LshapeUpRight)
        g.inner_grid[3, 2].set_rule_shape(LshapeUpLeft)

        g.inner_grid[4, 0].sun_color = 'purple'
        g.inner_grid[0, 3].sun_color = 'purple'

        g.inner_grid[4, 2].sun_color = 'green'
        g.inner_grid[1, 4].sun_color = 'green'

        g[2, 0].is_entrance = True
        g[3, 0].is_entrance = True

        g[2, 5].is_exit = True
        g[3, 5].is_exit = True

        g.finalize()

        # These took forever to generate. Think carefully before overwriting...
        overwrite_treehouse_paths = False
        g.generate_paths(overwrite_treehouse_paths)
        g.load_paths()
        g.solve(break_on_first=True)
        print('g.solutions', g.solutions)
        #exp_sols=[[(0,0), (0,1), (0,2), (0,3), (1,3), (1,2), (1,1), (1,0), (2,0), (2,1), (2,2), (2,3), (3,3)], [(0,0), (0,1), (0,2), (0,3), (1,3), (2,3), (2,2), (2,1), (2,0), (3,0), (3,1), (3,2), (3,3)], [(0,0), (1,0), (1,1), (1,2), (1,3), (2,3), (2,2), (2,1), (2,0), (3,0), (3,1), (3,2), (3,3)], [(0,0), (1,0), (2,0), (2,1), (2,2), (2,3), (3,3)]]
        #exp_sols=set(frozenset(p) for p in exp_sols)

        first_solution = g.solutions[0]
        self.assertIsNotNone(first_solution)
예제 #4
0
    def test2Ishapes(self):
        '''c d e f
            m n o
           8 9 a b
            j k l
           4 5 6 7
            g h i
           0 1 2 3'''
        # 4x4 Grid with a 3-block "I" shape in the center and one on the left
        g = RectangleGridPuzzle(4, 4, 'Ishape3test')
        Ishape3_1 = MultiBlock([(0, 0), (0, 1), (0, 2)], 'Ishape3_1')
        Ishape3_2 = MultiBlock([(0, 0), (0, 1), (0, 2)], 'Ishape3_2')

        g.inner_grid[1, 1].set_rule_shape(Ishape3_1)
        g.inner_grid[0, 0].set_rule_shape(Ishape3_2)
        g.lower_left().is_entrance = True
        g.upper_right().is_exit = True
        g.finalize()
        g.generate_paths()
        g.load_paths()
        g.solve()
        print('g.solutions', g.solutions)
        expected_solutions = [[(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (1, 2),
                               (1, 1), (1, 0), (2, 0), (2, 1), (2, 2), (2, 3),
                               (3, 3)],
                              [(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (2, 3),
                               (2, 2), (2, 1), (2, 0), (3, 0), (3, 1), (3, 2),
                               (3, 3)],
                              [(0, 0), (1, 0), (1, 1), (1, 2), (1, 3), (2, 3),
                               (2, 2), (2, 1), (2, 0), (3, 0), (3, 1), (3, 2),
                               (3, 3)],
                              [(0, 0), (1, 0), (2, 0), (2, 1), (2, 2), (2, 3),
                               (3, 3)]]
        expected_solutions = set(frozenset(p) for p in expected_solutions)
        #print('expected_solutions:',len(expected_solutions))
        actual_sols = set(frozenset(p) for p in g.solutions)
        missing_solutions = expected_solutions - actual_sols
        extra_solutions = actual_sols - expected_solutions
        self.assertTrue(
            len(missing_solutions) == 0,
            'Missing solutions:' + ','.join(str(s) for s in missing_solutions))
        self.assertTrue(
            len(extra_solutions) == 0,
            'Extra solutions:' + ','.join(str(s) for s in extra_solutions))
        self.assertEqual(len(g.solutions), 4, g.solutions)
예제 #5
0
    def testRuleShapeRendering(self):
        ''' Put 3 Tshapes in a 5x5 Grid to demo rules_shape rendering.'''

        g = RectangleGridPuzzle(5, 5, 'testRuleShapeRendering')

        TshapeDown = MultiBlock([(0, 1), (1, 1), (2, 1), (1, 0)],
                                'TshapeDown',
                                can_rotate=False)
        TshapeRight = MultiBlock([(0, 0), (0, 1), (0, 2), (1, 1)],
                                 'TshapeRight')
        TshapeLeft = MultiBlock([(0, 1), (1, 0), (1, 1), (1, 2)], 'TshapeLeft')
        #Ishape3Vert = MultiBlock([(0, 0), (0, 1), (0, 2)], 'Ishape3Vert')

        g.inner_grid[1, 3].set_rule_shape(TshapeDown)
        g.inner_grid[0, 0].set_rule_shape(TshapeRight)
        g.inner_grid[3, 1].set_rule_shape(TshapeLeft)

        g.lower_left().is_entrance = True
        g.upper_right().is_exit = True
        g.render()
        g.generate_paths()
        g.load_paths()
        g.solve()

        expected_solutions = [[(0, 0), (1, 0), (1, 1), (2, 1), (2, 2), (3, 2),
                               (3, 1), (4, 1), (4, 2), (4, 3), (4, 4)]]
        expected_solutions = set(frozenset(p) for p in expected_solutions)

        print('expected_solutions:', expected_solutions)
        actual_solutions = set(frozenset(p) for p in g.solutions)
        print('actual_solutions', actual_solutions)
        missing_solutions = expected_solutions - actual_solutions
        extra_solutions = actual_solutions - expected_solutions
        self.assertTrue(
            len(missing_solutions) == 0,
            'Missing solutions:' + ','.join(str(s) for s in missing_solutions))
        self.assertTrue(
            len(extra_solutions) == 0,
            'Extra solutions:' + ','.join(str(s) for s in extra_solutions))
예제 #6
0
    def testMultipleShapesInPartition(self):
        g = RectangleGridPuzzle(5, 5, 'MultipleShapesInPartition')
        '''  X
            XXX '''
        TshapeUp = MultiBlock([(0, 0), (1, 0), (2, 0), (1, 1)], 'TshapeUp')
        ''' XXX
             X  '''
        TshapeDown = MultiBlock([(0, 1), (1, 1), (2, 1), (1, 0)], 'TshapeDown')
        '''  X
            XX 
             X'''
        TshapeLeft = MultiBlock([(0, 1), (1, 0), (1, 1), (1, 2)], 'TshapeLeft')
        '''  X
             XX 
             X    '''
        TshapeRight = MultiBlock([(0, 0), (0, 1), (0, 2), (1, 1)],
                                 'TshapeRight')
        Single0 = MultiBlock([(0, 1)], 'Single0')
        Single1 = MultiBlock([(0, 2)], 'Single1')
        Ishape3Vert = MultiBlock([(0, 0), (0, 1), (0, 2)], 'Ishape3Vert')

        # Alternate arrangement
        #         [(0,0), (0,1), (1,1), (1,2), (2,2), (2,3), (1,3), (1,4), (2,4), (3,4), (4,4)]: # MultipleShapes soution
        #         g.inner_grid[0, 0].set_rule_shape(TshapeUp)
        #         g.inner_grid[1, 3].set_rule_shape(TshapeDown)
        #         g.inner_grid[3, 1].set_rule_shape(TshapeLeft)

        g.inner_grid[0, 0].set_rule_shape(TshapeRight)
        g.inner_grid[1, 3].set_rule_shape(TshapeDown)
        g.inner_grid[3, 1].set_rule_shape(TshapeLeft)
        g.lower_left().is_entrance = True
        g.upper_right().is_exit = True
        g.generate_paths()
        g.load_paths()
        g.solve()
        self.assertEqual(
            len(g.solutions), 1, 'Wrong number of solutions: %s' %
            ('\n'.join([''.join(str(s)) for s in g.solutions])))
        actual_solution = g.solutions[0]

        expected_solution = [(0, 0), (1, 0), (1, 1), (2, 1), (2, 2), (3, 2),
                             (3, 1), (4, 1), (4, 2), (4, 3), (4, 4)]

        self.assertEqual(list(actual_solution), expected_solution,
                         'Unexpected solution:\n%s' % (str(actual_solution)))
예제 #7
0
    def has_shape_violation(self):

        if self.shape_violation is not None:
            raise Exception('Violation already checked')
            return self.shape_violation
        self.solution_shapes = []
        rule_shapes = self.get_rule_shapes()
        #print('rule_shapes', rule_shapes)

        if self.total_rule_shape_points != len(self):
            self.shape_violation = True
            return True

        partition_multiblock = MultiBlock(self.keys(),
                                          name='partition_multiblock',
                                          auto_shift_Q1=False)

        self.shape_violation = not self.can_be_composed_of(
            rule_shapes, partition_multiblock, 0)
        return self.shape_violation
예제 #8
0
    def can_be_composed_of(self, rule_shapes, partition_multiblock,
                           depth_counter):
        cur_multiblock = rule_shapes[depth_counter]
        t = '\t' * depth_counter
        print(t, 'partition_multiblock', partition_multiblock)
        print(t, 'cur_multiblock', cur_multiblock)
        found_solution = False

        for cur_shape in cur_multiblock.rotations:

            print('    cur_shape', cur_shape)
            # Is the shape bigger than the partition?
            if not partition_multiblock.could_contain(cur_shape):
                print('            %s can'
                      't contain %s', partition_multiblock, cur_shape)
                continue

            # Put the shape in the lower-left corner
            cur_shape.set_offset(partition_multiblock.offset_point())
            #print('    cur_shape.offset_point', cur_shape.offset_point())

            max_shift_point = partition_multiblock.upper_right(
            ) - cur_shape.upper_right()
            #print('    max_shift_point', max_shift_point)

            # TODO: Change to MultiBlock yield?
            for y in range(max_shift_point.y + 1):
                for x in range(max_shift_point.x + 1):

                    cur_shape.set_offset(Point((x, y)))

                    abs_points = cur_shape.get_absolute_point_set()
                    #print('        abs_points', abs_points)

                    outside_points = abs_points - partition_multiblock
                    if outside_points:
                        #print('            !!outside_points', outside_points)
                        continue
                    # Return all the points in the partition that are left
                    remaining_partition_points = partition_multiblock - abs_points
                    #print('        remaining_partition_points', remaining_partition_points)

                    # Haven't filled all our points yet...
                    if remaining_partition_points:
                        if depth_counter == len(rule_shapes) - 1:
                            #print( '            still points')
                            raise Exception('still points')
                        else:
                            #print('            keep on truckin...')
                            new_partition = MultiBlock(
                                remaining_partition_points,
                                auto_shift_Q1=False)
                            #print('            new_partition', new_partition)
                            found_solution = self.can_be_composed_of(
                                rule_shapes, new_partition, depth_counter + 1)
                    # Filled all our points, are we at the end?
                    else:
                        if depth_counter == len(rule_shapes) - 1:
                            found_solution = True

                        else:
                            # Should not happen till we start implementing SubtractionSquare
                            raise Exception('Filled too soon')
                            return False
                    if found_solution:
                        print('\t' * (depth_counter) + 'FOUND SOLUTION!!',
                              cur_shape)
                        sol_pts = cur_shape.get_absolute_point_set()
                        self.solution_shapes.append(sol_pts)
                        return True
        return False