Ejemplo n.º 1
0
    def problem(cls, p: Problem) -> Problem:
        if p.is_line_symmetry_row and p.is_line_symmetry_col:
            q: Problem = p.copy()
            q.train_x_list = [cls.case_row_col(c) for c in p.train_x_list]
            q.test_x_list = [cls.case_row_col(c) for c in p.test_x_list]
        elif p.is_line_symmetry_row:
            q: Problem = p.copy()
            q.train_x_list = [cls.case_row(c) for c in p.train_x_list]
            q.test_x_list = [cls.case_row(c) for c in p.test_x_list]
        elif p.is_line_symmetry_col:
            q: Problem = p.copy()
            q.train_x_list = [cls.case_col(c) for c in p.train_x_list]
            q.test_x_list = [cls.case_col(c) for c in p.test_x_list]
        else:
            raise AssertionError

        # check if some more to do
        res = 0
        c: Case
        for c in q.train_x_list:
            if c.color_delete is not None:
                res += (c.repr_values() == c.color_delete).sum()
        for c in q.test_x_list:
            if c.color_delete is not None:
                res += (c.repr_values() == c.color_delete).sum()
        if res == 0:
            return q
        else:
            return FillSomewhere.problem(q)
Ejemplo n.º 2
0
def hand_pick(p: Problem) -> List[Problem]:
    q0: Problem = p.copy()
    q0.train_x_list = [hand_pick_case(c, 0) for c in p.train_x_list]
    q0.test_x_list = [hand_pick_case(c, 0) for c in p.test_x_list]
    q1: Problem = p.copy()
    q1.train_x_list = [hand_pick_case(c, 1) for c in p.train_x_list]
    q1.test_x_list = [hand_pick_case(c, 1) for c in p.test_x_list]
    q2: Problem = p.copy()
    q2.train_x_list = [hand_pick_case(c, 2) for c in p.train_x_list]
    q2.test_x_list = [hand_pick_case(c, 2) for c in p.test_x_list]

    return [q0, q1, q2]
Ejemplo n.º 3
0
 def problem(cls, p: Problem, shadow_type: str) -> Problem:
     if shadow_type == "problem_max":
         max_color = (sum([c.color_count() for c in p.train_x_list])).argmax()
         # print(max_color)
         q: Problem = p.copy()
         q.train_x_list = [cls.case(c, shadow_type, max_color) for c in p.train_x_list]
         q.test_x_list = [cls.case(c, shadow_type, max_color) for c in p.test_x_list]
     else:
         q: Problem = p.copy()
         q.train_x_list = [cls.case(c, shadow_type) for c in p.train_x_list]
         q.test_x_list = [cls.case(c, shadow_type) for c in p.test_x_list]
     return q
    def problem(cls, p: Problem) -> Problem:
        # fast check
        if p.history == ["color"]:
            color = True
        else:
            color = False
        for c_x, c_y in zip(p.train_x_list, p.train_y_list):
            flag_keep, flag_color = cls.case_assert(c_x, c_y, color)
            assert flag_keep
        # assign flag
        train_list = []
        test_list = []
        for c_x, c_y in zip(p.train_x_list, p.train_y_list):
            y_list = cls.case_create_flag(c_x, c_y, flag_color)
            c_ax: AbstractCase = AbstractCase(c_x)
            c_ax.y_list = y_list
            train_list.append(c_ax)
        for c_x in p.test_x_list:
            c_ax: AbstractCase = AbstractCase(c_x)
            test_list.append(c_ax)

        cls.auto_solve(train_list, test_list)

        q: Problem = p.copy()
        q.train_x_list = [
            cls.case_fit(c, ca) for c, ca in zip(p.train_x_list, train_list)
        ]
        q.test_x_list = [
            cls.case_fit(c, ca) for c, ca in zip(p.test_x_list, test_list)
        ]
        return q
Ejemplo n.º 5
0
    def problem(cls, p: Problem) -> Problem:
        # fast check
        for c_x, c_y in zip(p.train_x_list, p.train_y_list):
            assert cls.case_assert(c_x, c_y)
        # assign flag
        train_list = []
        test_list = []
        for c_x, c_y in zip(p.train_x_list, p.train_y_list):
            y_list = cls.case_create_flag(c_x, c_y)
            c_ax: AbstractCase = AbstractCase(c_x)
            c_ax.y_list = y_list
            train_list.append(c_ax)
        for c_x in p.test_x_list:
            c_ax: AbstractCase = AbstractCase(c_x)
            test_list.append(c_ax)

        cls.auto_solve(train_list, test_list)

        q: Problem = p.copy()
        q.train_x_list = [
            cls.case_fit(c, ca) for c, ca in zip(p.train_x_list, train_list)
        ]
        q.test_x_list = [
            cls.case_fit(c, ca) for c, ca in zip(p.test_x_list, test_list)
        ]
        return q
    def problem(cls, p: Problem) -> Problem:

        q = p.copy()
        q.train_x_list = []
        q.train_y_list = []
        q.test_x_list = []

        # check if fusion-able
        c_x: Case
        c_y: Case
        c_list = []
        for c_x, c_y in zip(p.train_x_list, p.train_y_list):
            x_arr = c_x.repr_values()
            y_arr = c_y.repr_values()
            new_y_arr, x0, x1, y0, y1, c = fusion_arr_train(x_arr, y_arr)
            # print(new_y_arr)
            # print(new_y_arr, x0, x1, y0, y1, c)
            q.train_x_list.append(cls.case_x(c_x, x0, x1, y0, y1))
            q.train_y_list.append(cls.case_y(c_y, new_y_arr, x0, x1, y0, y1))
            c_list.append(c)

        for c_x in p.test_x_list:
            x_arr = c_x.repr_values()
            c_suggest = c_list[0]
            x0, x1, y0, y1, c = fusion_arr_test(x_arr, c_suggest)
            q.test_x_list.append(cls.case_x(c_x, x0, x1, y0, y1))

        # pre_solve again
        is_pattern.set_is_pattern(q)
        is_periodic.set_is_periodic_row(q)
        is_periodic.set_is_periodic_col(q)
        is_symmetry.set_is_line_symmetry_row(q)
        is_symmetry.set_is_line_symmetry_col(q)
        return q
Ejemplo n.º 7
0
 def problem(cls, p: Problem) -> Problem:
     if p.is_line_symmetry_row and p.is_line_symmetry_col:
         q: Problem = p.copy()
         q.train_x_list = [cls.case_row_col(c) for c in p.train_x_list]
         q.test_x_list = [cls.case_row_col(c) for c in p.test_x_list]
     elif p.is_line_symmetry_row:
         q: Problem = p.copy()
         q.train_x_list = [cls.case_row(c) for c in p.train_x_list]
         q.test_x_list = [cls.case_row(c) for c in p.test_x_list]
     elif p.is_line_symmetry_col:
         q: Problem = p.copy()
         q.train_x_list = [cls.case_col(c) for c in p.train_x_list]
         q.test_x_list = [cls.case_col(c) for c in p.test_x_list]
     else:
         raise AssertionError
     return q
 def problem(cls, p: Problem) -> Problem:
     flag, m_row, m_col = is_multiple(p)
     assert flag
     q: Problem = p.copy()
     q.train_x_list = [cls.case(c, m_row, m_col) for c in p.train_x_list]
     q.test_x_list = [cls.case(c, m_row, m_col) for c in p.test_x_list]
     return q
 def problem(cls, p: Problem) -> Problem:
     assert is_same(p)
     if p.is_periodic_row and p.is_periodic_col:
         q: Problem = p.copy()
         q.train_x_list = [cls.case_row_col(c) for c in p.train_x_list]
         q.test_x_list = [cls.case_row_col(c) for c in p.test_x_list]
     elif p.is_periodic_row:
         q: Problem = p.copy()
         q.train_x_list = [cls.case_row(c) for c in p.train_x_list]
         q.test_x_list = [cls.case_row(c) for c in p.test_x_list]
     elif p.is_periodic_col:
         q: Problem = p.copy()
         q.train_x_list = [cls.case_col(c) for c in p.train_x_list]
         q.test_x_list = [cls.case_col(c) for c in p.test_x_list]
     else:
         raise AssertionError
     return q
def set_shape(p: Problem, new_shape: Tuple[int, int]) -> Problem:
    q: Problem
    q = p.copy()
    q.train_x_list = [
        attr_case.set_shape(x, new_shape) for x in p.train_x_list
    ]
    q.test_x_list = [attr_case.set_shape(x, new_shape) for x in p.test_x_list]
    q.train_y_list = [x for x in p.train_y_list]
    return q
    def problem(cls, p: Problem) -> Problem:
        assert p.is_pattern
        pattern_arr = get_pattern_arr(p)

        q: Problem = p.copy()
        q.train_x_list = []
        q.test_x_list = []

        q.train_x_list = [cls.case(c_x, pattern_arr) for c_x in p.train_x_list]
        q.test_x_list = [cls.case(c_x, pattern_arr) for c_x in p.test_x_list]
        return q
def duplicate(p: Problem) -> Problem:

    flag, m_row, m_col = is_multiple(p)
    flag_n = False

    if not flag:
        flag, nc_row, nc_col = is_constant(p)
        flag_n = True

    assert flag

    q: Problem
    q = p.copy()
    q.train_x_list = []
    q.test_x_list = []
    c_x: Case
    c_x_new: Case
    for c_x in p.train_x_list:
        c_x_new = c_x.copy()
        base_values = c_x.repr_values()
        n_row, n_col = base_values.shape
        if flag_n:
            assert nc_row % n_row == 0
            assert nc_col % n_col == 0
            m_row = nc_row // n_row
            m_col = nc_col // n_col
        c_x_new.shape = m_row * n_row, m_col * n_col
        new_values = np.zeros((m_row * n_row, m_col * n_col), dtype=np.int)
        for i in range(m_row):
            for j in range(m_col):
                new_values[i * n_row:(i + 1) * n_row,
                           j * n_col:(j + 1) * n_col] = base_values
        c_x_new.matter_list = [
            Matter(new_values, background_color=c_x.background_color, new=True)
        ]
        q.train_x_list.append(c_x_new)

    for c_x in p.test_x_list:
        c_x_new = c_x.copy()
        base_values = c_x.repr_values()
        n_row, n_col = base_values.shape
        c_x_new.shape = m_row * n_row, m_col * n_col
        new_values = np.zeros((m_row * n_row, m_col * n_col), dtype=np.int)
        for i in range(m_row):
            for j in range(m_col):
                new_values[i * n_row:(i + 1) * n_row,
                           j * n_col:(j + 1) * n_col] = base_values
        c_x_new.matter_list = [
            Matter(new_values, background_color=c_x.background_color, new=True)
        ]
        q.test_x_list.append(c_x_new)

    return q
def set_color_add(p: Problem, color_add: int) -> Problem:
    q: Problem
    q = p.copy()
    q.color_add = color_add
    q.train_x_list = [
        attr_case.set_color_add(x, color_add) for x in p.train_x_list
    ]
    q.test_x_list = [
        attr_case.set_color_add(x, color_add) for x in p.test_x_list
    ]
    q.train_y_list = [x for x in p.train_y_list]
    return q
Ejemplo n.º 14
0
 def problem(cls,
             p: Problem,
             allow_diagonal: bool = False,
             boundary_none: bool = False) -> Problem:
     q: Problem = p.copy()
     q.train_x_list = [
         cls.case(c, allow_diagonal, boundary_none) for c in p.train_x_list
     ]
     q.test_x_list = [
         cls.case(c, allow_diagonal, boundary_none) for c in p.test_x_list
     ]
     return q
Ejemplo n.º 15
0
 def problem(cls, p: Problem) -> Problem:
     q: Problem = p.copy()
     q.train_x_list = [cls.case(c) for c in p.train_x_list]
     q.test_x_list = [cls.case(c) for c in p.test_x_list]
     background_colors = []
     for c in q.train_x_list:
         background_colors.append(c.background_color)
     for c in q.test_x_list:
         background_colors.append(c.background_color)
     if len(set(background_colors)) == 1:
         assert background_colors[0] != 0
         q.background_color = background_colors[0]
     return q
    def problem(cls, p: Problem) -> Problem:
        assert only_color(p)
        # assert non_background coincide
        q: Problem = p.copy()
        for op in ["<=", "==", ">="]:
            for const in range(1, 10):
                q.train_x_list = [
                    cls.case(c, op, const) for c in p.train_x_list
                ]
                q.test_x_list = [cls.case(c, op, const) for c in p.test_x_list]
                ac, n_train = q.judge()
                if ac == n_train:
                    return q

        raise AssertionError
Ejemplo n.º 17
0
 def problem(cls, p: Problem) -> Problem:
     # color_dict
     color_dict = dict()
     for c_x, c_y in zip(p.train_x_list, p.train_y_list):
         new_dict = cls.case_xy(c_x, c_y)
         # print(new_dict)
         for k in new_dict.keys():
             if k in color_dict.keys():
                 assert color_dict[k] == new_dict[k]
             else:
                 color_dict[k] = new_dict[k]
     # fit
     q: Problem = p.copy()
     q.train_x_list = [cls.case(c, color_dict) for c in p.train_x_list]
     q.test_x_list = [cls.case(c, color_dict) for c in p.test_x_list]
     return q
    def problem(cls, p: Problem) -> Problem:
        c_x: Case
        c_y: Case

        # find rule
        x_arr_list = []
        y_arr_list = []
        for c_x, c_y in zip(p.train_x_list, p.train_y_list):
            assert c_x.background_color == p.background_color
            x_arr_list.append(c_x.repr_values())
            y_arr_list.append(c_y.repr_values())

        rule_33 = find_replace_rule_33_all(x_arr_list, y_arr_list,
                                           p.background_color)

        # fit rule
        q: Problem = p.copy()
        q.train_x_list = []
        q.test_x_list = []
        c_x: Case
        c_x_new: Case
        for c_x in p.train_x_list:
            c_x_new = c_x.copy()
            new_values = fit_replace_rule_33_one_all(c_x.repr_values(),
                                                     rule_33,
                                                     p.background_color)
            c_x_new.matter_list = [
                Matter(new_values,
                       background_color=p.background_color,
                       new=True)
            ]
            q.train_x_list.append(c_x_new)

        for c_x in p.test_x_list:
            c_x_new = c_x.copy()
            new_values = fit_replace_rule_33_one_all(c_x.repr_values(),
                                                     rule_33,
                                                     p.background_color)
            c_x_new.matter_list = [
                Matter(new_values,
                       background_color=p.background_color,
                       new=True)
            ]
            q.test_x_list.append(c_x_new)

        return q
Ejemplo n.º 19
0
 def problem(cls, p: Problem) -> List[Problem]:
     res_list = []
     c: Case
     for c in p.train_y_list:
         q: Problem = p.copy()
         new_values = c.repr_values()
         q.train_x_list = []
         for _ in range(p.len_train):
             new_case = Case(new=True)
             new_case.initialize(new_values)
             q.train_x_list.append(new_case)
         q.test_x_list = []
         for _ in range(p.len_test):
             new_case = Case(new=True)
             new_case.initialize(new_values)
             q.test_x_list.append(new_case)
         res_list.append(q)
     return res_list
def run_map(p: Problem, command: str) -> Problem:
    q: Problem
    # run
    if command == "identity":
        q = p.copy()
        raise DeprecationWarning
    elif command == "color":
        q = MapColor.problem(p)
    elif command == "connect":
        q = MapConnect.problem(p, True)
    elif command == "connect4":
        q = MapConnect.problem(p, False)
    elif command == "color_connect":
        q = MapColorConnect.problem(p, True)
    elif command == "color_connect4":
        q = MapColorConnect.problem(p, False)
    elif command == "divide_row_col":
        q = Divide.problem(p)
    elif command == "multiple_row_col":
        q = Multiple.problem(p)
    elif command == "mesh_2":
        q = SplitMeshTwo.problem(p)
    elif command == "mesh_align":
        q = SplitMeshAlign.problem(p)
    elif command == "mesh_split":
        q = SplitMesh.problem(p)
    elif command == "fusion":
        q = Fusion.problem(p)
    elif command == "map_interior":
        q = MapInterior.problem(p, boundary_none=False)
    elif command == "map_interior_in":
        q = MapInterior.problem(p, boundary_none=True)
    elif command == "map_interior_pierce":
        q = MapInteriorPierce.problem(p,
                                      allow_diagonal=False,
                                      boundary_none=True)
    else:
        raise NotImplementedError

    return q
    def problem(cls, p: Problem) -> Problem:
        q: Problem = p.copy()
        flag, m_row, m_col = is_multiple(p)
        if flag:
            q.train_x_list = [
                cls.case_m(c, m_row, m_col) for c in p.train_x_list
            ]
            q.test_x_list = [
                cls.case_m(c, m_row, m_col) for c in p.test_x_list
            ]
            return q
        flag, n_row, n_col = is_constant(p)
        if flag:
            q.train_x_list = [
                cls.case_n(c, n_row, n_col) for c in p.train_x_list
            ]
            q.test_x_list = [
                cls.case_n(c, n_row, n_col) for c in p.test_x_list
            ]
            return q

        raise AssertionError
Ejemplo n.º 22
0
def fit_replace_rule_33(p: Problem) -> Problem:
    # assert
    case_x: Case
    case_y: Case

    x_arr_list = []
    y_arr_list = []

    for case_x, case_y in zip(p.train_x_list, p.train_y_list):
        # same shape
        x_values = case_x.repr_values()
        y_values = case_y.repr_values()
        assert x_values.shape == y_values.shape

        x_arr_list.append(x_values)
        y_arr_list.append(y_values)

    rule_33 = find_replace_rule_33(x_arr_list, y_arr_list, p.background_color)

    q: Problem
    q = p.copy()
    q.train_x_list = []
    q.test_x_list = []
    c_x: Case
    c_x_new: Case
    for c_x in p.train_x_list:
        c_x_new = c_x.copy()
        new_values = fit_replace_rule_33_one(c_x.repr_values(), rule_33, p.background_color)
        c_x_new.matter_list = [Matter(new_values, background_color=p.background_color, new=True)]
        q.train_x_list.append(c_x_new)

    for c_x in p.test_x_list:
        c_x_new = c_x.copy()
        new_values = fit_replace_rule_33_one(c_x.repr_values(), rule_33, p.background_color)
        c_x_new.matter_list = [Matter(new_values, background_color=p.background_color, new=True)]
        q.test_x_list.append(c_x_new)

    return q
def point_cross(p: Problem) -> Problem:

    res_problem = point_cross_cnt(p)
    op_arr = np.zeros(10, dtype=int)
    for c in range(10):
        c_min = res_problem[c, :].min()
        # keep > delete > cross > row > col
        if res_problem[c, 1] == c_min:
            op_arr[c] = 1
        elif res_problem[c, 0] == c_min:
            op_arr[c] = 0
        elif res_problem[c, 4] == c_min:
            op_arr[c] = 4
        elif res_problem[c, 2] == c_min:
            op_arr[c] = 2
        else:  # res_problem[c, 3] == c_min:
            op_arr[c] = 3

    q: Problem = p.copy()
    q.train_x_list = [point_cross_fit_case(c, op_arr) for c in p.train_x_list]
    q.test_x_list = [point_cross_fit_case(c, op_arr) for c in p.test_x_list]

    return q
 def problem(cls, p: Problem, descending: bool = False) -> Problem:
     q: Problem = p.copy()
     q.train_x_list = [cls.case(c, descending) for c in p.train_x_list]
     q.test_x_list = [cls.case(c, descending) for c in p.test_x_list]
     return q
 def problem(cls, p: Problem) -> Problem:
     q: Problem = p.copy()
     q.train_x_list = [cls.case(c) for c in p.train_x_list]
     q.test_x_list = [cls.case(c) for c in p.test_x_list]
     return q
def solve_rotations(p: Problem) -> Problem:

    case_x: Case
    case_y: Case
    m: Matter

    # assert same length
    case_x = p.train_x_list[0]
    base_len = len(case_x.matter_list)
    for case_x in p.train_x_list:
        assert base_len == len(case_x.matter_list)
    for case_x in p.test_x_list:
        assert base_len == len(case_x.matter_list)

    # search
    for case_x, case_y in zip(p.train_x_list, p.train_y_list):
        # assert same size
        assert case_x.shape == case_y.shape
        assert (case_x.color_count() == case_y.color_count()).min()

        y_repr = case_y.repr_values()
        good_operations = np.ones((base_len, 8), dtype=np.int)
        for i in range(base_len):
            m = case_x.matter_list[i]
            compare = y_repr[m.x0:m.x0 + m.shape[0], m.y0:m.y0 + m.shape[1]]

            if (m.values != compare).sum():
                good_operations[i, 0] = 0
            if not m.is_square():
                good_operations[i, 1] = 0
            elif (rot_arr.transpose(m.values) != compare).sum():
                good_operations[i, 1] = 0
            if (rot_arr.rev_row(m.values) != compare).sum():
                good_operations[i, 2] = 0
            if (rot_arr.rev_col(m.values) != compare).sum():
                good_operations[i, 3] = 0
            if (rot_arr.rot_180(m.values) != compare).sum():
                good_operations[i, 4] = 0
            if not m.is_square():
                good_operations[i, 5] = 0
            elif (rot_arr.rot_rev_180(m.values) != compare).sum():
                good_operations[i, 5] = 0
            if not m.is_square():
                good_operations[i, 6] = 0
            elif (rot_arr.rot_90(m.values) != compare).sum():
                good_operations[i, 6] = 0
            if not m.is_square():
                good_operations[i, 7] = 0
            elif (rot_arr.rot_270(m.values) != compare).sum():
                good_operations[i, 7] = 0
            # some solution exists
            assert good_operations.max(axis=1).min() == 1

    # check shape for test_x
    for case_x in p.test_x_list:
        for i in range(base_len):
            m = case_x.matter_list[i]
            if not m.is_square():
                good_operations[i, 1] = 0
                good_operations[i, 5] = 0
                good_operations[i, 6] = 0
                good_operations[i, 7] = 0

    assert good_operations.max(axis=1).min() == 1

    q: Problem = p.copy()
    q.train_x_list = []
    q.test_x_list = []
    new_case_x: Case
    for case_x in p.train_x_list:
        new_case_x = case_x.copy()
        new_case_x.matter_list = []
        for i in range(base_len):
            m = case_x.matter_list[i]
            ind = good_operations[i].argmax()
            if ind == 0:
                new_case_x.matter_list.append(m.deepcopy())
            elif ind == 1:
                new_case_x.matter_list.append(rot_mat.transpose(m))
            elif ind == 2:
                new_case_x.matter_list.append(rot_mat.rev_row(m))
            elif ind == 3:
                new_case_x.matter_list.append(rot_mat.rev_col(m))
            elif ind == 4:
                new_case_x.matter_list.append(rot_mat.rot_180(m))
            elif ind == 5:
                new_case_x.matter_list.append(rot_mat.rot_rev_180(m))
            elif ind == 6:
                new_case_x.matter_list.append(rot_mat.rot_90(m))
            elif ind == 7:
                new_case_x.matter_list.append(rot_mat.rot_270(m))
        q.train_x_list.append(new_case_x)

    for case_x in p.test_x_list:
        new_case_x = case_x.copy()
        new_case_x.matter_list = []
        for i in range(base_len):
            m = case_x.matter_list[i]
            ind = good_operations[i].argmax()
            if ind == 0:
                new_case_x.matter_list.append(m.deepcopy())
            elif ind == 1:
                new_case_x.matter_list.append(rot_mat.transpose(m))
            elif ind == 2:
                new_case_x.matter_list.append(rot_mat.rev_row(m))
            elif ind == 3:
                new_case_x.matter_list.append(rot_mat.rev_col(m))
            elif ind == 4:
                new_case_x.matter_list.append(rot_mat.rot_180(m))
            elif ind == 5:
                new_case_x.matter_list.append(rot_mat.rot_rev_180(m))
            elif ind == 6:
                new_case_x.matter_list.append(rot_mat.rot_90(m))
            elif ind == 7:
                new_case_x.matter_list.append(rot_mat.rot_270(m))
        q.test_x_list.append(new_case_x)

    return q
Ejemplo n.º 27
0
 def problem(cls, p: Problem, full: bool = False) -> Problem:
     assert p.is_rot_symmetry
     q: Problem = p.copy()
     q.train_x_list = [cls.case(c, full) for c in p.train_x_list]
     q.test_x_list = [cls.case(c, full) for c in p.test_x_list]
     return q
 def problem(cls, p: Problem, hole_type: str) -> Problem:
     q: Problem = p.copy()
     q.train_x_list = [cls.case(c, hole_type) for c in p.train_x_list]
     q.test_x_list = [cls.case(c, hole_type) for c in p.test_x_list]
     return q
Ejemplo n.º 29
0
def color_pile(p: Problem) -> Problem:

    case_x: Case
    case_y: Case
    case_x_new: Case

    rule_all = 10 * np.ones(10, dtype=np.int64)

    for case_x, case_y in zip(p.train_x_list, p.train_y_list):

        # same shape
        assert case_x.shape == case_y.shape

        # reduce count
        cnt_arr = np.zeros((case_x.shape[0], case_x.shape[1], 10), dtype=np.int64)
        # collect values
        for m in case_x.matter_list:
            if not m.bool_show:
                continue
            for i in range(m.shape[0]):
                for j in range(m.shape[1]):
                    if m.values[i, j] != m.background_color:
                        assert 0 <= m.values[i, j] <= 9
                        cnt_arr[m.x0 + i, m.y0 + j, m.values[i, j]] += 1

        y_values = case_y.repr_values()

        # one rule
        res_arr = color_pile_arr(cnt_arr, y_values, case_x.background_color)
        for color in range(10):
            if (y_values == color).sum():
                assert res_arr[color] < 10

        # reduce rule
        rule_all = reduce_rule(res_arr, rule_all)

    q: Problem
    q = p.copy()
    q.train_x_list = []
    q.test_x_list = []

    # transform
    # test_x first so that find exception faster
    for case_x in p.test_x_list:
        new_values = case_x.background_color * np.ones(case_x.shape, dtype=np.int64)
        cnt_arr = np.zeros((case_x.shape[0], case_x.shape[1], 10), dtype=np.int64)
        # collect values
        for m in case_x.matter_list:
            if not m.bool_show:
                continue
            for i in range(m.shape[0]):
                for j in range(m.shape[1]):
                    if m.values[i, j] != m.background_color:
                        assert 0 <= m.values[i, j] <= 9
                        cnt_arr[m.x0 + i, m.y0 + j, m.values[i, j]] += 1
        # reduce
        for color_order in range(9, -1, -1):
            for color in range(10):
                if rule_all[color] == color_order:
                    new_values[cnt_arr[:, :, color] > 0] = color
        case_x_new = case_x.copy()
        case_x_new.matter_list = [Matter(new_values, background_color=case_x_new.background_color, new=True)]
        q.test_x_list.append(case_x_new)
    # train_x
    for case_x in p.train_x_list:
        new_values = case_x.background_color * np.ones(case_x.shape, dtype=np.int64)
        cnt_arr = np.zeros((case_x.shape[0], case_x.shape[1], 10), dtype=np.int64)
        # collect values
        for m in case_x.matter_list:
            if not m.bool_show:
                continue
            for i in range(m.shape[0]):
                for j in range(m.shape[1]):
                    if m.values[i, j] != m.background_color:
                        assert 0 <= m.values[i, j] <= 9
                        cnt_arr[m.x0 + i, m.y0 + j, m.values[i, j]] += 1
        # reduce
        for color_order in range(9, -1, -1):
            for color in range(10):
                if rule_all[color] == color_order:
                    new_values[cnt_arr[:, :, color] > 0] = color
        case_x_new = case_x.copy()
        case_x_new.matter_list = [Matter(new_values, background_color=case_x_new.background_color, new=True)]
        q.train_x_list.append(case_x_new)

    return q
def divide(p: Problem) -> Problem:

    flag, d_row, d_col = is_division(p)
    flag_n = False

    if not flag:
        flag, nc_row, nc_col = is_constant(p)
        flag_n = True
        cnt_arr = np.zeros((2, 2), dtype=int)
    else:
        cnt_arr = np.zeros((d_row, d_col), dtype=int)
    assert flag

    q: Problem
    q = p.copy()
    q.train_x_list = []
    q.test_x_list = []
    c_x: Case
    c_x_new: Case

    # find best
    for c_x, c_y in zip(p.train_x_list, p.train_y_list):
        base_values = c_x.repr_values()
        res_values = c_y.repr_values()
        n_row, n_col = base_values.shape
        if flag_n:
            assert n_row % nc_row == 0
            assert n_col % nc_col == 0
            d_row = n_row // nc_row
            d_col = n_col // nc_col
        q_row, q_col = n_row // d_row, n_col // d_col
        # print(d_row, d_col)
        # is_division -> any
        if not flag_n:
            for i in range(d_row):
                for j in range(d_col):
                    if (base_values[i * q_row:(i + 1) * q_row,
                                    j * q_col:(j + 1) *
                                    q_col] == res_values).min():
                        cnt_arr[i, j] += 1
        # is_constant -> 4 corners
        else:
            if (base_values[:q_row, :q_col] == res_values).min():
                cnt_arr[0, 0] += 1
            if (base_values[:q_row, -q_col:] == res_values).min():
                cnt_arr[0, 1] += 1
            if (base_values[-q_row:, :q_col] == res_values).min():
                cnt_arr[1, 0] += 1
            if (base_values[-q_row:, -q_col:] == res_values).min():
                cnt_arr[1, 1] += 1
    # print(cnt_arr)
    # fit
    i0, j0 = -1, -1
    for i in range(cnt_arr.shape[0]):
        for j in range(cnt_arr.shape[1]):
            if cnt_arr[i, j] == len(p.train_x_list):
                i0, j0 = i, j
                break
        if i0 >= 0:
            break
    assert i0 >= 0 and j0 >= 0

    # fit
    for c_x in p.train_x_list:
        base_values = c_x.repr_values()
        n_row, n_col = base_values.shape
        if flag_n:
            assert n_row % nc_row == 0
            assert n_col % nc_col == 0
            d_row = n_row // nc_row
            d_col = n_col // nc_col
        q_row, q_col = n_row // d_row, n_col // d_col

        # is_division -> any
        if not flag_n:
            new_values = base_values[i0 * q_row:(i0 + 1) * q_row,
                                     j0 * q_col:(j0 + 1) * q_col].copy()
        # is_constant -> 4 corners
        else:
            if i0 == 0 and j0 == 0:
                new_values = base_values[:q_row, :q_col].copy()
            elif i0 == 0 and j0 == 1:
                new_values = base_values[:q_row, -q_col:].copy()
            elif i0 == 1 and j0 == 0:
                new_values = base_values[-q_row:, :q_col].copy()
            else:
                new_values = base_values[-q_row:, -q_col:].copy()

        c_x_new = c_x.copy()
        c_x_new.shape = q_row, q_col
        c_x_new.matter_list = [
            Matter(new_values, background_color=c_x.background_color, new=True)
        ]
        q.train_x_list.append(c_x_new)

    for c_x in p.test_x_list:
        base_values = c_x.repr_values()
        n_row, n_col = base_values.shape
        if flag_n:
            assert n_row % nc_row == 0
            assert n_col % nc_col == 0
            d_row = n_row // nc_row
            d_col = n_col // nc_col
        q_row, q_col = n_row // d_row, n_col // d_col

        # is_division -> any
        if not flag_n:
            new_values = base_values[i0 * q_row:(i0 + 1) * q_row,
                                     j0 * q_col:(j0 + 1) * q_col].copy()
        # is_constant -> 4 corners
        else:
            if i0 == 0 and j0 == 0:
                new_values = base_values[:q_row, :q_col].copy()
            elif i0 == 0 and j0 == 1:
                new_values = base_values[:q_row, -q_col:].copy()
            elif i0 == 1 and j0 == 0:
                new_values = base_values[-q_row:, :q_col].copy()
            else:
                new_values = base_values[-q_row:, -q_col:].copy()

        c_x_new = c_x.copy()
        c_x_new.shape = q_row, q_col
        c_x_new.matter_list = [
            Matter(new_values, background_color=c_x.background_color, new=True)
        ]
        q.test_x_list.append(c_x_new)

    return q