summaryrefslogtreecommitdiff
path: root/src/alphametiken.py
blob: fb4324cf077564c246091b058c38c271879b6d34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# getestet mit Python 2.7.8 und 3.4.2
'''Generiert oder löst Alphametiken'''
# Nicht als root ausführen.
# Die Ausführung dauert bis zu zwei Minuten, abhängig von der Länge des
# Alphametiks. Die Generierung dauert unter Umständen 5 Minuten oder länger.

# Programm löst das Alphametik "SUCHEN-MACHT=SPASS"
# und generiert eines mit einem Rechenzeichen

import re, random

ALPHAMETIK = "SUCHEN-MACHT=SPASS"

ZAHLEN = ["EINS", "ZWEI", "DREI", "VIER", "FÜNF", \
 "SECHS", "SIEBEN", "ACHT", "NEUN", "ZEHN"]
#RECHENZEICHEN = ["+", "-", "*", "/"]
RECHENZEICHEN = ["+", "-"] # schneller

def buchstaben_liste(wort):
    '''Erstellt eine Liste der Buchstaben'''
    buchstaben = []
    for char in wort:
        if (char not in RECHENZEICHEN) \
            and (char not in buchstaben) \
            and (char not in " ="):

            buchstaben.append(char)

    return buchstaben

def ersetze(buchst, wort, \
    benutzte_zahlen=None, loesungen=None, alle_buchstaben=None):
    '''Ersetzt einen Buchstaben aus `buchst` in einem Wort `wort` \
nacheinander durch `0-9` und ruft sich selbst auf. \
Ist `buchst` leer, wird das Alphametik auf Richtigkeit getestet
und ggf. zu `loesungen` hinzugefügt. \
Zurückgegeben wird eine Liste mit Lösungen. \
Element der Liste ist der Rechnungsstring und ein dict.'''

    if alle_buchstaben == None:
        alle_buchstaben = buchst
    if benutzte_zahlen == None:
        benutzte_zahlen = []
    if loesungen == None:
        loesungen = []

    if len(buchst):
        for j in range(10):
            if j in benutzte_zahlen: # jede Zahl nur einmal verwenden
                continue

            m_benutzte_zahlen = benutzte_zahlen[:]
            m_benutzte_zahlen.append(j)

            m_wort = wort.replace(buchst[0], str(j))
            ersetze(buchst[1:], m_wort, m_benutzte_zahlen, \
                loesungen, alle_buchstaben)
    else:
        if re.search(r"\b0", wort):
            # 0 als erste Ziffer in einer Zahl ist nicht erlaubt
            return

        if eval(wort.replace("=", "==")):
            lsg = [wort, dict()]
            for j, k in zip(alle_buchstaben, benutzte_zahlen):
                lsg[1][j] = k

            loesungen.append(lsg)

    return loesungen

def loese(alpham):
    '''kleiner Wrapper, der die Benutzung von `ersetze` vereinfacht'''
    return ersetze(buchstaben_liste(alpham), alpham, None, None, None)

def generiere(laenge=1):
    '''gibt ein zufälliges Alphametik mit `laenge` \
"Ziffern" vor dem Gleichheitszeichen zurück'''
    while True:
        rechnung_ok = False
        while rechnung_ok == False: # sucht nach wahren Gleichungen
            alphametik = "x" + "_x" * laenge + "=y" # Template für Rechnung

            for j in range(laenge + 1): # zufällige Rechenzeichen einsetzen
                alphametik = alphametik.replace("_", \
                    random.choice(RECHENZEICHEN), 1)

            alphametik = alphametik.replace("y", str(random.randrange(1, 9)))
            # Ergebnis

            for j in range(laenge + 2):
                alphametik = alphametik.replace("x", \
                    str(random.randrange(1, 9)), 1)

            rechnung_ok = eval(alphametik.replace("=", "=="))

        # jetzt passende Alphametiken suchen oder weitersuchen
        for j in range(1, 10):
            alphametik = alphametik.replace(str(j), ZAHLEN[j - 1])

        loe = loese(alphametik)
        if len(loe) > 0:
            return alphametik # Geschafft, wir haben eines gefunden!

if __name__ == "__main__":
    LOESUNG = loese(ALPHAMETIK)

    if len(LOESUNG) == 0:
        print("Keine Lösungen vorhanden")
    else:
        print("Es konnten folgende Lösungen gefunden werden:")
        print(LOESUNG)

    print(generiere())