1. 程式人生 > >字母算術的python算法

字母算術的python算法

eve print main advance make __main__ tor 並且 letter

據說Google出過一道題目:WWWDOT – GOOGLE = DOTCOM。
其中每個字母代表一個數字,數字不能重復,而且最高位的數字不能為0。

像這樣的謎題被稱為cryptarithms或者字母算術(alphametics)。字母可以拼出實際的單詞,而如果你把每一個字母都用0–9中的某一個數字代替後, 也同樣可以拼出一個算術等式。關鍵的地方是找出每個字母都映射到了哪個數字。每個字母所有出現的地方都必須映射到同一個數字,數字不能重復, 並且“單詞”不能以0開始。

最著名的字母算術謎題是SEND + MORE = MONEY。

Raymond Hettinger寫過一個令人難以置信的Python程序,這個程序只用14行代碼來解決任何字母算術謎題。

代碼見:http://woodpecker.org.cn/diveintopython3/advanced-iterators.html

不過該代碼是python 3.x版本的,下面是我改過的可以在2.x版運行的代碼:

# -*- coding : utf-8 -*-
# Copyright (c) 2009, Raymond Hettinger, All rights reserved.
# Ported to Python 2.x and modified by poboke.com

import re
import itertools
import string

def solve(puzzle):

    #匹配出所有字母,轉為大寫
    words = re.findall(‘[A-Z]+‘, puzzle.upper())

    #將字母放到集合裏
    unique_chars = set(‘‘.join(words))

    #因為數字只有10個,所以如果字母大於10個就會出錯
    assert len(unique_chars) <= 10, ‘Too many letters‘

    #將式子的首字母排到前面,方便判斷首字母是否為0
    first_letters = {word[0] for word in words}
    n = len(first_letters)
    sorted_chars = ‘‘.join(first_letters) +         ‘‘.join(unique_chars - first_letters)

    #所有數字
    digits = ‘0123456789‘
    zero = digits[0]

    #獲取所有數字的全排列
    for guess in itertools.permutations(digits, len(sorted_chars)):

        #所有式子的首字母都不能為0
        if zero not in guess[:n]:

            #將字母替換為數字
            trans = string.maketrans(sorted_chars, ‘‘.join(guess))
            equation = puzzle.translate(trans)

            #如果數字式子的計算結果正確
            if eval(equation):
                print equation


if __name__ == ‘__main__‘:
    import sys
    for puzzle in sys.argv[1:]:
        print(puzzle)
        solve(puzzle)

這個是python2的代碼,如果是python3,需要修改
string.maketrans 為 str.maketrans
print加括號

執行結果如下:

poboke$ python alphametics.py "WWWDOT - GOOGLE == DOTCOM"
WWWDOT - GOOGLE == DOTCOM
777589 - 188103 == 589486
777589 - 188106 == 589483

poboke$ python alphametics.py "WWWDOT - POBOKE == DOTCOM"
WWWDOT - POBOKE == DOTCOM
666435 - 231397 == 435038
666435 - 231398 == 435037
666180 - 485893 == 180287
666180 - 485897 == 180283

poboke$ python alphametics.py "SEND + MORE == MONEY"
SEND + MORE == MONEY
9567 + 1085 == 10652

poboke$ python alphametics.py "SIX + SEVEN + SEVEN == TWENTY"
SIX + SEVEN + SEVEN == TWENTY
650 + 68782 + 68782 == 138214


字母算術的python算法