import itertools
 
 
def calc_word_value(reversed_word, symbol_map):
    result = 0
    for letter, factor in reversed_word:
        result += symbol_map[letter] * factor
    return result
 
def print_result(words, answer, variant):
    t_words = []
    for word in words:
        t_words.append("".join(str(variant[l]) for l in word))
 
    t_answer = "".join(str(variant[l]) for l in answer)
 
    print("{:15s} {} = {}".format("INPUT:", " + ".join(words), answer))
    print("{:15s} {} = {}".format("SOLUTION:", " + ".join(t_words), t_answer))
    print("")
 
 
def solver(puzzle, full_search=False):
    words_line, answer = puzzle.split('=')
    words = [word.strip() for word in words_line.split('+')]
    answer = answer.strip()
    all_words = words + [answer]
 
    # 'abcd' --> [('d', 1), ('c', 10), ('b', 100), ('a', 1000)]
    rev_words = []
    for word in words:
        rev_word = [(letter, 10**num) for num, letter in enumerate(word[::-1])]
        rev_words.append(rev_word)
    rev_answer = [(letter, 10**num) for num, letter in enumerate(answer[::-1])]
 
    letters = sorted(set("".join(all_words)))
    LEN = len(letters)
 
    for digits_selection in itertools.combinations(range(10), len(letters)):
        for digits_permutation in itertools.permutations(digits_selection):
            # make dict: letter --> digit (int)
            variant = dict(zip(letters, digits_permutation))
            is_allowed = True
            for word in all_words:
                if variant[word[0]] == 0:
                    is_allowed = False
 
            if is_allowed:
                words_sum = 0
                for rev_word in rev_words:
                    words_sum += calc_word_value(rev_word, variant)
 
                answer_sum = calc_word_value(rev_answer, variant)
                if words_sum == answer_sum:
                    print_result(words, answer, variant)
                    if not full_search:
                        return
 
 
full_search = False
 
solver("send + more = money", full_search=full_search)
solver("ZEROES + ONES = BINARY", full_search=full_search)
solver("COUPLE + COUPLE = QUARTET", full_search=full_search)
solver("DO + YOU + FEEL = LUCKY", full_search=full_search)
solver("ELEVEN + NINE + FIVE + FIVE = THIRTY", full_search=full_search)
				aW1wb3J0IGl0ZXJ0b29scwoKCmRlZiBjYWxjX3dvcmRfdmFsdWUocmV2ZXJzZWRfd29yZCwgc3ltYm9sX21hcCk6CiAgICByZXN1bHQgPSAwCiAgICBmb3IgbGV0dGVyLCBmYWN0b3IgaW4gcmV2ZXJzZWRfd29yZDoKICAgICAgICByZXN1bHQgKz0gc3ltYm9sX21hcFtsZXR0ZXJdICogZmFjdG9yCiAgICByZXR1cm4gcmVzdWx0CgpkZWYgcHJpbnRfcmVzdWx0KHdvcmRzLCBhbnN3ZXIsIHZhcmlhbnQpOgogICAgdF93b3JkcyA9IFtdCiAgICBmb3Igd29yZCBpbiB3b3JkczoKICAgICAgICB0X3dvcmRzLmFwcGVuZCgiIi5qb2luKHN0cih2YXJpYW50W2xdKSBmb3IgbCBpbiB3b3JkKSkKICAgIAogICAgdF9hbnN3ZXIgPSAiIi5qb2luKHN0cih2YXJpYW50W2xdKSBmb3IgbCBpbiBhbnN3ZXIpCgogICAgcHJpbnQoIns6MTVzfSB7fSA9IHt9Ii5mb3JtYXQoIklOUFVUOiIsICIgKyAiLmpvaW4od29yZHMpLCBhbnN3ZXIpKQogICAgcHJpbnQoIns6MTVzfSB7fSA9IHt9Ii5mb3JtYXQoIlNPTFVUSU9OOiIsICIgKyAiLmpvaW4odF93b3JkcyksIHRfYW5zd2VyKSkKICAgIHByaW50KCIiKQoKCmRlZiBzb2x2ZXIocHV6emxlLCBmdWxsX3NlYXJjaD1GYWxzZSk6CiAgICB3b3Jkc19saW5lLCBhbnN3ZXIgPSBwdXp6bGUuc3BsaXQoJz0nKQogICAgd29yZHMgPSBbd29yZC5zdHJpcCgpIGZvciB3b3JkIGluIHdvcmRzX2xpbmUuc3BsaXQoJysnKV0KICAgIGFuc3dlciA9IGFuc3dlci5zdHJpcCgpCiAgICBhbGxfd29yZHMgPSB3b3JkcyArIFthbnN3ZXJdCgogICAgIyAnYWJjZCcgLS0+IFsoJ2QnLCAxKSwgKCdjJywgMTApLCAoJ2InLCAxMDApLCAoJ2EnLCAxMDAwKV0KICAgIHJldl93b3JkcyA9IFtdCiAgICBmb3Igd29yZCBpbiB3b3JkczoKICAgICAgICByZXZfd29yZCA9IFsobGV0dGVyLCAxMCoqbnVtKSBmb3IgbnVtLCBsZXR0ZXIgaW4gZW51bWVyYXRlKHdvcmRbOjotMV0pXQogICAgICAgIHJldl93b3Jkcy5hcHBlbmQocmV2X3dvcmQpCiAgICByZXZfYW5zd2VyID0gWyhsZXR0ZXIsIDEwKipudW0pIGZvciBudW0sIGxldHRlciBpbiBlbnVtZXJhdGUoYW5zd2VyWzo6LTFdKV0KCiAgICBsZXR0ZXJzID0gc29ydGVkKHNldCgiIi5qb2luKGFsbF93b3JkcykpKQogICAgTEVOID0gbGVuKGxldHRlcnMpCgogICAgZm9yIGRpZ2l0c19zZWxlY3Rpb24gaW4gaXRlcnRvb2xzLmNvbWJpbmF0aW9ucyhyYW5nZSgxMCksIGxlbihsZXR0ZXJzKSk6CiAgICAgICAgZm9yIGRpZ2l0c19wZXJtdXRhdGlvbiBpbiBpdGVydG9vbHMucGVybXV0YXRpb25zKGRpZ2l0c19zZWxlY3Rpb24pOgogICAgICAgICAgICAjIG1ha2UgZGljdDogbGV0dGVyIC0tPiBkaWdpdCAoaW50KQogICAgICAgICAgICB2YXJpYW50ID0gZGljdCh6aXAobGV0dGVycywgZGlnaXRzX3Blcm11dGF0aW9uKSkKICAgICAgICAgICAgaXNfYWxsb3dlZCA9IFRydWUKICAgICAgICAgICAgZm9yIHdvcmQgaW4gYWxsX3dvcmRzOgogICAgICAgICAgICAgICAgaWYgdmFyaWFudFt3b3JkWzBdXSA9PSAwOgogICAgICAgICAgICAgICAgICAgIGlzX2FsbG93ZWQgPSBGYWxzZQoKICAgICAgICAgICAgaWYgaXNfYWxsb3dlZDoKICAgICAgICAgICAgICAgIHdvcmRzX3N1bSA9IDAKICAgICAgICAgICAgICAgIGZvciByZXZfd29yZCBpbiByZXZfd29yZHM6CiAgICAgICAgICAgICAgICAgICAgd29yZHNfc3VtICs9IGNhbGNfd29yZF92YWx1ZShyZXZfd29yZCwgdmFyaWFudCkKCiAgICAgICAgICAgICAgICBhbnN3ZXJfc3VtID0gY2FsY193b3JkX3ZhbHVlKHJldl9hbnN3ZXIsIHZhcmlhbnQpCiAgICAgICAgICAgICAgICBpZiB3b3Jkc19zdW0gPT0gYW5zd2VyX3N1bToKICAgICAgICAgICAgICAgICAgICBwcmludF9yZXN1bHQod29yZHMsIGFuc3dlciwgdmFyaWFudCkKICAgICAgICAgICAgICAgICAgICBpZiBub3QgZnVsbF9zZWFyY2g6CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybgoKCmZ1bGxfc2VhcmNoID0gRmFsc2UKCnNvbHZlcigic2VuZCArIG1vcmUgPSBtb25leSIsIGZ1bGxfc2VhcmNoPWZ1bGxfc2VhcmNoKQpzb2x2ZXIoIlpFUk9FUyArIE9ORVMgPSBCSU5BUlkiLCBmdWxsX3NlYXJjaD1mdWxsX3NlYXJjaCkKc29sdmVyKCJDT1VQTEUgKyBDT1VQTEUgPSBRVUFSVEVUIiwgZnVsbF9zZWFyY2g9ZnVsbF9zZWFyY2gpCnNvbHZlcigiRE8gKyBZT1UgKyBGRUVMID0gTFVDS1kiLCBmdWxsX3NlYXJjaD1mdWxsX3NlYXJjaCkKc29sdmVyKCJFTEVWRU4gKyBOSU5FICsgRklWRSArIEZJVkUgPSBUSElSVFkiLCBmdWxsX3NlYXJjaD1mdWxsX3NlYXJjaCk=