You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

验证生成ASCII33-126字符所有单词组合的Python递归算法正确性

ASCII可打印字符组合枚举算法验证与优化

需求说明

  • 枚举范围:ASCII码从!(十进制值33)到~(十进制值126)的所有可打印字符
  • 枚举目标:上述字符可组成的全部单词组合
  • 参考ASCII码表:
    ASCII码表示意图

现有递归实现的问题

你提供的递归代码存在多处问题,无法正确完成枚举:

  1. 初始值错误:注释标注起始字符为33对应的!,但实际初始字节\x20、进位重置值都是32(对应空格字符),超出了要求的字符范围
  2. 递归逻辑缺陷:分支判断后没有中断返回,多个递归分支会叠加执行,导致重复计数、生成无效组合,无法保证枚举无遗漏、无重复
  3. 递归深度限制:Python默认递归深度阈值约为1000,生成长度稍大的组合时会直接触发栈溢出报错
  4. 执行效率极低:全局变量计数、逐行打印日志、Python层面递归调用的开销非常大,即使修正逻辑,生成长度3的组合(共83万余条)速度也会很慢

附你提供的原始代码(补充了缺失的sys导入否则无法运行):

import sys
byteWord = bytearray(b'\x20')  # 注释标注:Hex = '\x21' & Dec = '33' & Char = '!'

cntVerif = 0  # 测试计数变量


def comb_fct(bytes_arr, cnt: int):
    global cntVerif  # 引用全局测试计数

    if len(bytes_arr) > 3:  # 测试阶段仅生成长度不超过3的组合
        print(f'{cntVerif+1}:TEST END')
        sys.exit()

    if bytes_arr[cnt] == 126:
        if cnt == len(bytes_arr) or len(bytes_arr) == 1:
            bytes_arr.insert(0, 32)
        bytes_arr[cnt] = 32
        cnt += 1
        cntVerif += 1  # 测试计数累加
        print(f'{cntVerif}:if bytes_arr[cnt] == 126: \n\tbytes_arr = {bytes_arr}')  # 测试日志
        comb_fct(bytes_arr, cnt)

    if cnt == -1 or cnt == len(bytes_arr)-1:
        bytes_arr[cnt] = bytes_arr[cnt] + 1
        cntVerif += 1  # 测试计数累加
        print(f'{cntVerif}:if cnt==-1: \n\tbytes_arr = {bytes_arr}')  # 测试日志
        comb_fct(bytes_arr, cnt=-1)  # 索引-1表示取数组最后一位

    bytes_arr[cnt] = bytes_arr[cnt] + 1
    cntVerif += 1  # 测试计数累加
    print(f'{cntVerif}:None if: \n\tbytes_arr={bytes_arr}')  # 测试日志
    comb_fct(bytes_arr, cnt+1)


comb_fct(byteWord, -1)

高效实现方案

这个需求本质是有放回的全排列枚举,不需要手写递归,直接用Python标准库itertools.product即可实现,该方法由C层面实现迭代逻辑,执行效率比手写Python递归高数十倍,且无递归深度限制,返回的迭代器不会一次性加载所有组合到内存,内存占用极低:

import itertools

# 预生成合法字符集合:ASCII 33到126共94个可打印字符
VALID_CHARS = bytes(range(33, 127))

def enum_all_words(max_len: int = 3, fixed_len: int | None = None):
    """
    枚举所有合法字符组成的单词
    :param max_len: 枚举单词的最大长度
    :param fixed_len: 如果传值,仅枚举固定长度的单词
    """
    if fixed_len is not None:
        length_range = [fixed_len]
    else:
        length_range = range(1, max_len + 1)
    
    for word_len in length_range:
        # product生成对应长度的所有可重复排列,为惰性迭代器
        for char_tuple in itertools.product(VALID_CHARS, repeat=word_len):
            yield bytes(char_tuple)

if __name__ == "__main__":
    # 示例:统计所有长度1-3的组合总数
    total_count = 0
    for word in enum_all_words(max_len=3):
        # 此处替换为你对每个单词的处理逻辑
        total_count += 1
        # 测试时可打开打印查看每个单词
        # print(word.decode("ascii"))
    print(f"总组合数:{total_count}")
    # 正确输出应为 94 + 94*94 + 94*94*94 = 839514

提示:如果需要枚举更长的单词(比如长度为5时总组合数超过73亿),保持逐次迭代处理即可,不要尝试把所有结果存入列表,否则会占满内存。

内容的提问来源于stack exchange,提问作者X0-user-0X

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 07:51:25