diff --git a/Quellcodes/AuS_A_DFA_Implementieren/.gitignore b/Quellcodes/AuS_A_DFA_Implementieren/.gitignore
new file mode 100644
index 0000000..2cc0cb6
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/.gitignore
@@ -0,0 +1,7 @@
+**/*.sh
+**/*.class
+**/*.ctxt
+repo.adoc
+repo_subtree.adoc
+/alt
+/hide
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lehrer/.classpath b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/.classpath
new file mode 100644
index 0000000..a177209
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lehrer/.project b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/.project
new file mode 100644
index 0000000..5557916
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/.project
@@ -0,0 +1,17 @@
+
+
+ tabellen-dfa
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lehrer/BinaerzahlenPruefer.java b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/BinaerzahlenPruefer.java
new file mode 100644
index 0000000..17f7550
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/BinaerzahlenPruefer.java
@@ -0,0 +1,127 @@
+/**
+ * Implementiert einen DEA, der 0/1-Folgen darauf prüft, ob
+ * sie "gültige Binärzahlen" darstellen.
+ * Gültige Binärzahlen im Sinne dieser Aufgabe beginnen mit
+ * einer 1, auf die eine beliebige Folge von 0/1 folgt. Die
+ * einzelne Ziffer 0 ist ebenfalls erlaubt, jedoch keine
+ * Binärzahlen mit "überflüssigen" führenden Nullen. Die
+ * Binärzahl darf außerdem ein Vorzeichen führen (muss aber
+ * nicht).
+ *
+ * Gültig sind beispielsweise:
+ * 1
+ * 0
+ * 101
+ * 11
+ * 10
+ * 1110010010
+ * 111
+ * -1
+ * 1000000000
+ * +1
+ * 1001001100
+ *
+ * Ungültig sind beispielsweise:
+ * 123
+ * 00
+ * hallo
+ * 0000000011111
+ * 1+1
+ * Binärzahl
+ * abc
+ * 321
+ * 01010101010101
+ * 0101
+ * 01
+ * 0101010101
+ *
+ * @author Urs Lautebach
+ * @version 2021-Januar
+ */
+
+/* Lehrertipps:
+ * 1.
+ * Diese Beispielaufgabe kann bei Bedarf noch vereinfacht
+ * werden, indem zunächst die Vorzeichen weggelassen werden.
+ * Allerdings passen dann die mitgelieferten Unit-Tests nicht!
+ *
+ * 2.
+ * Viele Schüler muss man daran erinnern, beim Testen gezielt
+ * auch ungültige Wörter zu verwenden.
+ *
+ * 3.
+ * Die Lösung setzt etwas Erfahrung mit mehrdimensionalen
+ * Arrays voraus.
+ */
+
+public class BinaerzahlenPruefer extends EndlicherAutomat {
+ /* Bei der Implementierung dieser Klasse muss man nur
+ * die Attribute alphabet, uebergaenge und endzustaende
+ * geeignet festlegen -- alles andere macht die
+ * Vaterklasse "EndlicherAutomat.java".
+ *
+ * Dort ist auch erklärt, wie die Nummerierung der
+ * Zustände, des Startzustand und der Übergangstabelle
+ * zu verstehen sind.
+ */
+
+ // Transitionstabelle anlegen mit den Zuständen auf der
+ // senkrechten und den Alphabetzeichen auf der Rechtsachse:
+ private static final int[][] transiTabelle = new int [][] {
+ /* die erste Zeile enthaelt die Sprünge heraus aus
+ * dem Fehlerzustand 0 (den der Automat ja aber gar
+ * nicht wieder verlassen darf), die also alle 0 sind:
+ */
+ { 0,0,0,0 },
+ { 2,2,3,4 },
+ { 0,0,3,4 },
+ { 0,0,0,0 },
+ { 0,0,4,4 },
+ };
+
+ // Alphabet für diesen Automaten als char[]
+ private static final char[] binaerzAlph = new char[] {
+ '-', '+', '0', '1'
+ };
+
+ // Menge der Endzustände:
+ private static final int[] endzustaende = new int[] {
+ 3, 4
+ };
+
+ /**
+ * Konstruktor für einen BinaerzahlenPruefer:
+ */
+ public BinaerzahlenPruefer() {
+ // Aufruf des super-Konstruktors:
+ super(binaerzAlph, transiTabelle, endzustaende);
+ }
+
+ /**
+ * Die main-Methode erlaubt den Aufruf von
+ * Binaerzahlenpruefer von der Kommandozeile aus mit
+ * mehreren zu testenden Strings:
+ *
+ * java BinaerzahlenPruefer 1110101 0001 +1010 abc
+ *
+ * Die Ausgabe lautet dann
+ * Akzeptiert: "1110101" ist ein gueltiges Binärwort.
+ * FEHLER! "0001" ist kein gültiges Binärwort!
+ * Akzeptiert: "+1010" ist ein gueltiges Binärwort.
+ * FEHLER! "abc" ist kein gültiges Binärwort!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat binaerzahlenDFA = new BinaerzahlenPruefer();
+
+ for(String wort : args) {
+ if(binaerzahlenDFA.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" ist ein gültiges Binärwort.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" ist kein gültiges Binärwort!");
+ }
+ }
+ }
+}
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lehrer/DEA_BeispieleTest.java b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/DEA_BeispieleTest.java
new file mode 100644
index 0000000..d544eb0
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/DEA_BeispieleTest.java
@@ -0,0 +1,104 @@
+import static org.junit.Assert.*;
+import org.junit.Test;
+public class DEA_BeispieleTest {
+
+ public DEA_BeispieleTest() {
+ }
+
+ @Test
+ public void testBinaerzahlenPruefer() {
+ BinaerzahlenPruefer binZPruefer = new BinaerzahlenPruefer();
+ assertTrue(binZPruefer.gehoertZuSprache("1"));
+ assertTrue(binZPruefer.gehoertZuSprache("0"));
+ assertTrue(binZPruefer.gehoertZuSprache("+1"));
+ assertTrue(binZPruefer.gehoertZuSprache("+0"));
+ assertTrue(binZPruefer.gehoertZuSprache("-1"));
+ assertTrue(binZPruefer.gehoertZuSprache("-0"));
+ assertTrue(binZPruefer.gehoertZuSprache("11"));
+ assertTrue(binZPruefer.gehoertZuSprache("10"));
+ assertTrue(binZPruefer.gehoertZuSprache("+11"));
+ assertTrue(binZPruefer.gehoertZuSprache("-11"));
+ assertTrue(binZPruefer.gehoertZuSprache("+10"));
+ assertTrue(binZPruefer.gehoertZuSprache("1111"));
+ assertTrue(binZPruefer.gehoertZuSprache("1000"));
+ assertTrue(binZPruefer.gehoertZuSprache("10100101010111000"));
+ assertTrue(binZPruefer.gehoertZuSprache("1111111"));
+
+ assertFalse(binZPruefer.gehoertZuSprache(""));
+ assertFalse(binZPruefer.gehoertZuSprache("+"));
+ assertFalse(binZPruefer.gehoertZuSprache("-"));
+ assertFalse(binZPruefer.gehoertZuSprache("x"));
+ assertFalse(binZPruefer.gehoertZuSprache("binärzahl"));
+ assertFalse(binZPruefer.gehoertZuSprache("00"));
+ assertFalse(binZPruefer.gehoertZuSprache("+00"));
+ assertFalse(binZPruefer.gehoertZuSprache("0+0"));
+ assertFalse(binZPruefer.gehoertZuSprache("123"));
+ assertFalse(binZPruefer.gehoertZuSprache("0011"));
+ assertFalse(binZPruefer.gehoertZuSprache("011"));
+ assertFalse(binZPruefer.gehoertZuSprache("111111+"));
+ assertFalse(binZPruefer.gehoertZuSprache("000000+"));
+ assertFalse(binZPruefer.gehoertZuSprache("1+1"));
+ assertFalse(binZPruefer.gehoertZuSprache("0+1"));
+ assertFalse(binZPruefer.gehoertZuSprache("1+0"));
+ }
+
+ @Test
+ public void testMailadressenChecker() {
+ MailadressenChecker mailAdrPruefer = new MailadressenChecker();
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.bbbb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b.b.b@bbb.bbb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("bbbbbb@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.b.b.b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("...@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("...bbb@bb.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("bbb...@bb.bb"));
+
+ assertFalse(mailAdrPruefer.gehoertZuSprache(""));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("@"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("b@b.b@bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("@bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@.."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@bb.b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@bb.bb.b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb.bb.bb.bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache(
+ "bbb@bb.bb.bb@bb.bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb..bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb.bbb.."));
+ }
+
+ @Test
+ public void test007Sucher() {
+ KGB_007Sucher detektiv = new KGB_007Sucher();
+ assertTrue(detektiv.gehoertZuSprache("007"));
+ assertTrue(detektiv.gehoertZuSprache("1007"));
+ assertTrue(detektiv.gehoertZuSprache("0071"));
+ assertTrue(detektiv.gehoertZuSprache("007007"));
+ assertTrue(detektiv.gehoertZuSprache("00007"));
+ assertTrue(detektiv.gehoertZuSprache("0000712"));
+ assertTrue(detektiv.gehoertZuSprache("2121200777"));
+ assertTrue(detektiv.gehoertZuSprache("0077"));
+ assertTrue(detektiv.gehoertZuSprache("212121007000000"));
+ assertTrue(detektiv.gehoertZuSprache("00712772712717"));
+
+ assertFalse(detektiv.gehoertZuSprache(""));
+ assertFalse(detektiv.gehoertZuSprache("0"));
+ assertFalse(detektiv.gehoertZuSprache("1"));
+ assertFalse(detektiv.gehoertZuSprache("2"));
+ assertFalse(detektiv.gehoertZuSprache("7"));
+ assertFalse(detektiv.gehoertZuSprache("07"));
+ assertFalse(detektiv.gehoertZuSprache("001"));
+ assertFalse(detektiv.gehoertZuSprache("002"));
+ assertFalse(detektiv.gehoertZuSprache("000"));
+ assertFalse(detektiv.gehoertZuSprache("001002"));
+ assertFalse(detektiv.gehoertZuSprache("7001"));
+ assertFalse(detektiv.gehoertZuSprache("0707"));
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lehrer/EndlicherAutomat.java b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/EndlicherAutomat.java
new file mode 100644
index 0000000..10f9b40
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/EndlicherAutomat.java
@@ -0,0 +1,212 @@
+/**
+ * Implementiert einen tabellengetriebenen endlichen Automaten.
+ * Instanzen dieser Klasse sind DEAs, die Wörter über einem
+ * vorgegebenen Alphabet akzeptieren oder ablehnen können.
+ *
+ * Die Aufgabe wurde vom schriftlichen Abitur 2020 in
+ * Baden-Württemberg inspiriert.
+ *
+ * @author Urs Lautebach
+ * @version 2020-Oktober
+ */
+/* Lehrertipps:
+ *
+ * 1.
+ * Die Implementierung setzt etwas Erfahrung mit mehrdimensionalen
+ * Arrays sowie die Handhabung von String und char voraus.
+ *
+ * 2.
+ * Die Schüler sollten vor der Implementierung dieser Klasse
+ * schon Transitionstabellen von Hand erstellt (in der
+ * Regel aus einem Übergangsgraphen) und idealerweise auch
+ * schon "Läufe" der so beschriebenen DEAs von Hand simuliert
+ * haben. Wenn sie das sogar ohne den Übergangsgraphen tun,
+ * entsteht leichter die richtige Grundvorstellung davon, warum
+ * dieser "allgemeine" DEA beliebige konkrete DEAs simulieren
+ * kann.
+ */
+public class EndlicherAutomat {
+ private int [][] uebergaenge = null;
+ private int[] endzustaende = null;
+ private char[] alphabet = null;
+
+ /**
+ * Konstruiert einen tabellengetriebenen DEA. Nach dem
+ * erfolgreichen Aufruf dieses Konstruktors kann man den DEA
+ * anschließend durch einen Aufruf der Methode
+ * gehoertZuSprache(String):boolean
+ * beliebig viele Wörter testen lassen.
+ *
+ * @param tabelle Transitionstabelle des DEA. Die erste
+ * Dimension bezeichnet die Zustände; die zweite Dimension die
+ * Eingabezeichen. Die Einträge der Tabelle bezeichnen jeweils
+ * den Zustand, in den der Automat (abhängig vom vorherigen
+ * Zustand und der Eingabe) wechseln soll.
+ *
+ * Der Zustand 0 gilt als Fehlerzustand. Zustand 1 ist immer
+ * Startzustand (so dass der Startzustand, anders als bei der
+ * formalen Beschreibung eines DEA, nicht explizit angegeben
+ * werden muss).
+ *
+ * @param finalStates Ein int[], das die Endzustände enthält.
+ *
+ * @param alphabet ein Array von char, das das Alphabet des
+ * Automaten enthält. Die Reihenfolge der Zeichen im Alphabet
+ * muss der Reihenfolge der Zeichen an der entsprechenden
+ * Achse der Transitionstabelle entsprechen.
+ */
+ EndlicherAutomat(final char[] alphabet,
+ final int[][] uebergaenge, final int[] endzustaende ) {
+ this.alphabet = alphabet;
+ this.uebergaenge = uebergaenge;
+ this.endzustaende = endzustaende;
+ // Die Methode plausibilitaetPruefen ist fertig vorgegeben;
+ // sie fängt einige offensichtliche Fehler ab:
+ plausibilitaetPruefen();
+ }
+
+ /**
+ * Die Methode prüft, ob die Attribute transitionstabelle,
+ * alphabet und endzustaende zueinander passen. Sie ist fertig
+ * implementiert und dafür gedacht, am Ende des Konstruktors
+ * aufgerufen zu werden.
+ */
+ private void plausibilitaetPruefen() {
+ if (uebergaenge == null) {
+ throw new IllegalArgumentException(
+ "Die Übergangstabelle ist null oder leer!");
+ }
+ if (alphabet == null) {
+ throw new IllegalArgumentException(
+ "Das Alphabet ist null oder leer!");
+ }
+ if (endzustaende == null) {
+ throw new IllegalArgumentException(
+ "endzustaende ist null oder leer!");
+ }
+ int tabelleHoehe = this.uebergaenge.length;
+ int tabelleBreite = uebergaenge[0].length;
+ // Hat die Übergangstabelle eine Zeile pro Alphabetzeichen?
+ if (tabelleBreite != alphabet.length) {
+ throw new IllegalArgumentException("Das Alphabet hat " +
+ alphabet.length + " Zeichen, die " +
+ " Übergangstabelle aber " + tabelleBreite +
+ " Spalten!");
+ }
+ // Sind alle Zeilen der Transitionstabelle gleich lang?
+ for (int[] zeile : uebergaenge) {
+ if (zeile.length != tabelleBreite) {
+ throw new IllegalArgumentException(
+ "Übergangstabelle ist nicht rechteckig!");
+ }
+ }
+ // Hat einer der Endzustände eine unplausible Nummer?
+ for (int zustand : endzustaende) {
+ if (zustand < 1 || zustand > tabelleHoehe - 1) {
+ throw new IllegalArgumentException(
+ "Der Endzustand " + zustand +
+ " kommt in der Übergangstabelle nicht vor!");
+ }
+ }
+ }
+
+ /**
+ * Ermittelt die Nummer (den Index) des angegebenen Zeichens
+ * innerhalb des Alphabetes dieses Automaten.
+ *
+ * @param input Zeichen, dessen Position ermittelt werden soll.
+ * @returns Position des Zeichens input innerhalb des Alphabets
+ * dieses Automaten; oder -1, falls es im Alphabet nicht
+ * enthalten ist.
+ */
+ public int indexImAlphabet(char input) {
+ /* Man geht das Alphabet durch und prüft, welches seiner
+ * Zeichen dem "input" entspricht. Falls man es findet,
+ * gibt man dessen Index zurück.
+ */
+ for (int index = 0; index < alphabet.length; index++) {
+ if (input == alphabet[index])
+ return index;
+ }
+ return -1;
+ }
+
+ /**
+ * Überprüft, ob der Zustand mit der übergebenen
+ * Zustandsnummer einer der Endzustände dieses Automaten ist.
+ *
+ * @param nr Nummer des fraglichen Zustandes.
+ * @return ob der Zustand ein Endzustand ist.
+ */
+ public boolean istEndzustand(int nr) {
+ for (int endzustand : endzustaende) {
+ // Gehe durch alle Endzustände. Wenn nr einer ist...
+ if (nr == endzustand) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Die Methode kann mit einem String als Parameter aufgerufen
+ * werden, was oft bequemer ist als ein char[].
+ *
+ * @param s String mit dem zu prüfenden Wort.
+ * @return ob s von diesem Automaten erkannt wird.
+ */
+ public boolean gehoertZuSprache(String s) {
+ // Hier ist nichts zu implementieren.
+ return gehoertZuSprache(s.toCharArray());
+ }
+
+ /**
+ * Übergibt dem DEA ein ganzes Wort und ermittelt, ob er es
+ * akzeptiert oder nicht.
+ *
+ * @param eingabe Die komplette zu analysierende Eingabe als
+ * char[].
+ * @returns true, wenn das Wort vom DEA akzeptiert wird;
+ * false sonst.
+ */
+ public boolean gehoertZuSprache(final char[] wort) {
+ /*
+ * Um zu prüfen, ob wort akzeptiert wird, muss der DEA...
+ *
+ * - in Zustand 1 beginnen;
+ *
+ * - das Eingabewort Zeichen für Zeichen durchgehen;
+ *
+ * - prüfen, ob das Zeichen im Alphabet vorkommt;
+ *
+ * - nach dessen Position im Alphabet und altem Zustand
+ * einen neuen Zustand aus der Tabelle uebergaenge wählen;
+ *
+ * - false antworten, wenn er im Fehlerzustand landet,
+ *
+ * - am Schluss der Eingabe entscheiden, ob der erreichte
+ * Zustand ein Endzustand ist.
+ */
+ // Startzustand ist immer Nr. 1:
+ int zustand = 1;
+ // Gehe durch alle Zeichen durch:
+ for (char zeichen : wort) {
+ int alphIndex = indexImAlphabet(zeichen);
+ // Falls das Zeichen gar nicht im Alphabet ist...:
+ if (alphIndex == -1) {
+ return false;
+ } else {
+ // wechsle in neuen Zustand:
+ zustand = uebergaenge[zustand][alphIndex];
+ }
+ // Bin ich im Fehlerzustand?
+ if (zustand == 0) {
+ return false;
+ }
+ }
+ // Die Eingabe ist verbraucht. Falls der aktuelle Zustand
+ // ein Endzustand ist, akzeptieren wir die Eingabe:
+ return istEndzustand(zustand);
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lehrer/KGB_007Sucher.java b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/KGB_007Sucher.java
new file mode 100644
index 0000000..25cd63b
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/KGB_007Sucher.java
@@ -0,0 +1,106 @@
+/**
+ * Dieser DFA erkennt Ziffernfolgen, in denen sich irgendwo
+ * James Bond versteckt hat -- in denen also die Folge 007
+ * vorkommt.
+ *
+ * Die folgenden Ziffernfolgen sollen beispielsweise akzeptiert
+ * werden:
+ *
+ * 12107117700710012021,
+ * 007,
+ * 0071121727,
+ * 0000000071121727,
+ * 007007007007,
+ * 1121271201212007.
+ *
+ * Die folgenden Ziffernfolgen sollen nicht akzeptiert werden:
+ *
+ * 12107110710012021,
+ * 07,
+ * 00,
+ * 07112172,
+ * 1121271201212000.
+
+ * Um den Automaten und vor allem die Übergangstabelle
+ * übersichtlicher zu halten, verwendet er nicht alle Ziffern,
+ * sondern lediglich das eingeschränkte Alphabet {0, 1, 2, 7}.
+ *
+ * Es empfiehlt sich, den Automaten zunächst zu zeichnen,
+ * die Übergangstabelle auf Papier zu erstellen und dann zu
+ * programmieren.
+ *
+ * @author Urs Lautebach
+ * @version 2020-Okt
+ */
+/* Lehrertipps:
+ * 1.
+ * Viele Schüler muss man daran erinnern, beim Testen gezielt
+ * auch ungültige Wörter zu verwenden.
+ *
+ * 2.
+ * Die Lösung setzt etwas Erfahrung mit mehrdimensionalen
+ * Arrays voraus.
+ *
+ * 3.
+ * Die 007-Aufgabe ist ein Beispiel für das sogenannte
+ * "Substring-Problem", das im 2016er Informatik-Bildungsplan
+ * für Baden-Württemberg ausdrücklich erwähnt wird.
+ */
+
+public class KGB_007Sucher extends EndlicherAutomat {
+ /* Bei der Implementierung dieser Klasse muss man nur
+ * die Attribute alphabet, uebergaenge und endzustaende
+ * geeignet festlegen -- alles andere macht die
+ * Vaterklasse.
+ */
+ private static final char[] alphabet = new char[] {
+ '0', '1', '2', '7'
+ };
+
+ private static final int[][] uebergaenge = new int[][] {
+ { 0, 0, 0, 0 },
+ { 2, 1, 1, 1 },
+ { 3, 1, 1, 1 },
+ { 3, 1, 1, 4 },
+ { 4, 4, 4, 4 },
+ };
+
+ private static final int[] endzustaende = new int[] {
+ 4
+ };
+
+ /**
+ * Instanziiert einen KGB_007Sucher-DFA.
+ */
+ KGB_007Sucher() {
+ // Aufruf des super-Konstruktors:
+ super(alphabet, uebergaenge, endzustaende);
+ }
+
+ /**
+ * Die main-Methode erlaubt den Aufruf des
+ * Binaerzahlenpruefers von der Kommandozeile aus mit:
+ *
+ * java KGB_007Sucher 127007117 1717771021
+ *
+ * Die Ausgabe lautet dann
+ *
+ * Akzeptiert: "127007117" enthält 007.
+ * FEHLER! "1717771021" enthält kein 007!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat fahnder = new KGB_007Sucher();
+
+ for(String wort : args) {
+ if(fahnder.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" enthält 007.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" enthält kein 007!");
+ }
+ }
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lehrer/MailadressenChecker.java b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/MailadressenChecker.java
new file mode 100644
index 0000000..b3864c4
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/MailadressenChecker.java
@@ -0,0 +1,114 @@
+/**
+ * Die Klasse implementiert einen DEA für die Überprüfung äußerst
+ * einfacher Mailadressen, die nur aus dem Buchstaben b, Punkten
+ * und dem at-Zeichen bestehen dürfen. Der Nutzername darf fast
+ * beliebig aufgebaut sein; die Domain muss mindestens zweistufig
+ * sein und die Toplevel-Domain muss mindestens zwei Zeichen haben.
+ *
+ * Gültig sind damit beispielsweise:
+ * b@b.bb
+ * b@b.bbbb
+ * b.b.b@bbb.bbb
+ * bbbbbb@b.bb
+ * b@b.b.b.b.bb
+ * ...@b.bb
+ * ...bbb@bb.bb
+ * bbb...@bb.bb
+ *
+ * Ungültig sind beispielsweise:
+ * .
+ * b
+ * @
+ * bb@
+ * b@b.b@bbb
+ * b@b.b@bb.b
+ * @bb
+ * bb@.
+ * bb@..
+ *
+ * Tatsächlich ist die Überprüfung realer Mailadressen wesentlich
+ * komlizierter als in diesem Beispiel.
+ *
+ * @author Urs Lautebach
+ * @version 2021-Janar
+ *
+ */
+/* Lehrertipps:
+ * 1.
+ * Mit einem vollständigen Buchstabenalphabet wird die
+ * Transitionstabelle schnell unhandlich und besteht dann doch
+ * fast nur aus identischen Transitionen. Die Einschränkung
+ * auf einen einzigen Buchstaben erlaubt die Konzentration auf
+ * interessantere Fragen.
+ *
+ * 2.
+ * Diese Aufgabe kann bei Bedarf noch vereinfacht werden, indem
+ * einzelne Anforderungen weggelassen werden.
+ * Allerdings passen dann die mitgelieferten Unit-Tests nicht!
+ *
+ * 3.
+ * Viele Schüler muss man daran erinnern, beim Testen gezielt
+ * auch ungültige Wörter zu verwenden.
+ *
+ * 4.
+ * Die Lösung setzt etwas Erfahrung mit mehrdimensionalen
+ * Arrays voraus.
+ */
+public class MailadressenChecker extends EndlicherAutomat {
+ /* Bei der Implementierung dieser Klasse muss man nur
+ * die Attribute alphabet, uebergaenge und endzustaende
+ * geeignet festlegen -- alles andere macht die
+ * Vaterklasse.
+ */
+
+ private static final char[] alphabet = new char[] {
+ 'b', '.', '@'
+ };
+ private static final int[][] transitionen = new int[][] {
+ { 0, 0, 0 },
+ { 2, 2, 0 },
+ { 2, 2, 3 },
+ { 4, 0, 0 },
+ { 4, 5, 0 },
+ { 6, 0, 0 },
+ { 7, 5, 0 },
+ { 7, 5, 0 },
+ };
+
+ private static final int[] endzustaende = new int[] {
+ 7
+ };
+
+ MailadressenChecker() {
+ // Aufruf des super-Konstruktors:
+ super(alphabet, transitionen, endzustaende);
+ }
+
+
+ /**
+ * Die main-Methode erlaubt den Aufruf des
+ * Binaerzahlenpruefers von der Kommandozeile mit beliebig
+ * vielen zu prüfenden Strings:
+ * java MailadressenChecker bbb.b@bb.bb a@b@c
+ *
+ * Die Ausgabe lautet dann
+ *
+ * Akzeptiert: "bbb.b@bb.bb" ist eine gültige Mailadresse.
+ * FEHLER! "a@b@c" ist als Mailadresse ungültig!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat checker = new MailadressenChecker();
+
+ for(String wort : args) {
+ if(checker.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" ist eine gültige Mailadresse.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" ist als Mailadresse ungültig!");
+ } // end if
+ } // end for
+ } // end main
+} // end class
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lehrer/README.md b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/README.md
new file mode 100644
index 0000000..c2be6f0
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/README.md
@@ -0,0 +1,3 @@
+# Tabellen Dfa
+
+Implementierung eines allgemeinen tabellengetriebenen DFA als Programmieraufgabe (samt einiger Beispiel-DFA).
\ No newline at end of file
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lehrer/lehrkraft-liesmich.txt b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/lehrkraft-liesmich.txt
new file mode 100644
index 0000000..63abfcd
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/lehrkraft-liesmich.txt
@@ -0,0 +1,36 @@
+Dieser Ordner enthält ein Java-Projekt, in dem die Implementierung
+eines tabellengetriebenen DEA geübt wird. Es kann mit BlueJ oder
+einem anderen Java-Werkzeug bearbeitet werden.
+
+Das Projekt liegt in drei Ausstattungen vor; Sie als Lehrkraft
+entscheiden, welche Variante(n) Sie den Schülern vorlegen.
+
+Der Ordner...
+
+.skelett
+--------
+enthält das Rohprojekt ohne Lösungshinweise oder Tipps, aber mit
+Spezifikation, Arbeitsanweisungen und JUnit-Test. Das Projekt
+sollte fehlerfrei compilieren und lauffähig sein, aber natürlich
+schlagen die Tests fehl.
+
+.tipp
+-----
+enthält das gleiche Projekt, aber zusätzlich mit Tipps für die
+Bearbeitung durch Schüler.
+
+.lsg
+----
+enthält die Musterlösung des fertig ausprogrammierten Projekts.
+Hier sollten alle Tests erfolgreich laufen.
+
+Zu bearbeiten sind die Datei EndlicherAutomat.java, in der der
+eigentliche Tabellenmechanismus implementiert wird, und eine Auswahl
+der Beispiel-DFA für
+
+Mailadressen
+007-Suche
+oder Binärzahlen
+
+bzw. eigene DFA für andere Sprachen nach Wahl.
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lehrer/package.bluej b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/package.bluej
new file mode 100644
index 0000000..a54f5f2
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lehrer/package.bluej
@@ -0,0 +1,75 @@
+#BlueJ package file
+dependency1.from=DFA_BeispieleTest
+dependency1.to=BinaerzahlenPruefer
+dependency1.type=UsesDependency
+dependency2.from=DFA_BeispieleTest
+dependency2.to=MailadressenChecker
+dependency2.type=UsesDependency
+dependency3.from=DFA_BeispieleTest
+dependency3.to=KGB_007Sucher
+dependency3.type=UsesDependency
+editor.fx.0.height=0
+editor.fx.0.width=0
+editor.fx.0.x=0
+editor.fx.0.y=0
+objectbench.height=119
+objectbench.width=770
+package.divider.horizontal=0.5785785785785785
+package.divider.vertical=0.7519685039370079
+package.editor.height=375
+package.editor.width=643
+package.editor.x=100
+package.editor.y=100
+package.frame.height=600
+package.frame.width=800
+package.numDependencies=3
+package.numTargets=6
+package.showExtends=true
+package.showUses=true
+project.charset=UTF-8
+readme.height=58
+readme.name=@README
+readme.width=47
+readme.x=10
+readme.y=10
+target1.height=62
+target1.name=bin
+target1.type=PackageTarget
+target1.width=80
+target1.x=70
+target1.y=10
+target2.height=50
+target2.name=KGB_007Sucher
+target2.showInterface=false
+target2.type=ClassTarget
+target2.width=140
+target2.x=10
+target2.y=130
+target3.height=50
+target3.name=DFA_BeispieleTest
+target3.showInterface=false
+target3.type=UnitTestTargetJunit4
+target3.width=160
+target3.x=180
+target3.y=240
+target4.height=50
+target4.name=EndlicherAutomat
+target4.showInterface=false
+target4.type=ClassTarget
+target4.width=160
+target4.x=180
+target4.y=30
+target5.height=50
+target5.name=MailadressenChecker
+target5.showInterface=false
+target5.type=ClassTarget
+target5.width=180
+target5.x=170
+target5.y=130
+target6.height=50
+target6.name=BinaerzahlenPruefer
+target6.showInterface=false
+target6.type=ClassTarget
+target6.width=180
+target6.x=380
+target6.y=130
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lsg/.classpath b/Quellcodes/AuS_A_DFA_Implementieren/lsg/.classpath
new file mode 100644
index 0000000..a177209
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lsg/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lsg/.project b/Quellcodes/AuS_A_DFA_Implementieren/lsg/.project
new file mode 100644
index 0000000..5557916
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lsg/.project
@@ -0,0 +1,17 @@
+
+
+ tabellen-dfa
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lsg/BinaerzahlenPruefer.java b/Quellcodes/AuS_A_DFA_Implementieren/lsg/BinaerzahlenPruefer.java
new file mode 100644
index 0000000..7e3a0ef
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lsg/BinaerzahlenPruefer.java
@@ -0,0 +1,113 @@
+/**
+ * Implementiert einen DEA, der 0/1-Folgen darauf prüft, ob
+ * sie "gültige Binärzahlen" darstellen.
+ * Gültige Binärzahlen im Sinne dieser Aufgabe beginnen mit
+ * einer 1, auf die eine beliebige Folge von 0/1 folgt. Die
+ * einzelne Ziffer 0 ist ebenfalls erlaubt, jedoch keine
+ * Binärzahlen mit "überflüssigen" führenden Nullen. Die
+ * Binärzahl darf außerdem ein Vorzeichen führen (muss aber
+ * nicht).
+ *
+ * Gültig sind beispielsweise:
+ * 1
+ * 0
+ * 101
+ * 11
+ * 10
+ * 1110010010
+ * 111
+ * -1
+ * 1000000000
+ * +1
+ * 1001001100
+ *
+ * Ungültig sind beispielsweise:
+ * 123
+ * 00
+ * hallo
+ * 0000000011111
+ * 1+1
+ * Binärzahl
+ * abc
+ * 321
+ * 01010101010101
+ * 0101
+ * 01
+ * 0101010101
+ *
+ * @author Urs Lautebach
+ * @version 2021-Januar
+ */
+
+
+public class BinaerzahlenPruefer extends EndlicherAutomat {
+ /* Bei der Implementierung dieser Klasse muss man nur
+ * die Attribute alphabet, uebergaenge und endzustaende
+ * geeignet festlegen -- alles andere macht die
+ * Vaterklasse "EndlicherAutomat.java".
+ *
+ * Dort ist auch erklärt, wie die Nummerierung der
+ * Zustände, des Startzustand und der Übergangstabelle
+ * zu verstehen sind.
+ */
+
+ // Transitionstabelle anlegen mit den Zuständen auf der
+ // senkrechten und den Alphabetzeichen auf der Rechtsachse:
+ private static final int[][] transiTabelle = new int [][] {
+ /* die erste Zeile enthaelt die Sprünge heraus aus
+ * dem Fehlerzustand 0 (den der Automat ja aber gar
+ * nicht wieder verlassen darf), die also alle 0 sind:
+ */
+ { 0,0,0,0 },
+ { 2,2,3,4 },
+ { 0,0,3,4 },
+ { 0,0,0,0 },
+ { 0,0,4,4 },
+ };
+
+ // Alphabet für diesen Automaten als char[]
+ private static final char[] binaerzAlph = new char[] {
+ '-', '+', '0', '1'
+ };
+
+ // Menge der Endzustände:
+ private static final int[] endzustaende = new int[] {
+ 3, 4
+ };
+
+ /**
+ * Konstruktor für einen BinaerzahlenPruefer:
+ */
+ public BinaerzahlenPruefer() {
+ // Aufruf des super-Konstruktors:
+ super(binaerzAlph, transiTabelle, endzustaende);
+ }
+
+ /**
+ * Die main-Methode erlaubt den Aufruf von
+ * Binaerzahlenpruefer von der Kommandozeile aus mit
+ * mehreren zu testenden Strings:
+ *
+ * java BinaerzahlenPruefer 1110101 0001 +1010 abc
+ *
+ * Die Ausgabe lautet dann
+ * Akzeptiert: "1110101" ist ein gueltiges Binärwort.
+ * FEHLER! "0001" ist kein gültiges Binärwort!
+ * Akzeptiert: "+1010" ist ein gueltiges Binärwort.
+ * FEHLER! "abc" ist kein gültiges Binärwort!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat binaerzahlenDFA = new BinaerzahlenPruefer();
+
+ for(String wort : args) {
+ if(binaerzahlenDFA.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" ist ein gültiges Binärwort.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" ist kein gültiges Binärwort!");
+ }
+ }
+ }
+}
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lsg/DEA_BeispieleTest.java b/Quellcodes/AuS_A_DFA_Implementieren/lsg/DEA_BeispieleTest.java
new file mode 100644
index 0000000..d544eb0
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lsg/DEA_BeispieleTest.java
@@ -0,0 +1,104 @@
+import static org.junit.Assert.*;
+import org.junit.Test;
+public class DEA_BeispieleTest {
+
+ public DEA_BeispieleTest() {
+ }
+
+ @Test
+ public void testBinaerzahlenPruefer() {
+ BinaerzahlenPruefer binZPruefer = new BinaerzahlenPruefer();
+ assertTrue(binZPruefer.gehoertZuSprache("1"));
+ assertTrue(binZPruefer.gehoertZuSprache("0"));
+ assertTrue(binZPruefer.gehoertZuSprache("+1"));
+ assertTrue(binZPruefer.gehoertZuSprache("+0"));
+ assertTrue(binZPruefer.gehoertZuSprache("-1"));
+ assertTrue(binZPruefer.gehoertZuSprache("-0"));
+ assertTrue(binZPruefer.gehoertZuSprache("11"));
+ assertTrue(binZPruefer.gehoertZuSprache("10"));
+ assertTrue(binZPruefer.gehoertZuSprache("+11"));
+ assertTrue(binZPruefer.gehoertZuSprache("-11"));
+ assertTrue(binZPruefer.gehoertZuSprache("+10"));
+ assertTrue(binZPruefer.gehoertZuSprache("1111"));
+ assertTrue(binZPruefer.gehoertZuSprache("1000"));
+ assertTrue(binZPruefer.gehoertZuSprache("10100101010111000"));
+ assertTrue(binZPruefer.gehoertZuSprache("1111111"));
+
+ assertFalse(binZPruefer.gehoertZuSprache(""));
+ assertFalse(binZPruefer.gehoertZuSprache("+"));
+ assertFalse(binZPruefer.gehoertZuSprache("-"));
+ assertFalse(binZPruefer.gehoertZuSprache("x"));
+ assertFalse(binZPruefer.gehoertZuSprache("binärzahl"));
+ assertFalse(binZPruefer.gehoertZuSprache("00"));
+ assertFalse(binZPruefer.gehoertZuSprache("+00"));
+ assertFalse(binZPruefer.gehoertZuSprache("0+0"));
+ assertFalse(binZPruefer.gehoertZuSprache("123"));
+ assertFalse(binZPruefer.gehoertZuSprache("0011"));
+ assertFalse(binZPruefer.gehoertZuSprache("011"));
+ assertFalse(binZPruefer.gehoertZuSprache("111111+"));
+ assertFalse(binZPruefer.gehoertZuSprache("000000+"));
+ assertFalse(binZPruefer.gehoertZuSprache("1+1"));
+ assertFalse(binZPruefer.gehoertZuSprache("0+1"));
+ assertFalse(binZPruefer.gehoertZuSprache("1+0"));
+ }
+
+ @Test
+ public void testMailadressenChecker() {
+ MailadressenChecker mailAdrPruefer = new MailadressenChecker();
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.bbbb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b.b.b@bbb.bbb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("bbbbbb@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.b.b.b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("...@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("...bbb@bb.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("bbb...@bb.bb"));
+
+ assertFalse(mailAdrPruefer.gehoertZuSprache(""));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("@"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("b@b.b@bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("@bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@.."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@bb.b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@bb.bb.b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb.bb.bb.bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache(
+ "bbb@bb.bb.bb@bb.bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb..bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb.bbb.."));
+ }
+
+ @Test
+ public void test007Sucher() {
+ KGB_007Sucher detektiv = new KGB_007Sucher();
+ assertTrue(detektiv.gehoertZuSprache("007"));
+ assertTrue(detektiv.gehoertZuSprache("1007"));
+ assertTrue(detektiv.gehoertZuSprache("0071"));
+ assertTrue(detektiv.gehoertZuSprache("007007"));
+ assertTrue(detektiv.gehoertZuSprache("00007"));
+ assertTrue(detektiv.gehoertZuSprache("0000712"));
+ assertTrue(detektiv.gehoertZuSprache("2121200777"));
+ assertTrue(detektiv.gehoertZuSprache("0077"));
+ assertTrue(detektiv.gehoertZuSprache("212121007000000"));
+ assertTrue(detektiv.gehoertZuSprache("00712772712717"));
+
+ assertFalse(detektiv.gehoertZuSprache(""));
+ assertFalse(detektiv.gehoertZuSprache("0"));
+ assertFalse(detektiv.gehoertZuSprache("1"));
+ assertFalse(detektiv.gehoertZuSprache("2"));
+ assertFalse(detektiv.gehoertZuSprache("7"));
+ assertFalse(detektiv.gehoertZuSprache("07"));
+ assertFalse(detektiv.gehoertZuSprache("001"));
+ assertFalse(detektiv.gehoertZuSprache("002"));
+ assertFalse(detektiv.gehoertZuSprache("000"));
+ assertFalse(detektiv.gehoertZuSprache("001002"));
+ assertFalse(detektiv.gehoertZuSprache("7001"));
+ assertFalse(detektiv.gehoertZuSprache("0707"));
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lsg/EndlicherAutomat.java b/Quellcodes/AuS_A_DFA_Implementieren/lsg/EndlicherAutomat.java
new file mode 100644
index 0000000..1680b57
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lsg/EndlicherAutomat.java
@@ -0,0 +1,196 @@
+/**
+ * Implementiert einen tabellengetriebenen endlichen Automaten.
+ * Instanzen dieser Klasse sind DEAs, die Wörter über einem
+ * vorgegebenen Alphabet akzeptieren oder ablehnen können.
+ *
+ * Die Aufgabe wurde vom schriftlichen Abitur 2020 in
+ * Baden-Württemberg inspiriert.
+ *
+ * @author Urs Lautebach
+ * @version 2020-Oktober
+ */
+public class EndlicherAutomat {
+ private int [][] uebergaenge = null;
+ private int[] endzustaende = null;
+ private char[] alphabet = null;
+
+ /**
+ * Konstruiert einen tabellengetriebenen DEA. Nach dem
+ * erfolgreichen Aufruf dieses Konstruktors kann man den DEA
+ * anschließend durch einen Aufruf der Methode
+ * gehoertZuSprache(String):boolean
+ * beliebig viele Wörter testen lassen.
+ *
+ * @param tabelle Transitionstabelle des DEA. Die erste
+ * Dimension bezeichnet die Zustände; die zweite Dimension die
+ * Eingabezeichen. Die Einträge der Tabelle bezeichnen jeweils
+ * den Zustand, in den der Automat (abhängig vom vorherigen
+ * Zustand und der Eingabe) wechseln soll.
+ *
+ * Der Zustand 0 gilt als Fehlerzustand. Zustand 1 ist immer
+ * Startzustand (so dass der Startzustand, anders als bei der
+ * formalen Beschreibung eines DEA, nicht explizit angegeben
+ * werden muss).
+ *
+ * @param finalStates Ein int[], das die Endzustände enthält.
+ *
+ * @param alphabet ein Array von char, das das Alphabet des
+ * Automaten enthält. Die Reihenfolge der Zeichen im Alphabet
+ * muss der Reihenfolge der Zeichen an der entsprechenden
+ * Achse der Transitionstabelle entsprechen.
+ */
+ EndlicherAutomat(final char[] alphabet,
+ final int[][] uebergaenge, final int[] endzustaende ) {
+ this.alphabet = alphabet;
+ this.uebergaenge = uebergaenge;
+ this.endzustaende = endzustaende;
+ // Die Methode plausibilitaetPruefen ist fertig vorgegeben;
+ // sie fängt einige offensichtliche Fehler ab:
+ plausibilitaetPruefen();
+ }
+
+ /**
+ * Die Methode prüft, ob die Attribute transitionstabelle,
+ * alphabet und endzustaende zueinander passen. Sie ist fertig
+ * implementiert und dafür gedacht, am Ende des Konstruktors
+ * aufgerufen zu werden.
+ */
+ private void plausibilitaetPruefen() {
+ if (uebergaenge == null) {
+ throw new IllegalArgumentException(
+ "Die Übergangstabelle ist null oder leer!");
+ }
+ if (alphabet == null) {
+ throw new IllegalArgumentException(
+ "Das Alphabet ist null oder leer!");
+ }
+ if (endzustaende == null) {
+ throw new IllegalArgumentException(
+ "endzustaende ist null oder leer!");
+ }
+ int tabelleHoehe = this.uebergaenge.length;
+ int tabelleBreite = uebergaenge[0].length;
+ // Hat die Übergangstabelle eine Zeile pro Alphabetzeichen?
+ if (tabelleBreite != alphabet.length) {
+ throw new IllegalArgumentException("Das Alphabet hat " +
+ alphabet.length + " Zeichen, die " +
+ " Übergangstabelle aber " + tabelleBreite +
+ " Spalten!");
+ }
+ // Sind alle Zeilen der Transitionstabelle gleich lang?
+ for (int[] zeile : uebergaenge) {
+ if (zeile.length != tabelleBreite) {
+ throw new IllegalArgumentException(
+ "Übergangstabelle ist nicht rechteckig!");
+ }
+ }
+ // Hat einer der Endzustände eine unplausible Nummer?
+ for (int zustand : endzustaende) {
+ if (zustand < 1 || zustand > tabelleHoehe - 1) {
+ throw new IllegalArgumentException(
+ "Der Endzustand " + zustand +
+ " kommt in der Übergangstabelle nicht vor!");
+ }
+ }
+ }
+
+ /**
+ * Ermittelt die Nummer (den Index) des angegebenen Zeichens
+ * innerhalb des Alphabetes dieses Automaten.
+ *
+ * @param input Zeichen, dessen Position ermittelt werden soll.
+ * @returns Position des Zeichens input innerhalb des Alphabets
+ * dieses Automaten; oder -1, falls es im Alphabet nicht
+ * enthalten ist.
+ */
+ public int indexImAlphabet(char input) {
+ /* Man geht das Alphabet durch und prüft, welches seiner
+ * Zeichen dem "input" entspricht. Falls man es findet,
+ * gibt man dessen Index zurück.
+ */
+ for (int index = 0; index < alphabet.length; index++) {
+ if (input == alphabet[index])
+ return index;
+ }
+ return -1;
+ }
+
+ /**
+ * Überprüft, ob der Zustand mit der übergebenen
+ * Zustandsnummer einer der Endzustände dieses Automaten ist.
+ *
+ * @param nr Nummer des fraglichen Zustandes.
+ * @return ob der Zustand ein Endzustand ist.
+ */
+ public boolean istEndzustand(int nr) {
+ for (int endzustand : endzustaende) {
+ // Gehe durch alle Endzustände. Wenn nr einer ist...
+ if (nr == endzustand) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Die Methode kann mit einem String als Parameter aufgerufen
+ * werden, was oft bequemer ist als ein char[].
+ *
+ * @param s String mit dem zu prüfenden Wort.
+ * @return ob s von diesem Automaten erkannt wird.
+ */
+ public boolean gehoertZuSprache(String s) {
+ // Hier ist nichts zu implementieren.
+ return gehoertZuSprache(s.toCharArray());
+ }
+
+ /**
+ * Übergibt dem DEA ein ganzes Wort und ermittelt, ob er es
+ * akzeptiert oder nicht.
+ *
+ * @param eingabe Die komplette zu analysierende Eingabe als
+ * char[].
+ * @returns true, wenn das Wort vom DEA akzeptiert wird;
+ * false sonst.
+ */
+ public boolean gehoertZuSprache(final char[] wort) {
+ /*
+ * Um zu prüfen, ob wort akzeptiert wird, muss der DEA...
+ *
+ * - in Zustand 1 beginnen;
+ *
+ * - das Eingabewort Zeichen für Zeichen durchgehen;
+ *
+ * - prüfen, ob das Zeichen im Alphabet vorkommt;
+ *
+ * - nach dessen Position im Alphabet und altem Zustand
+ * einen neuen Zustand aus der Tabelle uebergaenge wählen;
+ *
+ * - false antworten, wenn er im Fehlerzustand landet,
+ *
+ * - am Schluss der Eingabe entscheiden, ob der erreichte
+ * Zustand ein Endzustand ist.
+ */
+ // Startzustand ist immer Nr. 1:
+ int zustand = 1;
+ // Gehe durch alle Zeichen durch:
+ for (char zeichen : wort) {
+ int alphIndex = indexImAlphabet(zeichen);
+ // Falls das Zeichen gar nicht im Alphabet ist...:
+ if (alphIndex == -1) {
+ return false;
+ } else {
+ // wechsle in neuen Zustand:
+ zustand = uebergaenge[zustand][alphIndex];
+ }
+ // Bin ich im Fehlerzustand?
+ if (zustand == 0) {
+ return false;
+ }
+ }
+ // Die Eingabe ist verbraucht. Falls der aktuelle Zustand
+ // ein Endzustand ist, akzeptieren wir die Eingabe:
+ return istEndzustand(zustand);
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lsg/KGB_007Sucher.java b/Quellcodes/AuS_A_DFA_Implementieren/lsg/KGB_007Sucher.java
new file mode 100644
index 0000000..97ecf52
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lsg/KGB_007Sucher.java
@@ -0,0 +1,92 @@
+/**
+ * Dieser DFA erkennt Ziffernfolgen, in denen sich irgendwo
+ * James Bond versteckt hat -- in denen also die Folge 007
+ * vorkommt.
+ *
+ * Die folgenden Ziffernfolgen sollen beispielsweise akzeptiert
+ * werden:
+ *
+ * 12107117700710012021,
+ * 007,
+ * 0071121727,
+ * 0000000071121727,
+ * 007007007007,
+ * 1121271201212007.
+ *
+ * Die folgenden Ziffernfolgen sollen nicht akzeptiert werden:
+ *
+ * 12107110710012021,
+ * 07,
+ * 00,
+ * 07112172,
+ * 1121271201212000.
+
+ * Um den Automaten und vor allem die Übergangstabelle
+ * übersichtlicher zu halten, verwendet er nicht alle Ziffern,
+ * sondern lediglich das eingeschränkte Alphabet {0, 1, 2, 7}.
+ *
+ * Es empfiehlt sich, den Automaten zunächst zu zeichnen,
+ * die Übergangstabelle auf Papier zu erstellen und dann zu
+ * programmieren.
+ *
+ * @author Urs Lautebach
+ * @version 2020-Okt
+ */
+
+public class KGB_007Sucher extends EndlicherAutomat {
+ /* Bei der Implementierung dieser Klasse muss man nur
+ * die Attribute alphabet, uebergaenge und endzustaende
+ * geeignet festlegen -- alles andere macht die
+ * Vaterklasse.
+ */
+ private static final char[] alphabet = new char[] {
+ '0', '1', '2', '7'
+ };
+
+ private static final int[][] uebergaenge = new int[][] {
+ { 0, 0, 0, 0 },
+ { 2, 1, 1, 1 },
+ { 3, 1, 1, 1 },
+ { 3, 1, 1, 4 },
+ { 4, 4, 4, 4 },
+ };
+
+ private static final int[] endzustaende = new int[] {
+ 4
+ };
+
+ /**
+ * Instanziiert einen KGB_007Sucher-DFA.
+ */
+ KGB_007Sucher() {
+ // Aufruf des super-Konstruktors:
+ super(alphabet, uebergaenge, endzustaende);
+ }
+
+ /**
+ * Die main-Methode erlaubt den Aufruf des
+ * Binaerzahlenpruefers von der Kommandozeile aus mit:
+ *
+ * java KGB_007Sucher 127007117 1717771021
+ *
+ * Die Ausgabe lautet dann
+ *
+ * Akzeptiert: "127007117" enthält 007.
+ * FEHLER! "1717771021" enthält kein 007!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat fahnder = new KGB_007Sucher();
+
+ for(String wort : args) {
+ if(fahnder.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" enthält 007.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" enthält kein 007!");
+ }
+ }
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lsg/MailadressenChecker.java b/Quellcodes/AuS_A_DFA_Implementieren/lsg/MailadressenChecker.java
new file mode 100644
index 0000000..2000865
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lsg/MailadressenChecker.java
@@ -0,0 +1,93 @@
+/**
+ * Die Klasse implementiert einen DEA für die Überprüfung äußerst
+ * einfacher Mailadressen, die nur aus dem Buchstaben b, Punkten
+ * und dem at-Zeichen bestehen dürfen. Der Nutzername darf fast
+ * beliebig aufgebaut sein; die Domain muss mindestens zweistufig
+ * sein und die Toplevel-Domain muss mindestens zwei Zeichen haben.
+ *
+ * Gültig sind damit beispielsweise:
+ * b@b.bb
+ * b@b.bbbb
+ * b.b.b@bbb.bbb
+ * bbbbbb@b.bb
+ * b@b.b.b.b.bb
+ * ...@b.bb
+ * ...bbb@bb.bb
+ * bbb...@bb.bb
+ *
+ * Ungültig sind beispielsweise:
+ * .
+ * b
+ * @
+ * bb@
+ * b@b.b@bbb
+ * b@b.b@bb.b
+ * @bb
+ * bb@.
+ * bb@..
+ *
+ * Tatsächlich ist die Überprüfung realer Mailadressen wesentlich
+ * komlizierter als in diesem Beispiel.
+ *
+ * @author Urs Lautebach
+ * @version 2021-Janar
+ *
+ */
+public class MailadressenChecker extends EndlicherAutomat {
+ /* Bei der Implementierung dieser Klasse muss man nur
+ * die Attribute alphabet, uebergaenge und endzustaende
+ * geeignet festlegen -- alles andere macht die
+ * Vaterklasse.
+ */
+
+ private static final char[] alphabet = new char[] {
+ 'b', '.', '@'
+ };
+ private static final int[][] transitionen = new int[][] {
+ { 0, 0, 0 },
+ { 2, 2, 0 },
+ { 2, 2, 3 },
+ { 4, 0, 0 },
+ { 4, 5, 0 },
+ { 6, 0, 0 },
+ { 7, 5, 0 },
+ { 7, 5, 0 },
+ };
+
+ private static final int[] endzustaende = new int[] {
+ 7
+ };
+
+ MailadressenChecker() {
+ // Aufruf des super-Konstruktors:
+ super(alphabet, transitionen, endzustaende);
+ }
+
+
+ /**
+ * Die main-Methode erlaubt den Aufruf des
+ * Binaerzahlenpruefers von der Kommandozeile mit beliebig
+ * vielen zu prüfenden Strings:
+ * java MailadressenChecker bbb.b@bb.bb a@b@c
+ *
+ * Die Ausgabe lautet dann
+ *
+ * Akzeptiert: "bbb.b@bb.bb" ist eine gültige Mailadresse.
+ * FEHLER! "a@b@c" ist als Mailadresse ungültig!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat checker = new MailadressenChecker();
+
+ for(String wort : args) {
+ if(checker.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" ist eine gültige Mailadresse.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" ist als Mailadresse ungültig!");
+ } // end if
+ } // end for
+ } // end main
+} // end class
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lsg/README.md b/Quellcodes/AuS_A_DFA_Implementieren/lsg/README.md
new file mode 100644
index 0000000..c2be6f0
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lsg/README.md
@@ -0,0 +1,3 @@
+# Tabellen Dfa
+
+Implementierung eines allgemeinen tabellengetriebenen DFA als Programmieraufgabe (samt einiger Beispiel-DFA).
\ No newline at end of file
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lsg/lehrkraft-liesmich.txt b/Quellcodes/AuS_A_DFA_Implementieren/lsg/lehrkraft-liesmich.txt
new file mode 100644
index 0000000..63abfcd
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lsg/lehrkraft-liesmich.txt
@@ -0,0 +1,36 @@
+Dieser Ordner enthält ein Java-Projekt, in dem die Implementierung
+eines tabellengetriebenen DEA geübt wird. Es kann mit BlueJ oder
+einem anderen Java-Werkzeug bearbeitet werden.
+
+Das Projekt liegt in drei Ausstattungen vor; Sie als Lehrkraft
+entscheiden, welche Variante(n) Sie den Schülern vorlegen.
+
+Der Ordner...
+
+.skelett
+--------
+enthält das Rohprojekt ohne Lösungshinweise oder Tipps, aber mit
+Spezifikation, Arbeitsanweisungen und JUnit-Test. Das Projekt
+sollte fehlerfrei compilieren und lauffähig sein, aber natürlich
+schlagen die Tests fehl.
+
+.tipp
+-----
+enthält das gleiche Projekt, aber zusätzlich mit Tipps für die
+Bearbeitung durch Schüler.
+
+.lsg
+----
+enthält die Musterlösung des fertig ausprogrammierten Projekts.
+Hier sollten alle Tests erfolgreich laufen.
+
+Zu bearbeiten sind die Datei EndlicherAutomat.java, in der der
+eigentliche Tabellenmechanismus implementiert wird, und eine Auswahl
+der Beispiel-DFA für
+
+Mailadressen
+007-Suche
+oder Binärzahlen
+
+bzw. eigene DFA für andere Sprachen nach Wahl.
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/lsg/package.bluej b/Quellcodes/AuS_A_DFA_Implementieren/lsg/package.bluej
new file mode 100644
index 0000000..a54f5f2
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/lsg/package.bluej
@@ -0,0 +1,75 @@
+#BlueJ package file
+dependency1.from=DFA_BeispieleTest
+dependency1.to=BinaerzahlenPruefer
+dependency1.type=UsesDependency
+dependency2.from=DFA_BeispieleTest
+dependency2.to=MailadressenChecker
+dependency2.type=UsesDependency
+dependency3.from=DFA_BeispieleTest
+dependency3.to=KGB_007Sucher
+dependency3.type=UsesDependency
+editor.fx.0.height=0
+editor.fx.0.width=0
+editor.fx.0.x=0
+editor.fx.0.y=0
+objectbench.height=119
+objectbench.width=770
+package.divider.horizontal=0.5785785785785785
+package.divider.vertical=0.7519685039370079
+package.editor.height=375
+package.editor.width=643
+package.editor.x=100
+package.editor.y=100
+package.frame.height=600
+package.frame.width=800
+package.numDependencies=3
+package.numTargets=6
+package.showExtends=true
+package.showUses=true
+project.charset=UTF-8
+readme.height=58
+readme.name=@README
+readme.width=47
+readme.x=10
+readme.y=10
+target1.height=62
+target1.name=bin
+target1.type=PackageTarget
+target1.width=80
+target1.x=70
+target1.y=10
+target2.height=50
+target2.name=KGB_007Sucher
+target2.showInterface=false
+target2.type=ClassTarget
+target2.width=140
+target2.x=10
+target2.y=130
+target3.height=50
+target3.name=DFA_BeispieleTest
+target3.showInterface=false
+target3.type=UnitTestTargetJunit4
+target3.width=160
+target3.x=180
+target3.y=240
+target4.height=50
+target4.name=EndlicherAutomat
+target4.showInterface=false
+target4.type=ClassTarget
+target4.width=160
+target4.x=180
+target4.y=30
+target5.height=50
+target5.name=MailadressenChecker
+target5.showInterface=false
+target5.type=ClassTarget
+target5.width=180
+target5.x=170
+target5.y=130
+target6.height=50
+target6.name=BinaerzahlenPruefer
+target6.showInterface=false
+target6.type=ClassTarget
+target6.width=180
+target6.x=380
+target6.y=130
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/readme.adoc b/Quellcodes/AuS_A_DFA_Implementieren/readme.adoc
new file mode 100644
index 0000000..849992d
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/readme.adoc
@@ -0,0 +1,11 @@
+= Material :
+
+|===
+|Zuordnung|
+|Klassenstufe|
+|Bildungsplanbezug |
+|Werkzeug|
+|Autoren|
+|===
+
+== Inhalt
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/roh/.classpath b/Quellcodes/AuS_A_DFA_Implementieren/roh/.classpath
new file mode 100644
index 0000000..a177209
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/roh/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/roh/.project b/Quellcodes/AuS_A_DFA_Implementieren/roh/.project
new file mode 100644
index 0000000..5557916
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/roh/.project
@@ -0,0 +1,17 @@
+
+
+ tabellen-dfa
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/roh/BinaerzahlenPruefer.java b/Quellcodes/AuS_A_DFA_Implementieren/roh/BinaerzahlenPruefer.java
new file mode 100644
index 0000000..90e8318
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/roh/BinaerzahlenPruefer.java
@@ -0,0 +1,93 @@
+/**
+ * Implementiert einen DEA, der 0/1-Folgen darauf prüft, ob
+ * sie "gültige Binärzahlen" darstellen.
+ * Gültige Binärzahlen im Sinne dieser Aufgabe beginnen mit
+ * einer 1, auf die eine beliebige Folge von 0/1 folgt. Die
+ * einzelne Ziffer 0 ist ebenfalls erlaubt, jedoch keine
+ * Binärzahlen mit "überflüssigen" führenden Nullen. Die
+ * Binärzahl darf außerdem ein Vorzeichen führen (muss aber
+ * nicht).
+ *
+ * Gültig sind beispielsweise:
+ * 1
+ * 0
+ * 101
+ * 11
+ * 10
+ * 1110010010
+ * 111
+ * -1
+ * 1000000000
+ * +1
+ * 1001001100
+ *
+ * Ungültig sind beispielsweise:
+ * 123
+ * 00
+ * hallo
+ * 0000000011111
+ * 1+1
+ * Binärzahl
+ * abc
+ * 321
+ * 01010101010101
+ * 0101
+ * 01
+ * 0101010101
+ *
+ * @author Urs Lautebach
+ * @version 2021-Januar
+ */
+
+
+public class BinaerzahlenPruefer extends EndlicherAutomat {
+
+ // Transitionstabelle anlegen mit den Zuständen auf der
+ // senkrechten und den Alphabetzeichen auf der Rechtsachse:
+ private static final int[][] transiTabelle = new int [][] {
+ };
+
+ // Alphabet für diesen Automaten als char[]
+ private static final char[] binaerzAlph = new char[] {
+ };
+
+ // Menge der Endzustände:
+ private static final int[] endzustaende = new int[] {
+ };
+
+ /**
+ * Konstruktor für einen BinaerzahlenPruefer:
+ */
+ public BinaerzahlenPruefer() {
+ // Aufruf des super-Konstruktors:
+ super(binaerzAlph, transiTabelle, endzustaende);
+ }
+
+ /**
+ * Die main-Methode erlaubt den Aufruf von
+ * Binaerzahlenpruefer von der Kommandozeile aus mit
+ * mehreren zu testenden Strings:
+ *
+ * java BinaerzahlenPruefer 1110101 0001 +1010 abc
+ *
+ * Die Ausgabe lautet dann
+ * Akzeptiert: "1110101" ist ein gueltiges Binärwort.
+ * FEHLER! "0001" ist kein gültiges Binärwort!
+ * Akzeptiert: "+1010" ist ein gueltiges Binärwort.
+ * FEHLER! "abc" ist kein gültiges Binärwort!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat binaerzahlenDFA = new BinaerzahlenPruefer();
+
+ for(String wort : args) {
+ if(binaerzahlenDFA.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" ist ein gültiges Binärwort.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" ist kein gültiges Binärwort!");
+ }
+ }
+ }
+}
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/roh/DEA_BeispieleTest.java b/Quellcodes/AuS_A_DFA_Implementieren/roh/DEA_BeispieleTest.java
new file mode 100644
index 0000000..d544eb0
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/roh/DEA_BeispieleTest.java
@@ -0,0 +1,104 @@
+import static org.junit.Assert.*;
+import org.junit.Test;
+public class DEA_BeispieleTest {
+
+ public DEA_BeispieleTest() {
+ }
+
+ @Test
+ public void testBinaerzahlenPruefer() {
+ BinaerzahlenPruefer binZPruefer = new BinaerzahlenPruefer();
+ assertTrue(binZPruefer.gehoertZuSprache("1"));
+ assertTrue(binZPruefer.gehoertZuSprache("0"));
+ assertTrue(binZPruefer.gehoertZuSprache("+1"));
+ assertTrue(binZPruefer.gehoertZuSprache("+0"));
+ assertTrue(binZPruefer.gehoertZuSprache("-1"));
+ assertTrue(binZPruefer.gehoertZuSprache("-0"));
+ assertTrue(binZPruefer.gehoertZuSprache("11"));
+ assertTrue(binZPruefer.gehoertZuSprache("10"));
+ assertTrue(binZPruefer.gehoertZuSprache("+11"));
+ assertTrue(binZPruefer.gehoertZuSprache("-11"));
+ assertTrue(binZPruefer.gehoertZuSprache("+10"));
+ assertTrue(binZPruefer.gehoertZuSprache("1111"));
+ assertTrue(binZPruefer.gehoertZuSprache("1000"));
+ assertTrue(binZPruefer.gehoertZuSprache("10100101010111000"));
+ assertTrue(binZPruefer.gehoertZuSprache("1111111"));
+
+ assertFalse(binZPruefer.gehoertZuSprache(""));
+ assertFalse(binZPruefer.gehoertZuSprache("+"));
+ assertFalse(binZPruefer.gehoertZuSprache("-"));
+ assertFalse(binZPruefer.gehoertZuSprache("x"));
+ assertFalse(binZPruefer.gehoertZuSprache("binärzahl"));
+ assertFalse(binZPruefer.gehoertZuSprache("00"));
+ assertFalse(binZPruefer.gehoertZuSprache("+00"));
+ assertFalse(binZPruefer.gehoertZuSprache("0+0"));
+ assertFalse(binZPruefer.gehoertZuSprache("123"));
+ assertFalse(binZPruefer.gehoertZuSprache("0011"));
+ assertFalse(binZPruefer.gehoertZuSprache("011"));
+ assertFalse(binZPruefer.gehoertZuSprache("111111+"));
+ assertFalse(binZPruefer.gehoertZuSprache("000000+"));
+ assertFalse(binZPruefer.gehoertZuSprache("1+1"));
+ assertFalse(binZPruefer.gehoertZuSprache("0+1"));
+ assertFalse(binZPruefer.gehoertZuSprache("1+0"));
+ }
+
+ @Test
+ public void testMailadressenChecker() {
+ MailadressenChecker mailAdrPruefer = new MailadressenChecker();
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.bbbb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b.b.b@bbb.bbb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("bbbbbb@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.b.b.b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("...@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("...bbb@bb.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("bbb...@bb.bb"));
+
+ assertFalse(mailAdrPruefer.gehoertZuSprache(""));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("@"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("b@b.b@bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("@bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@.."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@bb.b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@bb.bb.b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb.bb.bb.bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache(
+ "bbb@bb.bb.bb@bb.bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb..bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb.bbb.."));
+ }
+
+ @Test
+ public void test007Sucher() {
+ KGB_007Sucher detektiv = new KGB_007Sucher();
+ assertTrue(detektiv.gehoertZuSprache("007"));
+ assertTrue(detektiv.gehoertZuSprache("1007"));
+ assertTrue(detektiv.gehoertZuSprache("0071"));
+ assertTrue(detektiv.gehoertZuSprache("007007"));
+ assertTrue(detektiv.gehoertZuSprache("00007"));
+ assertTrue(detektiv.gehoertZuSprache("0000712"));
+ assertTrue(detektiv.gehoertZuSprache("2121200777"));
+ assertTrue(detektiv.gehoertZuSprache("0077"));
+ assertTrue(detektiv.gehoertZuSprache("212121007000000"));
+ assertTrue(detektiv.gehoertZuSprache("00712772712717"));
+
+ assertFalse(detektiv.gehoertZuSprache(""));
+ assertFalse(detektiv.gehoertZuSprache("0"));
+ assertFalse(detektiv.gehoertZuSprache("1"));
+ assertFalse(detektiv.gehoertZuSprache("2"));
+ assertFalse(detektiv.gehoertZuSprache("7"));
+ assertFalse(detektiv.gehoertZuSprache("07"));
+ assertFalse(detektiv.gehoertZuSprache("001"));
+ assertFalse(detektiv.gehoertZuSprache("002"));
+ assertFalse(detektiv.gehoertZuSprache("000"));
+ assertFalse(detektiv.gehoertZuSprache("001002"));
+ assertFalse(detektiv.gehoertZuSprache("7001"));
+ assertFalse(detektiv.gehoertZuSprache("0707"));
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/roh/EndlicherAutomat.java b/Quellcodes/AuS_A_DFA_Implementieren/roh/EndlicherAutomat.java
new file mode 100644
index 0000000..f18fe3b
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/roh/EndlicherAutomat.java
@@ -0,0 +1,146 @@
+/**
+ * Implementiert einen tabellengetriebenen endlichen Automaten.
+ * Instanzen dieser Klasse sind DEAs, die Wörter über einem
+ * vorgegebenen Alphabet akzeptieren oder ablehnen können.
+ *
+ * Die Aufgabe wurde vom schriftlichen Abitur 2020 in
+ * Baden-Württemberg inspiriert.
+ *
+ * @author Urs Lautebach
+ * @version 2020-Oktober
+ */
+public class EndlicherAutomat {
+ private int [][] uebergaenge = null;
+ private int[] endzustaende = null;
+ private char[] alphabet = null;
+
+ /**
+ * Konstruiert einen tabellengetriebenen DEA. Nach dem
+ * erfolgreichen Aufruf dieses Konstruktors kann man den DEA
+ * anschließend durch einen Aufruf der Methode
+ * gehoertZuSprache(String):boolean
+ * beliebig viele Wörter testen lassen.
+ *
+ * @param tabelle Transitionstabelle des DEA. Die erste
+ * Dimension bezeichnet die Zustände; die zweite Dimension die
+ * Eingabezeichen. Die Einträge der Tabelle bezeichnen jeweils
+ * den Zustand, in den der Automat (abhängig vom vorherigen
+ * Zustand und der Eingabe) wechseln soll.
+ *
+ * Der Zustand 0 gilt als Fehlerzustand. Zustand 1 ist immer
+ * Startzustand (so dass der Startzustand, anders als bei der
+ * formalen Beschreibung eines DEA, nicht explizit angegeben
+ * werden muss).
+ *
+ * @param finalStates Ein int[], das die Endzustände enthält.
+ *
+ * @param alphabet ein Array von char, das das Alphabet des
+ * Automaten enthält. Die Reihenfolge der Zeichen im Alphabet
+ * muss der Reihenfolge der Zeichen an der entsprechenden
+ * Achse der Transitionstabelle entsprechen.
+ */
+ EndlicherAutomat(final char[] alphabet,
+ final int[][] uebergaenge, final int[] endzustaende ) {
+ // Die Methode plausibilitaetPruefen ist fertig vorgegeben;
+ // sie fängt einige offensichtliche Fehler ab:
+ plausibilitaetPruefen();
+ }
+
+ /**
+ * Die Methode prüft, ob die Attribute transitionstabelle,
+ * alphabet und endzustaende zueinander passen. Sie ist fertig
+ * implementiert und dafür gedacht, am Ende des Konstruktors
+ * aufgerufen zu werden.
+ */
+ private void plausibilitaetPruefen() {
+ if (uebergaenge == null) {
+ throw new IllegalArgumentException(
+ "Die Übergangstabelle ist null oder leer!");
+ }
+ if (alphabet == null) {
+ throw new IllegalArgumentException(
+ "Das Alphabet ist null oder leer!");
+ }
+ if (endzustaende == null) {
+ throw new IllegalArgumentException(
+ "endzustaende ist null oder leer!");
+ }
+ int tabelleHoehe = this.uebergaenge.length;
+ int tabelleBreite = uebergaenge[0].length;
+ // Hat die Übergangstabelle eine Zeile pro Alphabetzeichen?
+ if (tabelleBreite != alphabet.length) {
+ throw new IllegalArgumentException("Das Alphabet hat " +
+ alphabet.length + " Zeichen, die " +
+ " Übergangstabelle aber " + tabelleBreite +
+ " Spalten!");
+ }
+ // Sind alle Zeilen der Transitionstabelle gleich lang?
+ for (int[] zeile : uebergaenge) {
+ if (zeile.length != tabelleBreite) {
+ throw new IllegalArgumentException(
+ "Übergangstabelle ist nicht rechteckig!");
+ }
+ }
+ // Hat einer der Endzustände eine unplausible Nummer?
+ for (int zustand : endzustaende) {
+ if (zustand < 1 || zustand > tabelleHoehe - 1) {
+ throw new IllegalArgumentException(
+ "Der Endzustand " + zustand +
+ " kommt in der Übergangstabelle nicht vor!");
+ }
+ }
+ }
+
+ /**
+ * Ermittelt die Nummer (den Index) des angegebenen Zeichens
+ * innerhalb des Alphabetes dieses Automaten.
+ *
+ * @param input Zeichen, dessen Position ermittelt werden soll.
+ * @returns Position des Zeichens input innerhalb des Alphabets
+ * dieses Automaten; oder -1, falls es im Alphabet nicht
+ * enthalten ist.
+ */
+ public int indexImAlphabet(char input) {
+ // TODO: Implementieren Sie diese Methode.
+ return -54321; // dummy return
+ }
+
+ /**
+ * Überprüft, ob der Zustand mit der übergebenen
+ * Zustandsnummer einer der Endzustände dieses Automaten ist.
+ *
+ * @param nr Nummer des fraglichen Zustandes.
+ * @return ob der Zustand ein Endzustand ist.
+ */
+ public boolean istEndzustand(int nr) {
+ // TODO: Implementieren Sie diese Methode.
+ return false; // dummy return
+ }
+
+ /**
+ * Die Methode kann mit einem String als Parameter aufgerufen
+ * werden, was oft bequemer ist als ein char[].
+ *
+ * @param s String mit dem zu prüfenden Wort.
+ * @return ob s von diesem Automaten erkannt wird.
+ */
+ public boolean gehoertZuSprache(String s) {
+ // Hier ist nichts zu implementieren.
+ return gehoertZuSprache(s.toCharArray());
+ }
+
+ /**
+ * Übergibt dem DEA ein ganzes Wort und ermittelt, ob er es
+ * akzeptiert oder nicht.
+ *
+ * @param eingabe Die komplette zu analysierende Eingabe als
+ * char[].
+ * @returns true, wenn das Wort vom DEA akzeptiert wird;
+ * false sonst.
+ */
+ public boolean gehoertZuSprache(final char[] wort) {
+ // TODO: Implementieren Sie diese Methode.
+ return false; // dummy return
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/roh/KGB_007Sucher.java b/Quellcodes/AuS_A_DFA_Implementieren/roh/KGB_007Sucher.java
new file mode 100644
index 0000000..04481cb
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/roh/KGB_007Sucher.java
@@ -0,0 +1,80 @@
+/**
+ * Dieser DFA erkennt Ziffernfolgen, in denen sich irgendwo
+ * James Bond versteckt hat -- in denen also die Folge 007
+ * vorkommt.
+ *
+ * Die folgenden Ziffernfolgen sollen beispielsweise akzeptiert
+ * werden:
+ *
+ * 12107117700710012021,
+ * 007,
+ * 0071121727,
+ * 0000000071121727,
+ * 007007007007,
+ * 1121271201212007.
+ *
+ * Die folgenden Ziffernfolgen sollen nicht akzeptiert werden:
+ *
+ * 12107110710012021,
+ * 07,
+ * 00,
+ * 07112172,
+ * 1121271201212000.
+
+ * Um den Automaten und vor allem die Übergangstabelle
+ * übersichtlicher zu halten, verwendet er nicht alle Ziffern,
+ * sondern lediglich das eingeschränkte Alphabet {0, 1, 2, 7}.
+ *
+ * Es empfiehlt sich, den Automaten zunächst zu zeichnen,
+ * die Übergangstabelle auf Papier zu erstellen und dann zu
+ * programmieren.
+ *
+ * @author Urs Lautebach
+ * @version 2020-Okt
+ */
+
+public class KGB_007Sucher extends EndlicherAutomat {
+ private static final char[] alphabet = new char[] {
+ };
+
+ private static final int[][] uebergaenge = new int[][] {
+ };
+
+ private static final int[] endzustaende = new int[] {
+ };
+
+ /**
+ * Instanziiert einen KGB_007Sucher-DFA.
+ */
+ KGB_007Sucher() {
+ // Aufruf des super-Konstruktors:
+ super(alphabet, uebergaenge, endzustaende);
+ }
+
+ /**
+ * Die main-Methode erlaubt den Aufruf des
+ * Binaerzahlenpruefers von der Kommandozeile aus mit:
+ *
+ * java KGB_007Sucher 127007117 1717771021
+ *
+ * Die Ausgabe lautet dann
+ *
+ * Akzeptiert: "127007117" enthält 007.
+ * FEHLER! "1717771021" enthält kein 007!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat fahnder = new KGB_007Sucher();
+
+ for(String wort : args) {
+ if(fahnder.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" enthält 007.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" enthält kein 007!");
+ }
+ }
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/roh/MailadressenChecker.java b/Quellcodes/AuS_A_DFA_Implementieren/roh/MailadressenChecker.java
new file mode 100644
index 0000000..a89776b
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/roh/MailadressenChecker.java
@@ -0,0 +1,78 @@
+/**
+ * Die Klasse implementiert einen DEA für die Überprüfung äußerst
+ * einfacher Mailadressen, die nur aus dem Buchstaben b, Punkten
+ * und dem at-Zeichen bestehen dürfen. Der Nutzername darf fast
+ * beliebig aufgebaut sein; die Domain muss mindestens zweistufig
+ * sein und die Toplevel-Domain muss mindestens zwei Zeichen haben.
+ *
+ * Gültig sind damit beispielsweise:
+ * b@b.bb
+ * b@b.bbbb
+ * b.b.b@bbb.bbb
+ * bbbbbb@b.bb
+ * b@b.b.b.b.bb
+ * ...@b.bb
+ * ...bbb@bb.bb
+ * bbb...@bb.bb
+ *
+ * Ungültig sind beispielsweise:
+ * .
+ * b
+ * @
+ * bb@
+ * b@b.b@bbb
+ * b@b.b@bb.b
+ * @bb
+ * bb@.
+ * bb@..
+ *
+ * Tatsächlich ist die Überprüfung realer Mailadressen wesentlich
+ * komlizierter als in diesem Beispiel.
+ *
+ * @author Urs Lautebach
+ * @version 2021-Janar
+ *
+ */
+public class MailadressenChecker extends EndlicherAutomat {
+
+ private static final char[] alphabet = new char[] {
+ };
+ private static final int[][] transitionen = new int[][] {
+ };
+
+ private static final int[] endzustaende = new int[] {
+ };
+
+ MailadressenChecker() {
+ // Aufruf des super-Konstruktors:
+ super(alphabet, transitionen, endzustaende);
+ }
+
+
+ /**
+ * Die main-Methode erlaubt den Aufruf des
+ * Binaerzahlenpruefers von der Kommandozeile mit beliebig
+ * vielen zu prüfenden Strings:
+ * java MailadressenChecker bbb.b@bb.bb a@b@c
+ *
+ * Die Ausgabe lautet dann
+ *
+ * Akzeptiert: "bbb.b@bb.bb" ist eine gültige Mailadresse.
+ * FEHLER! "a@b@c" ist als Mailadresse ungültig!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat checker = new MailadressenChecker();
+
+ for(String wort : args) {
+ if(checker.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" ist eine gültige Mailadresse.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" ist als Mailadresse ungültig!");
+ } // end if
+ } // end for
+ } // end main
+} // end class
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/roh/README.md b/Quellcodes/AuS_A_DFA_Implementieren/roh/README.md
new file mode 100644
index 0000000..c2be6f0
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/roh/README.md
@@ -0,0 +1,3 @@
+# Tabellen Dfa
+
+Implementierung eines allgemeinen tabellengetriebenen DFA als Programmieraufgabe (samt einiger Beispiel-DFA).
\ No newline at end of file
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/roh/lehrkraft-liesmich.txt b/Quellcodes/AuS_A_DFA_Implementieren/roh/lehrkraft-liesmich.txt
new file mode 100644
index 0000000..63abfcd
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/roh/lehrkraft-liesmich.txt
@@ -0,0 +1,36 @@
+Dieser Ordner enthält ein Java-Projekt, in dem die Implementierung
+eines tabellengetriebenen DEA geübt wird. Es kann mit BlueJ oder
+einem anderen Java-Werkzeug bearbeitet werden.
+
+Das Projekt liegt in drei Ausstattungen vor; Sie als Lehrkraft
+entscheiden, welche Variante(n) Sie den Schülern vorlegen.
+
+Der Ordner...
+
+.skelett
+--------
+enthält das Rohprojekt ohne Lösungshinweise oder Tipps, aber mit
+Spezifikation, Arbeitsanweisungen und JUnit-Test. Das Projekt
+sollte fehlerfrei compilieren und lauffähig sein, aber natürlich
+schlagen die Tests fehl.
+
+.tipp
+-----
+enthält das gleiche Projekt, aber zusätzlich mit Tipps für die
+Bearbeitung durch Schüler.
+
+.lsg
+----
+enthält die Musterlösung des fertig ausprogrammierten Projekts.
+Hier sollten alle Tests erfolgreich laufen.
+
+Zu bearbeiten sind die Datei EndlicherAutomat.java, in der der
+eigentliche Tabellenmechanismus implementiert wird, und eine Auswahl
+der Beispiel-DFA für
+
+Mailadressen
+007-Suche
+oder Binärzahlen
+
+bzw. eigene DFA für andere Sprachen nach Wahl.
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/roh/package.bluej b/Quellcodes/AuS_A_DFA_Implementieren/roh/package.bluej
new file mode 100644
index 0000000..a54f5f2
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/roh/package.bluej
@@ -0,0 +1,75 @@
+#BlueJ package file
+dependency1.from=DFA_BeispieleTest
+dependency1.to=BinaerzahlenPruefer
+dependency1.type=UsesDependency
+dependency2.from=DFA_BeispieleTest
+dependency2.to=MailadressenChecker
+dependency2.type=UsesDependency
+dependency3.from=DFA_BeispieleTest
+dependency3.to=KGB_007Sucher
+dependency3.type=UsesDependency
+editor.fx.0.height=0
+editor.fx.0.width=0
+editor.fx.0.x=0
+editor.fx.0.y=0
+objectbench.height=119
+objectbench.width=770
+package.divider.horizontal=0.5785785785785785
+package.divider.vertical=0.7519685039370079
+package.editor.height=375
+package.editor.width=643
+package.editor.x=100
+package.editor.y=100
+package.frame.height=600
+package.frame.width=800
+package.numDependencies=3
+package.numTargets=6
+package.showExtends=true
+package.showUses=true
+project.charset=UTF-8
+readme.height=58
+readme.name=@README
+readme.width=47
+readme.x=10
+readme.y=10
+target1.height=62
+target1.name=bin
+target1.type=PackageTarget
+target1.width=80
+target1.x=70
+target1.y=10
+target2.height=50
+target2.name=KGB_007Sucher
+target2.showInterface=false
+target2.type=ClassTarget
+target2.width=140
+target2.x=10
+target2.y=130
+target3.height=50
+target3.name=DFA_BeispieleTest
+target3.showInterface=false
+target3.type=UnitTestTargetJunit4
+target3.width=160
+target3.x=180
+target3.y=240
+target4.height=50
+target4.name=EndlicherAutomat
+target4.showInterface=false
+target4.type=ClassTarget
+target4.width=160
+target4.x=180
+target4.y=30
+target5.height=50
+target5.name=MailadressenChecker
+target5.showInterface=false
+target5.type=ClassTarget
+target5.width=180
+target5.x=170
+target5.y=130
+target6.height=50
+target6.name=BinaerzahlenPruefer
+target6.showInterface=false
+target6.type=ClassTarget
+target6.width=180
+target6.x=380
+target6.y=130
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/tipp/.classpath b/Quellcodes/AuS_A_DFA_Implementieren/tipp/.classpath
new file mode 100644
index 0000000..a177209
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/tipp/.classpath
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/tipp/.project b/Quellcodes/AuS_A_DFA_Implementieren/tipp/.project
new file mode 100644
index 0000000..5557916
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/tipp/.project
@@ -0,0 +1,17 @@
+
+
+ tabellen-dfa
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/tipp/BinaerzahlenPruefer.java b/Quellcodes/AuS_A_DFA_Implementieren/tipp/BinaerzahlenPruefer.java
new file mode 100644
index 0000000..b015504
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/tipp/BinaerzahlenPruefer.java
@@ -0,0 +1,102 @@
+/**
+ * Implementiert einen DEA, der 0/1-Folgen darauf prüft, ob
+ * sie "gültige Binärzahlen" darstellen.
+ * Gültige Binärzahlen im Sinne dieser Aufgabe beginnen mit
+ * einer 1, auf die eine beliebige Folge von 0/1 folgt. Die
+ * einzelne Ziffer 0 ist ebenfalls erlaubt, jedoch keine
+ * Binärzahlen mit "überflüssigen" führenden Nullen. Die
+ * Binärzahl darf außerdem ein Vorzeichen führen (muss aber
+ * nicht).
+ *
+ * Gültig sind beispielsweise:
+ * 1
+ * 0
+ * 101
+ * 11
+ * 10
+ * 1110010010
+ * 111
+ * -1
+ * 1000000000
+ * +1
+ * 1001001100
+ *
+ * Ungültig sind beispielsweise:
+ * 123
+ * 00
+ * hallo
+ * 0000000011111
+ * 1+1
+ * Binärzahl
+ * abc
+ * 321
+ * 01010101010101
+ * 0101
+ * 01
+ * 0101010101
+ *
+ * @author Urs Lautebach
+ * @version 2021-Januar
+ */
+
+
+public class BinaerzahlenPruefer extends EndlicherAutomat {
+ /* Bei der Implementierung dieser Klasse muss man nur
+ * die Attribute alphabet, uebergaenge und endzustaende
+ * geeignet festlegen -- alles andere macht die
+ * Vaterklasse "EndlicherAutomat.java".
+ *
+ * Dort ist auch erklärt, wie die Nummerierung der
+ * Zustände, des Startzustand und der Übergangstabelle
+ * zu verstehen sind.
+ */
+
+ // Transitionstabelle anlegen mit den Zuständen auf der
+ // senkrechten und den Alphabetzeichen auf der Rechtsachse:
+ private static final int[][] transiTabelle = new int [][] {
+ };
+
+ // Alphabet für diesen Automaten als char[]
+ private static final char[] binaerzAlph = new char[] {
+ };
+
+ // Menge der Endzustände:
+ private static final int[] endzustaende = new int[] {
+ };
+
+ /**
+ * Konstruktor für einen BinaerzahlenPruefer:
+ */
+ public BinaerzahlenPruefer() {
+ // Aufruf des super-Konstruktors:
+ super(binaerzAlph, transiTabelle, endzustaende);
+ }
+
+ /**
+ * Die main-Methode erlaubt den Aufruf von
+ * Binaerzahlenpruefer von der Kommandozeile aus mit
+ * mehreren zu testenden Strings:
+ *
+ * java BinaerzahlenPruefer 1110101 0001 +1010 abc
+ *
+ * Die Ausgabe lautet dann
+ * Akzeptiert: "1110101" ist ein gueltiges Binärwort.
+ * FEHLER! "0001" ist kein gültiges Binärwort!
+ * Akzeptiert: "+1010" ist ein gueltiges Binärwort.
+ * FEHLER! "abc" ist kein gültiges Binärwort!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat binaerzahlenDFA = new BinaerzahlenPruefer();
+
+ for(String wort : args) {
+ if(binaerzahlenDFA.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" ist ein gültiges Binärwort.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" ist kein gültiges Binärwort!");
+ }
+ }
+ }
+}
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/tipp/DEA_BeispieleTest.java b/Quellcodes/AuS_A_DFA_Implementieren/tipp/DEA_BeispieleTest.java
new file mode 100644
index 0000000..d544eb0
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/tipp/DEA_BeispieleTest.java
@@ -0,0 +1,104 @@
+import static org.junit.Assert.*;
+import org.junit.Test;
+public class DEA_BeispieleTest {
+
+ public DEA_BeispieleTest() {
+ }
+
+ @Test
+ public void testBinaerzahlenPruefer() {
+ BinaerzahlenPruefer binZPruefer = new BinaerzahlenPruefer();
+ assertTrue(binZPruefer.gehoertZuSprache("1"));
+ assertTrue(binZPruefer.gehoertZuSprache("0"));
+ assertTrue(binZPruefer.gehoertZuSprache("+1"));
+ assertTrue(binZPruefer.gehoertZuSprache("+0"));
+ assertTrue(binZPruefer.gehoertZuSprache("-1"));
+ assertTrue(binZPruefer.gehoertZuSprache("-0"));
+ assertTrue(binZPruefer.gehoertZuSprache("11"));
+ assertTrue(binZPruefer.gehoertZuSprache("10"));
+ assertTrue(binZPruefer.gehoertZuSprache("+11"));
+ assertTrue(binZPruefer.gehoertZuSprache("-11"));
+ assertTrue(binZPruefer.gehoertZuSprache("+10"));
+ assertTrue(binZPruefer.gehoertZuSprache("1111"));
+ assertTrue(binZPruefer.gehoertZuSprache("1000"));
+ assertTrue(binZPruefer.gehoertZuSprache("10100101010111000"));
+ assertTrue(binZPruefer.gehoertZuSprache("1111111"));
+
+ assertFalse(binZPruefer.gehoertZuSprache(""));
+ assertFalse(binZPruefer.gehoertZuSprache("+"));
+ assertFalse(binZPruefer.gehoertZuSprache("-"));
+ assertFalse(binZPruefer.gehoertZuSprache("x"));
+ assertFalse(binZPruefer.gehoertZuSprache("binärzahl"));
+ assertFalse(binZPruefer.gehoertZuSprache("00"));
+ assertFalse(binZPruefer.gehoertZuSprache("+00"));
+ assertFalse(binZPruefer.gehoertZuSprache("0+0"));
+ assertFalse(binZPruefer.gehoertZuSprache("123"));
+ assertFalse(binZPruefer.gehoertZuSprache("0011"));
+ assertFalse(binZPruefer.gehoertZuSprache("011"));
+ assertFalse(binZPruefer.gehoertZuSprache("111111+"));
+ assertFalse(binZPruefer.gehoertZuSprache("000000+"));
+ assertFalse(binZPruefer.gehoertZuSprache("1+1"));
+ assertFalse(binZPruefer.gehoertZuSprache("0+1"));
+ assertFalse(binZPruefer.gehoertZuSprache("1+0"));
+ }
+
+ @Test
+ public void testMailadressenChecker() {
+ MailadressenChecker mailAdrPruefer = new MailadressenChecker();
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.bbbb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b.b.b@bbb.bbb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("bbbbbb@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("b@b.b.b.b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("...@b.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("...bbb@bb.bb"));
+ assertTrue(mailAdrPruefer.gehoertZuSprache("bbb...@bb.bb"));
+
+ assertFalse(mailAdrPruefer.gehoertZuSprache(""));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("@"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("b@b.b@bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("@bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@.."));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@bb.b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb@bb.bb.b"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bb.bb.bb.bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache(
+ "bbb@bb.bb.bb@bb.bb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb..bbb"));
+ assertFalse(mailAdrPruefer.gehoertZuSprache("bbb@bbb.bbb.."));
+ }
+
+ @Test
+ public void test007Sucher() {
+ KGB_007Sucher detektiv = new KGB_007Sucher();
+ assertTrue(detektiv.gehoertZuSprache("007"));
+ assertTrue(detektiv.gehoertZuSprache("1007"));
+ assertTrue(detektiv.gehoertZuSprache("0071"));
+ assertTrue(detektiv.gehoertZuSprache("007007"));
+ assertTrue(detektiv.gehoertZuSprache("00007"));
+ assertTrue(detektiv.gehoertZuSprache("0000712"));
+ assertTrue(detektiv.gehoertZuSprache("2121200777"));
+ assertTrue(detektiv.gehoertZuSprache("0077"));
+ assertTrue(detektiv.gehoertZuSprache("212121007000000"));
+ assertTrue(detektiv.gehoertZuSprache("00712772712717"));
+
+ assertFalse(detektiv.gehoertZuSprache(""));
+ assertFalse(detektiv.gehoertZuSprache("0"));
+ assertFalse(detektiv.gehoertZuSprache("1"));
+ assertFalse(detektiv.gehoertZuSprache("2"));
+ assertFalse(detektiv.gehoertZuSprache("7"));
+ assertFalse(detektiv.gehoertZuSprache("07"));
+ assertFalse(detektiv.gehoertZuSprache("001"));
+ assertFalse(detektiv.gehoertZuSprache("002"));
+ assertFalse(detektiv.gehoertZuSprache("000"));
+ assertFalse(detektiv.gehoertZuSprache("001002"));
+ assertFalse(detektiv.gehoertZuSprache("7001"));
+ assertFalse(detektiv.gehoertZuSprache("0707"));
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/tipp/EndlicherAutomat.java b/Quellcodes/AuS_A_DFA_Implementieren/tipp/EndlicherAutomat.java
new file mode 100644
index 0000000..a1015bd
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/tipp/EndlicherAutomat.java
@@ -0,0 +1,167 @@
+/**
+ * Implementiert einen tabellengetriebenen endlichen Automaten.
+ * Instanzen dieser Klasse sind DEAs, die Wörter über einem
+ * vorgegebenen Alphabet akzeptieren oder ablehnen können.
+ *
+ * Die Aufgabe wurde vom schriftlichen Abitur 2020 in
+ * Baden-Württemberg inspiriert.
+ *
+ * @author Urs Lautebach
+ * @version 2020-Oktober
+ */
+public class EndlicherAutomat {
+ private int [][] uebergaenge = null;
+ private int[] endzustaende = null;
+ private char[] alphabet = null;
+
+ /**
+ * Konstruiert einen tabellengetriebenen DEA. Nach dem
+ * erfolgreichen Aufruf dieses Konstruktors kann man den DEA
+ * anschließend durch einen Aufruf der Methode
+ * gehoertZuSprache(String):boolean
+ * beliebig viele Wörter testen lassen.
+ *
+ * @param tabelle Transitionstabelle des DEA. Die erste
+ * Dimension bezeichnet die Zustände; die zweite Dimension die
+ * Eingabezeichen. Die Einträge der Tabelle bezeichnen jeweils
+ * den Zustand, in den der Automat (abhängig vom vorherigen
+ * Zustand und der Eingabe) wechseln soll.
+ *
+ * Der Zustand 0 gilt als Fehlerzustand. Zustand 1 ist immer
+ * Startzustand (so dass der Startzustand, anders als bei der
+ * formalen Beschreibung eines DEA, nicht explizit angegeben
+ * werden muss).
+ *
+ * @param finalStates Ein int[], das die Endzustände enthält.
+ *
+ * @param alphabet ein Array von char, das das Alphabet des
+ * Automaten enthält. Die Reihenfolge der Zeichen im Alphabet
+ * muss der Reihenfolge der Zeichen an der entsprechenden
+ * Achse der Transitionstabelle entsprechen.
+ */
+ EndlicherAutomat(final char[] alphabet,
+ final int[][] uebergaenge, final int[] endzustaende ) {
+ // Die Methode plausibilitaetPruefen ist fertig vorgegeben;
+ // sie fängt einige offensichtliche Fehler ab:
+ plausibilitaetPruefen();
+ }
+
+ /**
+ * Die Methode prüft, ob die Attribute transitionstabelle,
+ * alphabet und endzustaende zueinander passen. Sie ist fertig
+ * implementiert und dafür gedacht, am Ende des Konstruktors
+ * aufgerufen zu werden.
+ */
+ private void plausibilitaetPruefen() {
+ if (uebergaenge == null) {
+ throw new IllegalArgumentException(
+ "Die Übergangstabelle ist null oder leer!");
+ }
+ if (alphabet == null) {
+ throw new IllegalArgumentException(
+ "Das Alphabet ist null oder leer!");
+ }
+ if (endzustaende == null) {
+ throw new IllegalArgumentException(
+ "endzustaende ist null oder leer!");
+ }
+ int tabelleHoehe = this.uebergaenge.length;
+ int tabelleBreite = uebergaenge[0].length;
+ // Hat die Übergangstabelle eine Zeile pro Alphabetzeichen?
+ if (tabelleBreite != alphabet.length) {
+ throw new IllegalArgumentException("Das Alphabet hat " +
+ alphabet.length + " Zeichen, die " +
+ " Übergangstabelle aber " + tabelleBreite +
+ " Spalten!");
+ }
+ // Sind alle Zeilen der Transitionstabelle gleich lang?
+ for (int[] zeile : uebergaenge) {
+ if (zeile.length != tabelleBreite) {
+ throw new IllegalArgumentException(
+ "Übergangstabelle ist nicht rechteckig!");
+ }
+ }
+ // Hat einer der Endzustände eine unplausible Nummer?
+ for (int zustand : endzustaende) {
+ if (zustand < 1 || zustand > tabelleHoehe - 1) {
+ throw new IllegalArgumentException(
+ "Der Endzustand " + zustand +
+ " kommt in der Übergangstabelle nicht vor!");
+ }
+ }
+ }
+
+ /**
+ * Ermittelt die Nummer (den Index) des angegebenen Zeichens
+ * innerhalb des Alphabetes dieses Automaten.
+ *
+ * @param input Zeichen, dessen Position ermittelt werden soll.
+ * @returns Position des Zeichens input innerhalb des Alphabets
+ * dieses Automaten; oder -1, falls es im Alphabet nicht
+ * enthalten ist.
+ */
+ public int indexImAlphabet(char input) {
+ // TODO: Implementieren Sie diese Methode.
+ /* Man geht das Alphabet durch und prüft, welches seiner
+ * Zeichen dem "input" entspricht. Falls man es findet,
+ * gibt man dessen Index zurück.
+ */
+ return -54321; // dummy return
+ }
+
+ /**
+ * Überprüft, ob der Zustand mit der übergebenen
+ * Zustandsnummer einer der Endzustände dieses Automaten ist.
+ *
+ * @param nr Nummer des fraglichen Zustandes.
+ * @return ob der Zustand ein Endzustand ist.
+ */
+ public boolean istEndzustand(int nr) {
+ // TODO: Implementieren Sie diese Methode.
+ return false; // dummy return
+ }
+
+ /**
+ * Die Methode kann mit einem String als Parameter aufgerufen
+ * werden, was oft bequemer ist als ein char[].
+ *
+ * @param s String mit dem zu prüfenden Wort.
+ * @return ob s von diesem Automaten erkannt wird.
+ */
+ public boolean gehoertZuSprache(String s) {
+ // Hier ist nichts zu implementieren.
+ return gehoertZuSprache(s.toCharArray());
+ }
+
+ /**
+ * Übergibt dem DEA ein ganzes Wort und ermittelt, ob er es
+ * akzeptiert oder nicht.
+ *
+ * @param eingabe Die komplette zu analysierende Eingabe als
+ * char[].
+ * @returns true, wenn das Wort vom DEA akzeptiert wird;
+ * false sonst.
+ */
+ public boolean gehoertZuSprache(final char[] wort) {
+ // TODO: Implementieren Sie diese Methode.
+ /*
+ * Um zu prüfen, ob wort akzeptiert wird, muss der DEA...
+ *
+ * - in Zustand 1 beginnen;
+ *
+ * - das Eingabewort Zeichen für Zeichen durchgehen;
+ *
+ * - prüfen, ob das Zeichen im Alphabet vorkommt;
+ *
+ * - nach dessen Position im Alphabet und altem Zustand
+ * einen neuen Zustand aus der Tabelle uebergaenge wählen;
+ *
+ * - false antworten, wenn er im Fehlerzustand landet,
+ *
+ * - am Schluss der Eingabe entscheiden, ob der erreichte
+ * Zustand ein Endzustand ist.
+ */
+ return false; // dummy return
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/tipp/KGB_007Sucher.java b/Quellcodes/AuS_A_DFA_Implementieren/tipp/KGB_007Sucher.java
new file mode 100644
index 0000000..7025f54
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/tipp/KGB_007Sucher.java
@@ -0,0 +1,85 @@
+/**
+ * Dieser DFA erkennt Ziffernfolgen, in denen sich irgendwo
+ * James Bond versteckt hat -- in denen also die Folge 007
+ * vorkommt.
+ *
+ * Die folgenden Ziffernfolgen sollen beispielsweise akzeptiert
+ * werden:
+ *
+ * 12107117700710012021,
+ * 007,
+ * 0071121727,
+ * 0000000071121727,
+ * 007007007007,
+ * 1121271201212007.
+ *
+ * Die folgenden Ziffernfolgen sollen nicht akzeptiert werden:
+ *
+ * 12107110710012021,
+ * 07,
+ * 00,
+ * 07112172,
+ * 1121271201212000.
+
+ * Um den Automaten und vor allem die Übergangstabelle
+ * übersichtlicher zu halten, verwendet er nicht alle Ziffern,
+ * sondern lediglich das eingeschränkte Alphabet {0, 1, 2, 7}.
+ *
+ * Es empfiehlt sich, den Automaten zunächst zu zeichnen,
+ * die Übergangstabelle auf Papier zu erstellen und dann zu
+ * programmieren.
+ *
+ * @author Urs Lautebach
+ * @version 2020-Okt
+ */
+
+public class KGB_007Sucher extends EndlicherAutomat {
+ /* Bei der Implementierung dieser Klasse muss man nur
+ * die Attribute alphabet, uebergaenge und endzustaende
+ * geeignet festlegen -- alles andere macht die
+ * Vaterklasse.
+ */
+ private static final char[] alphabet = new char[] {
+ };
+
+ private static final int[][] uebergaenge = new int[][] {
+ };
+
+ private static final int[] endzustaende = new int[] {
+ };
+
+ /**
+ * Instanziiert einen KGB_007Sucher-DFA.
+ */
+ KGB_007Sucher() {
+ // Aufruf des super-Konstruktors:
+ super(alphabet, uebergaenge, endzustaende);
+ }
+
+ /**
+ * Die main-Methode erlaubt den Aufruf des
+ * Binaerzahlenpruefers von der Kommandozeile aus mit:
+ *
+ * java KGB_007Sucher 127007117 1717771021
+ *
+ * Die Ausgabe lautet dann
+ *
+ * Akzeptiert: "127007117" enthält 007.
+ * FEHLER! "1717771021" enthält kein 007!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat fahnder = new KGB_007Sucher();
+
+ for(String wort : args) {
+ if(fahnder.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" enthält 007.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" enthält kein 007!");
+ }
+ }
+ }
+}
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/tipp/MailadressenChecker.java b/Quellcodes/AuS_A_DFA_Implementieren/tipp/MailadressenChecker.java
new file mode 100644
index 0000000..b5149ed
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/tipp/MailadressenChecker.java
@@ -0,0 +1,83 @@
+/**
+ * Die Klasse implementiert einen DEA für die Überprüfung äußerst
+ * einfacher Mailadressen, die nur aus dem Buchstaben b, Punkten
+ * und dem at-Zeichen bestehen dürfen. Der Nutzername darf fast
+ * beliebig aufgebaut sein; die Domain muss mindestens zweistufig
+ * sein und die Toplevel-Domain muss mindestens zwei Zeichen haben.
+ *
+ * Gültig sind damit beispielsweise:
+ * b@b.bb
+ * b@b.bbbb
+ * b.b.b@bbb.bbb
+ * bbbbbb@b.bb
+ * b@b.b.b.b.bb
+ * ...@b.bb
+ * ...bbb@bb.bb
+ * bbb...@bb.bb
+ *
+ * Ungültig sind beispielsweise:
+ * .
+ * b
+ * @
+ * bb@
+ * b@b.b@bbb
+ * b@b.b@bb.b
+ * @bb
+ * bb@.
+ * bb@..
+ *
+ * Tatsächlich ist die Überprüfung realer Mailadressen wesentlich
+ * komlizierter als in diesem Beispiel.
+ *
+ * @author Urs Lautebach
+ * @version 2021-Janar
+ *
+ */
+public class MailadressenChecker extends EndlicherAutomat {
+ /* Bei der Implementierung dieser Klasse muss man nur
+ * die Attribute alphabet, uebergaenge und endzustaende
+ * geeignet festlegen -- alles andere macht die
+ * Vaterklasse.
+ */
+
+ private static final char[] alphabet = new char[] {
+ };
+ private static final int[][] transitionen = new int[][] {
+ };
+
+ private static final int[] endzustaende = new int[] {
+ };
+
+ MailadressenChecker() {
+ // Aufruf des super-Konstruktors:
+ super(alphabet, transitionen, endzustaende);
+ }
+
+
+ /**
+ * Die main-Methode erlaubt den Aufruf des
+ * Binaerzahlenpruefers von der Kommandozeile mit beliebig
+ * vielen zu prüfenden Strings:
+ * java MailadressenChecker bbb.b@bb.bb a@b@c
+ *
+ * Die Ausgabe lautet dann
+ *
+ * Akzeptiert: "bbb.b@bb.bb" ist eine gültige Mailadresse.
+ * FEHLER! "a@b@c" ist als Mailadresse ungültig!
+ */
+ public static void main(String[] args) {
+ // Endlichen Automaten instanziieren:
+ EndlicherAutomat checker = new MailadressenChecker();
+
+ for(String wort : args) {
+ if(checker.gehoertZuSprache(wort)) {
+ System.out.println("Akzeptiert: \"" + wort +
+ "\" ist eine gültige Mailadresse.");
+ } else {
+ System.out.println("FEHLER! \"" + wort +
+ "\" ist als Mailadresse ungültig!");
+ } // end if
+ } // end for
+ } // end main
+} // end class
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/tipp/README.md b/Quellcodes/AuS_A_DFA_Implementieren/tipp/README.md
new file mode 100644
index 0000000..c2be6f0
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/tipp/README.md
@@ -0,0 +1,3 @@
+# Tabellen Dfa
+
+Implementierung eines allgemeinen tabellengetriebenen DFA als Programmieraufgabe (samt einiger Beispiel-DFA).
\ No newline at end of file
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/tipp/lehrkraft-liesmich.txt b/Quellcodes/AuS_A_DFA_Implementieren/tipp/lehrkraft-liesmich.txt
new file mode 100644
index 0000000..63abfcd
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/tipp/lehrkraft-liesmich.txt
@@ -0,0 +1,36 @@
+Dieser Ordner enthält ein Java-Projekt, in dem die Implementierung
+eines tabellengetriebenen DEA geübt wird. Es kann mit BlueJ oder
+einem anderen Java-Werkzeug bearbeitet werden.
+
+Das Projekt liegt in drei Ausstattungen vor; Sie als Lehrkraft
+entscheiden, welche Variante(n) Sie den Schülern vorlegen.
+
+Der Ordner...
+
+.skelett
+--------
+enthält das Rohprojekt ohne Lösungshinweise oder Tipps, aber mit
+Spezifikation, Arbeitsanweisungen und JUnit-Test. Das Projekt
+sollte fehlerfrei compilieren und lauffähig sein, aber natürlich
+schlagen die Tests fehl.
+
+.tipp
+-----
+enthält das gleiche Projekt, aber zusätzlich mit Tipps für die
+Bearbeitung durch Schüler.
+
+.lsg
+----
+enthält die Musterlösung des fertig ausprogrammierten Projekts.
+Hier sollten alle Tests erfolgreich laufen.
+
+Zu bearbeiten sind die Datei EndlicherAutomat.java, in der der
+eigentliche Tabellenmechanismus implementiert wird, und eine Auswahl
+der Beispiel-DFA für
+
+Mailadressen
+007-Suche
+oder Binärzahlen
+
+bzw. eigene DFA für andere Sprachen nach Wahl.
+
diff --git a/Quellcodes/AuS_A_DFA_Implementieren/tipp/package.bluej b/Quellcodes/AuS_A_DFA_Implementieren/tipp/package.bluej
new file mode 100644
index 0000000..a54f5f2
--- /dev/null
+++ b/Quellcodes/AuS_A_DFA_Implementieren/tipp/package.bluej
@@ -0,0 +1,75 @@
+#BlueJ package file
+dependency1.from=DFA_BeispieleTest
+dependency1.to=BinaerzahlenPruefer
+dependency1.type=UsesDependency
+dependency2.from=DFA_BeispieleTest
+dependency2.to=MailadressenChecker
+dependency2.type=UsesDependency
+dependency3.from=DFA_BeispieleTest
+dependency3.to=KGB_007Sucher
+dependency3.type=UsesDependency
+editor.fx.0.height=0
+editor.fx.0.width=0
+editor.fx.0.x=0
+editor.fx.0.y=0
+objectbench.height=119
+objectbench.width=770
+package.divider.horizontal=0.5785785785785785
+package.divider.vertical=0.7519685039370079
+package.editor.height=375
+package.editor.width=643
+package.editor.x=100
+package.editor.y=100
+package.frame.height=600
+package.frame.width=800
+package.numDependencies=3
+package.numTargets=6
+package.showExtends=true
+package.showUses=true
+project.charset=UTF-8
+readme.height=58
+readme.name=@README
+readme.width=47
+readme.x=10
+readme.y=10
+target1.height=62
+target1.name=bin
+target1.type=PackageTarget
+target1.width=80
+target1.x=70
+target1.y=10
+target2.height=50
+target2.name=KGB_007Sucher
+target2.showInterface=false
+target2.type=ClassTarget
+target2.width=140
+target2.x=10
+target2.y=130
+target3.height=50
+target3.name=DFA_BeispieleTest
+target3.showInterface=false
+target3.type=UnitTestTargetJunit4
+target3.width=160
+target3.x=180
+target3.y=240
+target4.height=50
+target4.name=EndlicherAutomat
+target4.showInterface=false
+target4.type=ClassTarget
+target4.width=160
+target4.x=180
+target4.y=30
+target5.height=50
+target5.name=MailadressenChecker
+target5.showInterface=false
+target5.type=ClassTarget
+target5.width=180
+target5.x=170
+target5.y=130
+target6.height=50
+target6.name=BinaerzahlenPruefer
+target6.showInterface=false
+target6.type=ClassTarget
+target6.width=180
+target6.x=380
+target6.y=130