結果

問題 No.228 ゆきこちゃんの 15 パズル
ユーザー ThetaTheta
提出日時 2022-11-07 15:29:59
言語 Python3
(3.12.2 + numpy 1.26.4 + scipy 1.12.0)
結果
AC  
実行時間 315 ms / 5,000 ms
コード長 4,104 bytes
コンパイル時間 329 ms
コンパイル使用メモリ 13,056 KB
実行使用メモリ 11,392 KB
最終ジャッジ日時 2024-07-20 23:15:43
合計ジャッジ時間 6,001 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 313 ms
11,264 KB
testcase_01 AC 29 ms
11,264 KB
testcase_02 AC 129 ms
11,264 KB
testcase_03 AC 305 ms
11,392 KB
testcase_04 AC 30 ms
11,264 KB
testcase_05 AC 166 ms
11,264 KB
testcase_06 AC 67 ms
11,264 KB
testcase_07 AC 306 ms
11,264 KB
testcase_08 AC 68 ms
11,264 KB
testcase_09 AC 295 ms
11,264 KB
testcase_10 AC 124 ms
11,392 KB
testcase_11 AC 248 ms
11,264 KB
testcase_12 AC 315 ms
11,264 KB
testcase_13 AC 307 ms
11,392 KB
testcase_14 AC 305 ms
11,392 KB
testcase_15 AC 308 ms
11,264 KB
testcase_16 AC 308 ms
11,392 KB
testcase_17 AC 304 ms
11,264 KB
testcase_18 AC 306 ms
11,264 KB
testcase_19 AC 307 ms
11,264 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

from copy import deepcopy


class Number:
    def __init__(self, num: int, is_moved: bool) -> None:
        self.num = num
        self.is_moved = is_moved


class Board:
    def __init__(self, numbers: list[list[Number]]) -> None:
        self.board = numbers

    def __str__(self) -> str:
        str_ = []
        for row in self.board:
            str_.append(" ".join(map(lambda num_o: str(num_o.num), row)))
        return "\n".join(str_)

    def __eq__(self, __o: object) -> bool:
        for s_row, o_row in zip(self.board, __o.board):
            for s_num, o_num in zip(s_row, o_row):
                if s_num.num != o_num.num:
                    return False
        return True

    def __ne__(self, __o: object) -> bool:
        return not self.__eq__(__o)

    def where_zero(self) -> tuple[int, int]:
        for row_idx, row in enumerate(self.board):
            try:
                return (row_idx, list(map(lambda num: num.num, row)).index(0))
            except ValueError:
                continue
        raise ValueError

    def move_up(self):
        zero_idx = self.where_zero()
        if zero_idx[0] == 3:
            return

        if self.board[zero_idx[0]+1][zero_idx[1]].is_moved:
            return

        new_board = deepcopy(self)
        new_board.board[zero_idx[0]][zero_idx[1]] = Number(
            self.board[zero_idx[0]+1][zero_idx[1]].num, True)
        new_board.board[zero_idx[0]+1][zero_idx[1]
                                       ] = Number(self.board[zero_idx[0]][zero_idx[1]].num, False)
        return new_board

    def move_down(self):
        zero_idx = self.where_zero()
        if zero_idx[0] == 0:
            return

        if self.board[zero_idx[0]-1][zero_idx[1]].is_moved:
            return

        new_board = deepcopy(self)
        new_board.board[zero_idx[0]][zero_idx[1]] = Number(
            self.board[zero_idx[0]-1][zero_idx[1]].num, True)
        new_board.board[zero_idx[0]-1][zero_idx[1]
                                       ] = Number(self.board[zero_idx[0]][zero_idx[1]].num, False)
        return new_board

    def move_right(self):
        zero_idx = self.where_zero()
        if zero_idx[1] == 0:
            return

        if self.board[zero_idx[0]][zero_idx[1]-1].is_moved:
            return

        new_board = deepcopy(self)
        new_board.board[zero_idx[0]][zero_idx[1]] = Number(
            self.board[zero_idx[0]][zero_idx[1]-1].num, True)
        new_board.board[zero_idx[0]][zero_idx[1]-1
                                     ] = Number(self.board[zero_idx[0]][zero_idx[1]].num, False)
        return new_board

    def move_left(self):
        zero_idx = self.where_zero()
        if zero_idx[1] == 3:
            return

        if self.board[zero_idx[0]][zero_idx[1]+1].is_moved:
            return

        new_board = deepcopy(self)
        new_board.board[zero_idx[0]][zero_idx[1]] = Number(
            self.board[zero_idx[0]][zero_idx[1]+1].num, True)
        new_board.board[zero_idx[0]][zero_idx[1]+1
                                     ] = Number(self.board[zero_idx[0]][zero_idx[1]].num, False)
        return new_board

    def move_4dir(self):
        candidate = [self.move_down(), self.move_left(),
                     self.move_right(), self.move_up()]
        return list(filter(lambda elm: elm is not None, candidate))


def main():
    target_board_nums = [list(map(int, input().split())) for _ in range(4)]
    target_board = Board([list(map(lambda num: Number(
        num, is_moved=False), target_board_num)) for target_board_num in target_board_nums])

    init_board_nums = [list(range(init, init+4)) for init in range(1, 16, 4)]

    init_board_nums[3][3] = 0
    init_board = Board([list(map(lambda num: Number(
        num, is_moved=False), init_board_num)) for init_board_num in init_board_nums])

    stack = [init_board]

    while stack:
        current_board = stack.pop()
        if current_board == target_board:
            print("Yes")
            return

        stack.extend(current_board.move_4dir())
    print("No")


if __name__ == "__main__":
    main()
0