def _removeMemo(
    how_anlz_list: List[HowToAnalyze],
    region: Region,
    squ_list: List[Square]
) -> None:
    """メモの除外

    ヒント(値)によってメモを除外

    Args:
        how_anlz_list (List[ChangeHistroy]): 解析方法
        region (Region): 領域
        squ_list (List[Square]): 枡リスト
    """
    # 確定枡を抽出
    not_none_squ_list: List[Square] = SudokuUtil.find_fixed_squ_from_region(
        squ_list)

    # 未確定枡を抽出
    none_squ_list: List[Square] = SudokuUtil.find_unfixed_squ_from_region(
        squ_list)

    # メモからヒント(値)を除外
    for none_squ in none_squ_list:
        for memo in none_squ.memo_val_list[:]:
            for not_none_squ in not_none_squ_list:
                if memo == not_none_squ.get_fixed_val():
                    none_squ.memo_val_list.remove(memo)

                    # 解析方法生成
                    how_anlz: HowToAnalyze = HowToAnalyze(
                        Method.ELIMIONATION)
                    how_anlz.region = region
                    how_anlz.remove_memo_list.append(memo)
                    how_anlz.changed_squ = none_squ
                    how_anlz.trigger_squ_list.append(not_none_squ)
                    how_anlz.msg = MsgFactory.how_to_elimionation(how_anlz)

                    how_anlz_list.append(how_anlz)
示例#2
0
def _analyze_naked_pair(
    wk: AnalyzeWk,
    how_anlz_list: List[HowToAnalyze],
    region: Region,
    squ_list: List[Square]
) -> None:
    """ネイキッドペア解析

    Args:
        wk (AnalyzeWk): ワーク
        how_anlz_list (List[HowToAnalyze]): 解析方法
        region (Region): 領域
    """

    # 未確定枡を取得
    unfixed_list: List[Square] = SudokuUtil.find_unfixed_squ_from_region(
        squ_list)

    # 対象領域の全ての枡が確定している
    if len(unfixed_list) == 0:
        return

    # ペア数(2~8)を大きくしながら解析
    # ※制限時は2~3
    find_pair_cnt: int = 8
    if Method.NAKED_PAIR in wk.limit_method_list:
        find_pair_cnt = 3
    for naked_num in range(2, find_pair_cnt + 1):

        # 未確定枡数-1よりネイキッド数の方が大きくなったら処理終了
        # [補足]
        # 未確定数とネイキッド数が同じ場合、必ず全ての枡がペアになるため除外するメモがなくなる
        # ⇒-1して終了条件の比較を行っている
        if len(unfixed_list) - 1 <= naked_num:
            return

        # ペア可能リストを算出
        can_pair_list = list()
        for unfixed_squ in unfixed_list:
            if len(unfixed_squ.memo_val_list) > naked_num:
                continue

            # naked_num=3の場合
            # +[1]--------------------------------------+
            # | 1:1          1:2        1:3             |
            # | m=[N,M,O](@) m=[N,P](*) ?               |
            # | 2:1          2:2        2:3             |
            # | m=[M,O]($)   m=[M,Q](*) ?               |
            # | 3:1          3:2        3:3             |
            # | m=[N,M](#)   m=[O,R](*) m=[N,M,O,R,Q,S] |
            # +[4]--------------------------------------+
            # @枡、$枡、#枡、*枡3個を抽出
            # 1:1 m=[N,M,O](@)
            # 1:2 m=[N,P](*)
            # 2:1 m=[M,O]($)
            # 2:2 m=[M,Q](*)
            # 3:1 m=[N,M](#)
            # 3:2 m=[O,R](*)
            can_pair_list.append(unfixed_squ)

        # ペア可能リストがペア数より小さい場合は対象外
        # 次のペア数を調べる
        if len(can_pair_list) < naked_num:
            continue

        # ペアを見つける
        # 例に当てはめると
        # 1:1 m=[N,M,O](@)
        # 1:2 m=[N,P](*)
        # 2:1 m=[M,O]($)
        # 2:2 m=[M,Q](*)
        # 3:1 m=[N,M](#)
        # 3:2 m=[O,R](*)
        # から
        # 1:1 m=[N,M,O](@)
        # 2:1 m=[M,O]($)
        # 3:1 m=[N,M](#)
        # を見つける
        for pivot_squ in can_pair_list[:]:
            pivot_pair: Set[int] = set(pivot_squ.memo_val_list)
            for compare_squ in can_pair_list[:]:
                if pivot_squ == compare_squ:
                    continue
                pivot_pair = pivot_pair.union(set(compare_squ.memo_val_list))
                if len(pivot_pair) > naked_num:
                    break
            if len(pivot_pair) > naked_num:
                can_pair_list.remove(pivot_squ)

        # ネイキッド数≒枡数は対象外
        if len(can_pair_list) != naked_num:
            continue

        # ペア発見!
        pair_set: Set[int] = set()
        for squ in can_pair_list:
            pair_set = pair_set.union(squ.memo_val_list)
        pair_list: List[int] = list(pair_set)
        pair_list.sort()

        # 変更枡抽出
        change_squ_list: List[Square] = list()
        for squ in unfixed_list:
            if squ in can_pair_list:
                continue
            for memo in squ.memo_val_list:
                if memo in pair_list:
                    change_squ_list.append(squ)
                    break

        # ペアは見つかったが、変更枡が存在しない
        if len(change_squ_list) == 0:
            continue

        for change_squ in change_squ_list:
            for loop_memo in pair_list:
                if loop_memo not in change_squ.memo_val_list:
                    continue

                # メモを除外
                change_squ.memo_val_list.remove(loop_memo)

                # 解析方法生成
                how_anlz: HowToAnalyze = HowToAnalyze(
                    Method.NAKED_PAIR)
                how_anlz.region = region
                how_anlz.changed_squ = change_squ
                how_anlz.remove_memo_list.append(loop_memo)
                how_anlz.trigger_squ_list.extend(can_pair_list)
                how_anlz.msg = MsgFactory.how_to_naked_pair(
                    how_anlz, pair_list)

                how_anlz_list.append(how_anlz)