Пример #1
0
def y_wing_scan(board):
    for x in range(9):
        for y in range(9):
            if np.sum(board[x][y]) != 2:
                continue
            [az, bz] = list(np.nonzero(board[x][y])[0])

            xy_units = units(x, y)
            # get all pairs of unit cells
            concatenated_units = sorted(
                list(set(xy_units[0] + xy_units[1] + xy_units[2])))
            concatenated_units.remove((x, y))
            pairs = []
            for (ax, ay) in concatenated_units:
                for (bx, by) in concatenated_units:
                    if (ax, ay) == (bx, by):
                        continue
                    if np.sum(board[ax][ay]) == 2 and np.sum(
                            board[bx][by]) == 2:
                        if board[ax][ay][az] == 1 and board[bx][by][bz] == 1:
                            union = board[ax][ay] + board[bx][by]
                            if np.sum(union > 0) == 3:
                                if np.argmax(union) != az and np.argmax(
                                        union) != bz:
                                    # found a valid pair
                                    pairs.append([(ax, ay), (bx, by),
                                                  np.argmax(union)])
            if len(pairs) > 0:

                removed = False
                for [(ax, ay), (bx, by), cz] in pairs:
                    units_a = set(
                        [cell for unit in units(ax, ay) for cell in unit])
                    units_b = set(
                        [cell for unit in units(bx, by) for cell in unit])
                    for (cx,
                         cy) in sorted(list(units_a.intersection(units_b))):
                        if (cx, cy) in [(ax, ay), (bx, by), (x, y)]:
                            continue
                        if board[cx][cy][cz] == 1:
                            board[cx][cy][cz] = 0
                            removed = True
                            if removed:
                                relevant_cells = [(x, y), (ax, ay), (bx, by),
                                                  (cx, cy)]
                                relevant_candidates = [[cz]]
                                return (True, relevant_cells,
                                        np.array(relevant_candidates))

    return False, None, None
Пример #2
0
def hidden_single_scan(board):
    for x in range(9):
        for y in range(9):
            if np.sum(board[x][y]) == 1:
                continue
            xy_units = units(x, y)
            for z in range(9):
                if board[x][y][z] == 0:
                    continue

                for unit in xy_units:
                    hidden_candidate = True
                    for (searchX, searchY) in unit:
                        if (searchX, searchY) == (x, y):
                            continue
                        if board[searchX][searchY][z] == 1:
                            hidden_candidate = False
                            break

                    if hidden_candidate:
                        board[x][y] = np.zeros((9))
                        board[x][y][z] = 1
                        update_guesses(board, x, y)
                        relevant_cells = [(x, y)]
                        relevant_candidates = [
                            np.nonzero(board[a][b])[0]
                            for (a, b) in relevant_cells
                        ]
                        return (True, relevant_cells,
                                np.array(relevant_candidates))

    return False, None, None
Пример #3
0
def xyz_wing_scan(board):
    for x in range(9):
        for y in range(9):
            if np.sum(board[x][y]) != 3:
                continue
            xyz = np.nonzero(board[x][y])[0]
            xy_units = units(x, y)
            # get all pairs of unit cells

    return False, None, None
Пример #4
0
def naked_triples_scan(board):
    for x in range(9):
        for y in range(9):
            # find 3 cells with a total of 3 numbers
            # every cell has to have at least 2 guesses
            if np.sum(board[x][y]) != 2 and np.sum(board[x][y]) != 3:
                continue
            xy_units = units(x, y)
            for unit in xy_units:
                found_triple = False
                for (x1, y1) in unit:
                    if np.sum(board[x1][y1]) != 2 and np.sum(
                            board[x1][y1]) != 3:
                        continue
                    for (x2, y2) in unit:
                        if np.sum(board[x2][y2]) != 2 and np.sum(
                                board[x2][y2]) != 3:
                            continue
                        if len(set([(x, y), (x1, y1), (x2, y2)])) < 3:
                            # make sure cells are unique
                            continue

                        # found 3 unique cells in this unit with 2-3 guesses
                        intersection = board[x][y] + board[x1][y1] + board[x2][
                            y2]
                        if np.sum(intersection >= 1) == 3:
                            found_triple = True
                            break
                    else:
                        # double loop breaking
                        continue
                    break

                if found_triple:
                    removed = False
                    for (searchX, searchY) in unit:
                        if (searchX,
                                searchY) == (x, y) or (searchX, searchY) == (
                                    x1, y1) or (searchX, searchY) == (x2, y2):
                            continue
                        for zz in range(9):
                            if intersection[zz] > 0:
                                if board[searchX][searchY][zz] == 1:
                                    removed = True
                                    board[searchX][searchY][zz] = 0
                    if removed:
                        relevant_cells = [(x, y), (x1, y1), (x2, y2)]
                        relevant_candidates = [
                            np.nonzero(board[a][b])[0]
                            for (a, b) in relevant_cells
                        ]
                        return (True, relevant_cells,
                                np.array(relevant_candidates))

    return False, None, None
Пример #5
0
def naked_single_scan(board):
    for x in range(9):
        for y in range(9):
            if np.sum(board[x][y]) != 1:
                continue
            xy_units = units(x, y)
            removed = False
            candidate = np.argmax(board[x][y])
            for unit in xy_units:
                for (searchX, searchY) in unit:
                    if (searchX, searchY) == (x, y):
                        continue
                    if board[searchX][searchY][candidate] == 1:
                        board[searchX][searchY][candidate] = 0
                        removed = True
            if removed:
                relevant_cells = [(x, y)]
                relevant_candidates = [
                    np.nonzero(board[a][b])[0] for (a, b) in relevant_cells
                ]
                return (True, relevant_cells, np.array(relevant_candidates))
    return False, None, None
Пример #6
0
def naked_pairs_scan(board):
    for x in range(9):
        for y in range(9):
            if np.sum(board[x][y]) != 2:
                continue
            xy_units = units(x, y)
            for unit in xy_units:
                found_pair = False
                for (x1, y1) in unit:
                    if (x1, y1) == (x, y):
                        continue
                    if np.array_equal(board[x][y], board[x1][y1]):
                        found_pair = True
                        break

                if found_pair:
                    removed = False
                    for (searchX, searchY) in unit:
                        if (searchX, searchY) == (x, y) or (searchX,
                                                            searchY) == (x1,
                                                                         y1):
                            continue
                        for zz in range(9):
                            if board[x][y][zz] == 1:
                                if board[searchX][searchY][zz] == 1:
                                    removed = True
                                    board[searchX][searchY][zz] = 0
                    if removed:
                        relevant_cells = [(x, y), (x1, y1)]
                        relevant_candidates = [
                            np.nonzero(board[a][b])[0]
                            for (a, b) in relevant_cells
                        ]
                        return (True, relevant_cells,
                                np.array(relevant_candidates))
    return False, None, None
Пример #7
0
def x_wing_scan(board):
    for x in range(9):
        for y in range(9):
            for z in range(9):
                if np.sum(board[x][y]) == 1:
                    continue
                if board[x][y][z] == 0:
                    continue

                similar_in_unit = [[], []]
                # [0] contains all cells in the same row with candidate z
                # [1] contains all cells in the same col with candidate z
                xy_units = units(x, y)
                for i in [0, 1]:
                    for (x1, y1) in xy_units[i]:
                        if board[x1][y1][z] == 1:
                            similar_in_unit[i].append((x1, y1))

                if len(similar_in_unit[0]) == 2 and len(
                        similar_in_unit[1]) >= 2:
                    # the two coords in [0] (row) are locked in a pair
                    a = 0
                    b = 1
                elif len(similar_in_unit[1]) == 2 and len(
                        similar_in_unit[0]) >= 2:
                    a = 1
                    b = 0
                else:
                    continue
                opposite_coord = similar_in_unit[a][similar_in_unit[a].index(
                    (x, y)) - 1][a]

                # time to look at each coordinate to find another locked pair with the same similar axis
                for (x1, y1) in similar_in_unit[b]:
                    if (x1, y1) != (x, y):
                        other_units = units(x1, y1)
                        other_similar = []
                        for (x2, y2) in other_units[
                                a]:  # looking at this other cell's row
                            if board[x2][y2][z] == 1:
                                other_similar.append((x2, y2))
                        if len(other_similar) == 2:
                            # found another locked pair, time to check if x coordinates match up
                            # we know that one x coordinate will, just have to check if the second one does
                            opposite_corner = other_similar[
                                other_similar.index((x1, y1)) - 1]
                            if opposite_corner[a] == opposite_coord:
                                # found an x wing
                                x_wing = [similar_in_unit[a], other_similar]
                                # go through columns and remove
                                # print('!!!')
                                # print(x_wing, z + 1)
                                removed = False
                                unit_a = units(*x_wing[0][0])[b]
                                unit_b = units(*x_wing[0][1])[b]
                                for (searchX, searchY) in unit_a:
                                    if (searchX, searchY) in x_wing[0] or (
                                            searchX, searchY) in x_wing[1]:
                                        continue
                                    if board[searchX][searchY][z] == 1:
                                        removed = True
                                        board[searchX][searchY][z] = 0
                                for (searchX, searchY) in unit_b:
                                    if (searchX, searchY) in x_wing[0] or (
                                            searchX, searchY) in x_wing[1]:
                                        continue
                                    if board[searchX][searchY][z] == 1:
                                        removed = True
                                        board[searchX][searchY][z] = 0

                                if removed:
                                    relevant_cells = x_wing[0] + x_wing[1]
                                    relevant_candidates = [
                                        np.nonzero(board[a][b])[0]
                                        for (a, b) in relevant_cells
                                    ]
                                    return (True, relevant_cells,
                                            np.array(relevant_candidates))

    return False, None, None
Пример #8
0
def intersection_scan(board):
    for x in range(9):
        for y in range(9):
            if np.sum(board[x][y]) == 1:
                continue

            xy_units = units(x, y)
            for z in range(9):
                if board[x][y][z] == 0:
                    continue

                # pointing pairs and triples
                for i in range(3):
                    candidate_coords = []
                    for (x1, y1) in xy_units[i]:
                        if np.sum(board[x1][y1]) == 1:
                            continue
                        if board[x1][y1][z] == 1:
                            candidate_coords.append((x1, y1))

                    if len(candidate_coords) <= 3:
                        removed = False
                        if i == 2:
                            # pointing pairs within the same box
                            # check if the candidates line up on a row or column
                            if all(
                                    map(lambda coord: coord in xy_units[0],
                                        candidate_coords)):
                                # row lineup
                                for (searchX, searchY) in xy_units[0]:
                                    if not (searchX,
                                            searchY) in candidate_coords:
                                        if board[searchX][searchY][z] == 1:
                                            board[searchX][searchY][z] = 0
                                            removed = True
                            elif all(
                                    map(lambda coord: coord in xy_units[1],
                                        candidate_coords)):
                                # col lineup
                                for (searchX, searchY) in xy_units[1]:
                                    if not (searchX,
                                            searchY) in candidate_coords:
                                        if board[searchX][searchY][z] == 1:
                                            board[searchX][searchY][z] = 0
                                            removed = True
                        else:
                            # candidates on a row or column
                            # check if they are in the same box
                            if all(
                                    map(lambda coord: coord in xy_units[2],
                                        candidate_coords)):
                                for (searchX, searchY) in xy_units[2]:
                                    if not (searchX,
                                            searchY) in candidate_coords:
                                        if board[searchX][searchY][z] == 1:
                                            board[searchX][searchY][z] = 0
                                            removed = True
                        if removed:
                            # relevant_candidates = [np.nonzero(board[a][b])[0] for (a, b) in candidate_coords]
                            return (True, candidate_coords, np.array([[z]]))

    return False, None, None
Пример #9
0
def naked_quads_scan(board):
    for x in range(9):
        for y in range(9):
            # find 3 cells with a total of 3 numbers
            # every cell has to have at least 2 guesses
            if np.sum(board[x][y]) not in [2, 3, 4]:
                continue
            xy_units = units(x, y)
            for unit in xy_units:
                found_quad = False
                # TODO get all four-groups of cells that fit criterion?
                # rather than nested looping
                for (x1, y1) in unit:
                    if np.sum(board[x1][y1]) not in [2, 3, 4]:
                        continue
                    for (x2, y2) in unit:
                        if np.sum(board[x2][y2]) not in [2, 3, 4]:
                            continue
                        for (x3, y3) in unit:
                            if np.sum(board[x3][y3]) not in [2, 3, 4]:
                                continue
                            if len(set([(x, y), (x1, y1), (x2, y2),
                                        (x3, y3)])) < 4:
                                # make sure cells are unique
                                continue
                            # found 4 unique cells in this unit with 2-4 guesses
                            intersection = board[x][y] + board[x1][y1] + board[
                                x2][y2] + board[x3][y3]
                            if np.sum(intersection >= 1) == 4:
                                found_quad = True
                                break
                        else:
                            # double loop breaking
                            continue
                        break
                    else:
                        # double loop breaking
                        continue
                    break

                if found_quad:
                    removed = False
                    for (searchX, searchY) in unit:
                        if (searchX, searchY) == (x, y) or (
                                searchX,
                                searchY) == (x1, y1) or (searchX, searchY) == (
                                    x2, y2) or (searchX, searchY) == (x3, y3):
                            continue
                        for zz in range(9):
                            if intersection[zz] > 0:
                                if board[searchX][searchY][zz] == 1:
                                    removed = True
                                    board[searchX][searchY][zz] = 0
                    if removed:
                        relevant_cells = [(x, y), (x1, y1), (x2, y2), (x3, y3)]
                        relevant_candidates = [
                            np.nonzero(board[a][b])[0]
                            for (a, b) in relevant_cells
                        ]
                        return (True, relevant_cells,
                                np.array(relevant_candidates))

    return False, None, None