Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import pandas as pd | |
| import itertools | |
| import re | |
| # --- Eigener LaTeX-Generator für die Schaltfunktion --- | |
| def to_custom_latex(expr_str): | |
| """ | |
| Wandelt den bereinigten Python-Logik-String in sauberen LaTeX-Code | |
| mit \overline{...} für NOT, \oplus für XOR, \wedge für AND und \vee für OR um. | |
| """ | |
| # Temporäre Platzhalter für geklammerte Negationen oder Variablen-Negationen | |
| # Findet Ausdrücke wie ~(A) oder ~A und ersetzt sie durch \overline{...} | |
| # Regulärer Ausdruck fängt Ausdrücke mit Tilde ab | |
| # 1. Negationen mit Klammern: ~(A + B) -> \overline{A + B} | |
| while "~(" in expr_str: | |
| # Einfacher Parser für passende Klammern | |
| start_idx = expr_str.find("~(") | |
| open_brackets = 0 | |
| end_idx = -1 | |
| for i in range(start_idx + 1, len(expr_str)): | |
| if expr_str[i] == "(": | |
| open_brackets += 1 | |
| elif expr_str[i] == ")": | |
| open_brackets -= 1 | |
| if open_brackets == 0: | |
| end_idx = i | |
| break | |
| if end_idx != -1: | |
| inner = expr_str[start_idx+2:end_idx] | |
| # Rekursiver Aufruf für das Innere der Klammer | |
| expr_str = expr_str[:start_idx] + f"\\overline{{{to_custom_latex(inner)}}}" + expr_str[end_idx+1:] | |
| else: | |
| break | |
| # 2. Einfache Variablen-Negation: ~A -> \overline{A} | |
| expr_str = re.sub(r'~([a-zA-Z])', r'\\overline{\1}', expr_str) | |
| # 3. Restliche mathematische Symbole ersetzen | |
| expr_str = expr_str.replace("&", r" \wedge ") | |
| expr_str = expr_str.replace("|", r" \vee ") | |
| expr_str = expr_str.replace("^", r" \oplus ") | |
| return expr_str | |
| # --- Streamlit UI --- | |
| st.set_page_config(page_title="Wahrheitstabelle & Logik-Parser", layout="wide") | |
| st.title("🎛️ Dynamischer Wahrheitstabellen-Generator") | |
| st.markdown(""" | |
| Geben Sie eine Schaltfunktion ein. Folgende Operatoren sind definiert: | |
| * **`*`** : UND ($\land$) | |
| * **`+`** : ODER ($\lor$) | |
| * **`^`** : EXKLUSIV-ODER ($\oplus$) | |
| * **`!`** oder **`~`** : NEGATION ($\overline{A}$) | |
| """) | |
| # Layout: 2 Spalten | |
| col1, col2 = col1, col2 = st.columns([1, 2]) | |
| with col1: | |
| st.subheader("Eingabe & Konfiguration") | |
| # Standard-Beispiel | |
| user_input = st.text_input("Schaltfunktion f:", value="(A ^ B) * !C") | |
| if user_input: | |
| # Eingabe bereinigen und in valides Python-Boole-Format bringen | |
| clean_expr = user_input.replace(" ", "") | |
| clean_expr = clean_expr.replace("+", " | ") | |
| clean_expr = clean_expr.replace("*", " & ") | |
| clean_expr = clean_expr.replace("!", "~") | |
| # Erkannte Variablen extrahieren | |
| detected_vars = sorted(list(set(re.findall(r'[a-zA-Z]', clean_expr)))) | |
| if not detected_vars: | |
| st.error("Keine Variablen (Buchstaben) in der Funktion gefunden.") | |
| st.stop() | |
| st.success("Funktion erfolgreich interpretiert!") | |
| # --- Dynamische Sortierung der Spalten --- | |
| st.markdown("### Spaltenreihenfolge") | |
| ordered_vars = st.multiselect( | |
| "Reihenfolge der Variablen festlegen:", | |
| options=detected_vars, | |
| default=detected_vars | |
| ) | |
| # Validierung der Auswahl | |
| missing_vars = set(detected_vars) - set(ordered_vars) | |
| if missing_vars: | |
| st.warning(f"Bitte alle Variablen auswählen. Es fehlen noch: {', '.join(missing_vars)}") | |
| st.stop() | |
| with col2: | |
| st.subheader("Darstellung & Wahrheitstabelle") | |
| if user_input and detected_vars: | |
| # --- LaTeX Darstellung (Eigener Parser ohne SymPy-Winkel-Zwang) --- | |
| st.markdown("#### Logische Formel (LaTeX)") | |
| latex_formula = to_custom_latex(clean_expr) | |
| st.latex(f"f = {latex_formula}") | |
| # --- Wahrheitstabelle generieren via Python eval() --- | |
| st.markdown("#### Wahrheitstabelle") | |
| num_vars = len(ordered_vars) | |
| combinations = list(itertools.product([0, 1], repeat=num_vars)) | |
| table_data = [] | |
| for combo in combinations: | |
| # Zustand für die aktuelle Zeile als Dictionary (z.B. {'A': 0, 'B': 1}) | |
| var_values = dict(zip(ordered_vars, combo)) | |
| # Python-konformen String für die Auswertung vorbereiten. | |
| # Da Python mit '&', '|', '~', '^' nativ auf Integers (0 und 1) bitweise rechnet, | |
| # können wir den String direkt evaluieren, wenn wir die Variablen ersetzen. | |
| eval_expr = clean_expr | |
| for var, val in var_values.items(): | |
| # Nutze Regex-Word-Boundaries, damit 'A' nicht in 'and' oder längeren Ausdrücken ersetzt wird | |
| eval_expr = re.sub(r'\b' + var + r'\b', str(val), eval_expr) | |
| try: | |
| # Berechne das Ergebnis (0 oder 1). | |
| # Das bitweise NOT (~) von 0 ist in Python -1, von 1 ist es -2. | |
| # Daher maskieren wir das Ergebnis am Ende mit & 1, um immer 0 oder 1 zu erhalten. | |
| result = eval(eval_expr) & 1 | |
| except Exception as e: | |
| st.error(f"Fehler bei der Tabellenberechnung: {e}") | |
| st.stop() | |
| row = list(combo) + [result] | |
| table_data.append(row) | |
| # DataFrame erstellen | |
| column_names = ordered_vars + ["f"] | |
| df = pd.DataFrame(table_data, columns=column_names) | |
| # Tabelle anzeigen | |
| st.dataframe( | |
| df.style.format(hyperlinks="to_html") | |
| .background_gradient(subset=["f"], cmap="Blues", low=0.1, high=0.05), | |
| use_container_width=True, | |
| hide_index=True | |
| ) |