字谜程序——python

来源:互联网 发布:sql server restoring 编辑:程序博客网 时间:2024/06/11 10:20

最近学习python,看到了别人写的一个求解字谜的程序,十分精简,充分应用了python的itertools模块,也体现其特有的语法。这里我稍作修改后,把每段代码都做了详细注释,适合初学者阅读

 

#coding=utf-8
'''
字谜程序 如:
HAWAII + IDAHO + IOWA + OHIO == STATES
其中每个总目对应数字,上式的解为
510199 + 98153 + 9301 + 3593 == 621246

采用穷举方式求解
1.通过re.findall()函数找到谜题中的所有字母
2.使用集合和set()函数找到谜题出现的所有不同的字母
3.通过assert语句检查是否有超过10个的不同的字母 (意味着谜题无解)
4.通过一个生成器对象将字符转换成对应的ASCII码值
5.使用itertools.permutations()函数计算所有可能的解法
6.使用translate()字符串方法将所有可能的解转换成Python表达式
7.使用eval()函数通过求值Python 表达式来检验解法
8.返回第一个求值结果为True的解法

具体可参见 http://woodpecker.org.cn/diveintopython3/advanced-iterators.html
'''

import re
import itertools

def solve(puzzle):
# upper把字符全部转化为大写字母
    words = re.findall('[A-Z]+', puzzle.upper())

#  集合set 是装有独特值的无序“袋子”。如果有两个集合,则可以执行像联合、交集以及集合求差等标准集合运算。
#   如:a_set.intersection(b_set)
# 'tag'.join(s)以tag连接字符串s    s.split('tag')以tag拆分字符串
    unique_characters = set(''.join(words))

# 当表达式结果不成立时,AssertionError异常被抛出,并打印信息
    assert len(unique_characters) <= 10, 'Too many letters'

# 采用生成器表达式,取出所有单词首字母到set集合中
# 生成器表达式返回迭代器,调用 next(gen) 返回迭代器的下一个值,可以将生成器表达式 list(),set()等来迭代所有的值返回列表或者集合。
# ord(c)为返回c字符的ASCII数值
# 生成器表达式取代列表解析可以同时节省cpu 和 内存(ram)
    first_letters = {word[0] for word in words}
    n = len(first_letters)
#  unique_characters - first_letters表示剔除unique_characters 中的first_letters
#     \表示连接下一行
    sorted_characters = ''.join(first_letters) + \
        ''.join(unique_characters - first_letters)
    characters = tuple(ord(c) for c in sorted_characters)
    digits = tuple(ord(c) for c in '0123456789')
    zero = digits[0]

# itertools.permutations(A,2)返回所有A序列2排列情况的迭代器
    for guess in itertools.permutations(digits, len(characters)):
        if zero not in guess[:n]:
#             translate为字符翻译 >>>'MARK'.translate({ord('A'): ord('O')})   >>>‘MORK’
#             dict为字典,无序键值对
#             zip为交替返回两个序列
            equation = puzzle.translate(dict(zip(characters, guess)))# 是邪恶的,只用于对信任的表达式求解
            if eval(equation):
                return equation


if __name__ == '__main__':
    solution = solve('SEND + MORE == MONEY')
    if solution:
        print(solution)

0 0
原创粉丝点击