update
This commit is contained in:
@@ -6,14 +6,17 @@ import unicodedata
|
||||
|
||||
from . import config
|
||||
|
||||
# Sprache kommt aus config.SPRACHE (Lektion 106) — kein hartkodiertes Deutsch
|
||||
try:
|
||||
import Stemmer
|
||||
_stemmer = Stemmer.Stemmer("german")
|
||||
_name = config.STEMMER_NAME.get(config.SPRACHE)
|
||||
_stemmer = Stemmer.Stemmer(_name) if _name else None
|
||||
except ImportError: # Fallback ohne C-Extension: ungestemmt
|
||||
_stemmer = None
|
||||
|
||||
_WORT_RE = re.compile(r"[a-zäöüß0-9]+")
|
||||
_NEGATION = {"nicht", "kein", "keine", "keinen", "keiner", "nie", "niemals", "ohne"}
|
||||
_WORT_RE = re.compile(r"\w+", re.UNICODE) # alle Schriften, nicht nur Latein
|
||||
_NEGATION = config.NEGATIONEN.get(config.SPRACHE, set())
|
||||
_NEG_PRAEFIX = config.NEGATIONS_PRAEFIX.get(config.SPRACHE, "\0")
|
||||
|
||||
|
||||
def norm(text: str) -> str:
|
||||
@@ -37,9 +40,10 @@ def jaccard(a: str, b: str, gestemmt: bool = True) -> float:
|
||||
|
||||
|
||||
def negations_menge(text: str) -> frozenset:
|
||||
"""Antonyme messen 0.91-0.95 Cosinus (Lektion 31) — harte Merge-Vorbedingung."""
|
||||
"""Antonyme messen 0.91-0.95 Cosinus (Lektion 31) — harte Merge-Vorbedingung.
|
||||
Lexikon je Sprache; ohne Eintrag ist der Guard bewusst aus (dokumentiert)."""
|
||||
t = tokens(text)
|
||||
return frozenset(w for w in t if w in _NEGATION or w.startswith("nicht"))
|
||||
return frozenset(w for w in t if w in _NEGATION or w.startswith(_NEG_PRAEFIX))
|
||||
|
||||
|
||||
def titel_kern(titel: str) -> str:
|
||||
@@ -81,19 +85,34 @@ def ueberlappung(a: tuple[int, int], b: tuple[int, int]) -> float:
|
||||
return schnitt / kuerzer if kuerzer > 0 else 0.0
|
||||
|
||||
|
||||
_SATZ_RE = re.compile(r"(?<=[.!?])\s+(?=[A-ZÄÖÜ])")
|
||||
_SATZ_RE = re.compile(r"(?<=[.!?])\s+")
|
||||
|
||||
|
||||
def satz_split(text: str) -> list[str]:
|
||||
"""Terminator + Whitespace; Teile, die klein weitergehen (Abkürzungen,
|
||||
„z. B."), werden wieder angefügt — Unicode-Groß statt [A-ZÄÖÜ]-Klasse."""
|
||||
saetze = []
|
||||
for absatz in text.split("\n"):
|
||||
absatz = absatz.strip()
|
||||
if not absatz or absatz.startswith(("#", "```", "|", "<!--")):
|
||||
continue
|
||||
saetze += [s.strip() for s in _SATZ_RE.split(absatz) if s.strip()]
|
||||
for teil in _SATZ_RE.split(absatz):
|
||||
teil = teil.strip()
|
||||
if not teil:
|
||||
continue
|
||||
if saetze and teil[0].islower():
|
||||
saetze[-1] += " " + teil
|
||||
else:
|
||||
saetze.append(teil)
|
||||
return saetze
|
||||
|
||||
|
||||
def paar_liste(paare: list[tuple[str, str]]) -> str:
|
||||
"""EIN Paar-Rendering für alle Paar-Urteils-Aufgaben (dedup, redundanz)."""
|
||||
return "\n\n".join(f"PAAR {i + 1}:\nA: {a}\nB: {b}"
|
||||
for i, (a, b) in enumerate(paare))
|
||||
|
||||
|
||||
# ── Positions-Maps für Anker-Suche ──
|
||||
|
||||
def _map_bauen(text: str, wandler) -> tuple[str, list[int]]:
|
||||
|
||||
Reference in New Issue
Block a user