Wertetabellen für logische Aussagen (Kleinprojekte)
Schreiben Sie ein Programm, dass einen String entgegennimmt, der einer logischen Aussage entspricht (s. http://de.wikipedia.org/wiki/Aussagenlogik). Dabei sollte die Struktur so aussehen, dass 'nicht' durch ein '-', 'und' durch ein '*' und 'oder' durch ein '+' repräsentiert wird (z.B. '(A*-B)+(-A*B)' bedeutet '(A und nicht B) oder (nicht A und B)' -> Exklusiv-Oder). Weiterhin sollten Variablen durch Großbuchstaben repräsentiert werden und Klammern verneint werden können.
Ihr Programm soll diesen String verstehen und als Ergebnis eine Warheitstabelle für diese Aussage ausgeben. In dieser Warheitstabelle stehen alle Möglichkeiten für die Belegung der Variablen aus der Eingabe und das Ergebnis der Eingabe zu diesen Werten.
Als Tipp für alle, die Python als Programmiersprache nutzen: Es lohnt sich ein Blick auf das pyparsing Modul.
1 Kommentare
2 Lösung(en)
'''Dieses Programm nimmt einen String entgegen der in der logischen
Schreibweise geschrieben wurde und gibt dann eine Tabelle aller moeglichen
Faelle zurueck'''
import pyparsing as pyp
from functools import reduce
from itertools import chain
from collections import OrderedDict
from string import ascii_uppercase as LETTERS
def elements_of(list1, list2):
'''Returns a list containing every elemement of list1 if in list2.'''
return [e for e in list1 if e in list2]
def flatten(l):
'''Makes the list l flat.'''
if isinstance(l, list):
return reduce(lambda x, y: x+y, map(flatten, l))
else:
return [l]
def flatten2d(l):
'''Makes the 2d-list l flat.'''
return list(chain.from_iterable(l))
def replace(old, new, l):
'''Replaces every old in l with new.'''
return [e if e != old else new for e in l]
def replace_all(replacements, l):
'''Does multiple replacements in one step.'''
for o, n in replacements:
l = replace(o, n, l)
return l
def get(l, index, default=None):
'''Like the dict.get, but for lists.'''
try:
return l[index]
except IndexError:
return default
def sort_dict(d):
'''Sorts a dict by the keys of the items and returns a OrderedDict'''
return OrderedDict(sorted(d.items()))
def pretty_matrix(matrix):
'''Returns a pretty formatted matrix (2d)'''
column_widths = []
matrix = [[str(col) for col in row] for row in matrix]
yxmatrix = list(zip(*matrix))
for col in yxmatrix:
column_widths.append(max(len(e) for e in col))
r = ""
for i, row in enumerate(matrix):
for j, col in enumerate(row):
r += ("{:<"+str(column_widths[j])+"} ").format(col)
r += "\n"
return r[:-1]
def join_in_list(l, symbol="|"):
'''Puts the symbol between every two adjacent elements in l'''
return flatten2d(zip(l, [symbol]*len(l)))[:-1]
def combinations(l, length=None, _already=[]):
length = length or len(l)
if len(_already) >= length:
yield _already
else:
for v in l:
for y in combinations(l, length, _already+[v]):
yield y
def print_table(keys, values):
'''Print a table with keys as keywords and values as possible values'''
keys = join_in_list(keys)
values = [join_in_list(line) for line in values]
text = pretty_matrix([keys]+values)
lines = text.split("\n")
lines.insert(1, "-"*(len(lines[0])-1))
print("\n".join(lines))
expr = pyp.Forward()
variable = pyp.Word(LETTERS, exact=1)
negation = pyp.Optional(pyp.Literal("-"))
operator = pyp.oneOf("* +")
atom = negation&variable | \
negation&pyp.Group(pyp.Literal("(").suppress()+
expr+pyp.Literal(")").suppress())
expr << atom + (operator + atom)*(0,1)
class Statement(object):
expression = expr #The expression to check the input
@staticmethod
def parse(string):
return Statement.expression.parseString(string, True).asList()
@staticmethod
def _eval(l):
r = replace_all([("*", "and"), ("+", "or"), ("-", "not")], l)
r = [e if not isinstance(e, list) else "("+Statement._eval(e)+")"
for e in r]
r = " ".join(r)
return r
@staticmethod
def _string(l):
r = [e if not isinstance(e, list) else "("+Statement._string(e)+")"
for e in l]
r = "".join(r)
return r
def __init__(self, string):
try:
if type(string) != str:
raise ValueError()
self.statement = Statement.parse(string)
except (pyp.ParseBaseException, ValueError):
raise ValueError("Invalid input string")
self.variables = sorted(set(variable for variable in
flatten(self.statement)
if variable in LETTERS))
def __str__(self):
return Statement._string(self.statement)
def __repr__(self):
return 'Aussage("'+str(self)+'")'
def __eq__(self, other):
return str(self) == str(other)
def eval(self):
return Statement._eval(self.statement)
def result(self, **kwargs):
try:
return bool(eval(self.eval(), kwargs))
except NameError:
raise ValueError("Es muessen alle Variablen gesetzt werden.")
def truth_table(self):
variable_values = {}
values = []
for combi in combinations([0, 1], len(self.variables)):
variable_values = sort_dict({self.variables[i]:v
for i, v in enumerate(combi)})
values.append(list(variable_values.values())+
[int(self.result(**variable_values))])
return self.variables+["Ergebnis"], values
print("""Dieses Programm gibt fuer eine logische Verknuepfung von Variablen
in der logischen Schreibweise (s. de.wikipedia.org/wiki/Aussagenlogik) eine
Wahrheitstabelle aus.
Gib eine logische Verknuepfung ein.
Schreibe dabei 'nicht' als vorgestelltes '-', 'und' als '*' und 'oder' als '+'.
Achte darauf, dass nur ein Operator (* oder +) pro Klammer und als Variablen-
namen nur Großbuchstaben erlaubt sind.
funktioniert : "-(A*-B)" oder "(-A*B)+(A*-B)"
funktioniert nicht: "A*B*C" oder "A oder B"
""")
while True:
inp = input("logische Aussage: ")
if inp in ["exit", "quit"]:
break
try:
statement = Statement(inp)
except ValueError:
print("Fehlerhafte Eingabe")
continue
else:
print()
print_table(*statement.truth_table())
break
Lösung von: Karl Welzel ()
// eingabemaske
document.write(
'<p>Aussage:<br><input type="text" value="(A*-B)+(-A*B)" id="formula"' +
'onchange="calculate()"></p>' +
'<table>' +
'<td>A…Z</td><td>Variable</td>' +
'</tr><tr>' +
'<td>-</td><td>logisches <i>nicht</i> (¬)</td>' +
'</tr><tr>' +
'<td>*</td><td>logisches <i>und</i> (?)</td>' +
'</tr><tr>' +
'<td>+</td><td>logisches <i>oder</i> (?)</td>' +
'</tr><tr>' +
'<td>( )</td><td>In-/Exklusionen</td></tr>' +
'</table>' +
'<p id="out"></p>'
);
function calculate() {
var proposition = document.getElementById("formula").value,
// netterweise übernehmen wir das mit den großbuchstaben
calculus = proposition.toUpperCase(),
variables = [],
values = [],
out = document.getElementById("out"),
outTable = "",
i;
// setzt die werte ein und liefert das ergebnis
function evaluate() {
var temp = calculus;
for (i = 0; i < values.length; i++) {
var reg = new RegExp(variables[i], "g");
temp = temp.replace(reg, values[i]);
}
return eval(temp);
}
// tabellenzeile schreiben
function writeTableLine() {
var i = 0;
outTable += "<tr>";
while (i < values.length) {
outTable +="<td>";
values[i] == true ? outTable += "w</td>" : outTable += "f</td>";
i++;
}
outTable += "<td>";
evaluate() == true ? outTable += "w</td></tr>" : outTable += "f</td></tr>";
}
// junktoren nach javascript übersetzen
calculus = calculus.replace(/-/g, "!"); // NOT
calculus = calculus.replace(/\*/g, "&&"); // AND
calculus = calculus.replace(/\+/g, "||"); // OR
// großbuchstaben finden und an $variables übergeben
for (i = 0; i < calculus.length; i++)
if (calculus.charCodeAt(i) >= 65 && calculus.charCodeAt(i) <= 90)
variables.push(calculus[i]);
// $variables sortieren und dubletten löschen
variables.sort();
i = 0;
while (i < variables.length) {
if (variables[i] == variables[i + 1]) variables.splice(i + 1, 1);
else i++;
}
// $values füllen, zunächst alle werte auf "wahr"
for (i = 0; i < variables.length; i++) values[i] = true;
// $outTable vorbereiten: tabellenkopf
outTable += '<table><thead><tr>';
for (i = 0; i < variables.length; i++) outTable += '<th>' + variables[i] +
'</th>';
outTable += '<th>' + proposition + '</th></tr></thead>';
// überprüfung, ob die aussage wohlgeformt ist,
// ansonsten tabelle fertigstellen
try {
writeTableLine();
while (eval(values.join("||"))) { // bis alle variablen falsch sind
// permutation von $values
i = values.length - 1;
while (!values[i]) i--;
values[i] = false;
for (i++; i < values.length; i++) values[i] = true;
writeTableLine();
}
}
catch(err) {
out.innerHTML = (err);
}
// ausgabe
out.innerHTML = outTable + "</table>";
} // lissalanda@gmx.at
Lösung von: Lisa Salander (Heidi-Klum-Gymnasium Bottrop)
Verifikation/Checksumme:
Eingabe: (A*-B)+(-A*B)
Ausgabe:
A | B | Ergebnis |
0 | 0 | 1 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
Eingabe: -N
Ausgabe:
N | Ergebnis |
0 | 1 |
1 | 0 |
Eingabe: (*B)+C
Ausgabe: Fehlerhafte Eingabe
Eingabe: (c+d)
Ausgabe: Fehlerhafte Eingabe
Aktionen
Neue Lösung hinzufügen
Bewertung
Durchschnittliche Bewertung:
Kommentare (1)