编辑代码

# -*- coding: utf-8 -*-
# 导入 itertools 中的 product 函数,用于生成笛卡尔积(即所有组合)
from itertools import product
import sys # 导入 sys 模块,用于退出脚本

# 提供的数字范围字符串,每个位置允许的数字用空格隔开
provided_digits_str = "34679 123456789 013579 0345679"

print(f"输入字符串: \"{provided_digits_str}\"")

# --- 新增:解析输入,识别 'x' 并确定模式 ---
provided_parts = provided_digits_str.split()
total_positions = len(provided_parts)

# 简单校验输入格式是否为 4 个部分
if total_positions != 4:
    print(f"错误:输入字符串 \"{provided_digits_str}\" 应包含 4 个部分(数字或 'x'/'X'),用空格隔开。")
    sys.exit(1) # 退出脚本

non_x_indices = []         # 存储非 'x' 位置的原始索引 (0, 1, 2, 3)
x_indices = []             # 存储 'x' 位置的原始索引
active_provided_digits = [] # 只存储非 'x' 位置的允许数字集合

for i, part in enumerate(provided_parts):
    if part.lower() == 'x':
        x_indices.append(i)
    else:
        try:
            # 尝试将数字字符串转换为数字集合
            digit_set = set(map(int, part))
            non_x_indices.append(i)
            active_provided_digits.append(digit_set)
        except ValueError:
            # 如果包含非数字字符(且不是 'x'/'X'),则报错
            print(f"错误:输入字符串 \"{provided_digits_str}\" 的第 {i+1} 部分 \"{part}\" 包含无效字符。只允许数字和 'x'/'X'。")
            sys.exit(1) # 退出脚本

num_digits = len(non_x_indices) # 需要生成的组合位数 (非 'x' 的数量)
num_x = len(x_indices)          # 'x' 的数量

# 根据非 'x' 的位数确定模式名称
if num_digits == 4:
    mode_name = "四定"
    combination_length_name = "4 位数"
elif num_digits == 3:
    mode_name = "三定"
    combination_length_name = "3 位数"
elif num_digits == 2:
    mode_name = "两定"
    combination_length_name = "2 位数"
elif num_digits == 1:
    mode_name = "一定"
    combination_length_name = "1 位数"
elif num_digits == 0:
     mode_name = "零定" # 特殊情况,所有位置都是 'x'
     combination_length_name = "0 位数"
else:
     # 理论上不会执行到这里,因为 total_positions 已校验为 4
     print("错误:出现意外情况,无法确定模式。")
     sys.exit(1)

print(f"检测到模式: {mode_name} (共 {num_digits} 个非 'x' 位置)")
# --- 解析结束 ---

# 初始化一个字典来存储结果
# 键 (key) 是匹配的位置数量 (0 到 num_digits)
# 值 (value) 是一个列表,用于存放符合该匹配数量的组合字符串
combinations = {i: [] for i in range(num_digits + 1)}

# --- 修改:根据 num_digits 确定生成范围 ---
if num_digits > 0:
    print(f"正在生成和检查所有 {combination_length_name} 组合 ({'0'*num_digits}{'9'*num_digits})...")
    # 遍历所有可能的 num_digits 位数组合
    # 例如 num_digits=3, product(range(10), repeat=3) 会生成从 (0, 0, 0) 到 (9, 9, 9) 的所有元组
    for combo_tuple in product(range(10), repeat=num_digits):
        matched_positions = 0  # 初始化当前组合的匹配位置计数器

        # 遍历当前生成的组合元组中的每个数字及其索引 (这里的 i 是 0 到 num_digits-1)
        for i, digit in enumerate(combo_tuple):
            # 获取该数字对应的原始位置允许的数字集合
            # active_provided_digits[i] 存储的是第 i 个非 'x' 位置的集合
            allowed_set = active_provided_digits[i]
            # 检查当前数字 (digit) 是否在对应允许的数字集合 (allowed_set) 中
            if digit in allowed_set:
                matched_positions += 1  # 如果匹配,计数器加 1

        # --- 新增:将生成的数字和 'X' 组合成完整字符串 ---
        full_combo_list = [''] * total_positions # 创建包含 total_positions 个空位的列表
        # 填充 'X'
        for idx in x_indices:
            full_combo_list[idx] = 'X'
        # 填充生成的数字到非 'x' 位置
        for i, idx in enumerate(non_x_indices):
            full_combo_list[idx] = str(combo_tuple[i])

        # 将列表合并为最终的字符串,例如 ['1', 'X', '8', '9'] -> "1X89"
        combo_str_full = "".join(full_combo_list)
        # --- 组合结束 ---

        # 将转换后的完整字符串添加到对应匹配数量的列表中
        combinations[matched_positions].append(combo_str_full)

elif num_digits == 0: # 处理 "x x x x" 的特殊情况
    print("所有位置均为 'x',只有一个组合 'XXXX'。")
    combinations[0].append('X' * total_positions) # 匹配 0 个位置

print("检查完成,开始打印结果:\n")

# --- 修改:打印结果的标题和范围 ---
# 遍历结果字典,按匹配数量打印所有组合
for value in range(num_digits + 1): # 循环范围是 0 到 num_digits
    combo_list = combinations[value]
    count = len(combo_list)
    # 更新标题以反映实际匹配数和总数
    # 对于 N 定模式,最多匹配 N 个位置
    print(f"--- 匹配 {value} 个位置的组合 (共 {count} 个) ---")

    if combo_list:  # 如果列表不为空
        # 将列表中的所有组合字符串用空格连接起来打印
        print(" ".join(combo_list))
    else:
        # 如果列表为空
        print("(无)")
    print() # 打印一个空行,让输出更清晰

print("所有结果打印完毕。")