diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f68d109 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..df543e3 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..506f8fd --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/KotlinJavaRuntime.xml b/.idea/libraries/KotlinJavaRuntime.xml new file mode 100644 index 0000000..c9c6ce8 --- /dev/null +++ b/.idea/libraries/KotlinJavaRuntime.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..ef89d98 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..d365af0 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Automate.iml b/Automate.iml new file mode 100644 index 0000000..2f77829 --- /dev/null +++ b/Automate.iml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9d3e0bf --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +# Simulation d'un automate en Kotlin + +Ce projet Kotlin simule un automate fini simple. Il permet de définir des états, des transitions entre eux, et de vérifier si un mot donné est accepté par l'automate. + +## Comment lancer le projet ? + +Lancez [le .jar](automateDemo.jar) avec la commande `java -jar .\automateDemo.jar` + +## Automates par défauts +(dans `Main.kt`) + +Voici les automates disponibles : + +- Automate acceptant les nombres de 01 à 57 + [![Automate 01-57](src/main/resources/auto_exo7-01-57.jpg)](src/main/resources/auto_exo7-01-57.jpg) + +- Automate acceptant les dates (format JJ/MM/AAAA) + [![Automate Date](src/main/resources/auto_exo7-Date.jpg)](src/main/resources/auto_exo7-Date.jpg) + +- Automate acceptant les heures (HH:MM) + [![Automate Heure](src/main/resources/auto_exo7-Heure.jpg)](src/main/resources/auto_exo7-Heure.jpg) + +## Classes + +### `State` +Cette classe représente un état dans l'automate. + +- **Attributs** : + - `nom` : Nom de l'état. + - `transitions` : Un dictionnaire de transitions où la clé est un caractère et la valeur est l'état suivant. + +- **Fonctions** : + - `getNom()` : Retourne le nom de l'état. + - `getTransition()` : Retourne la table des transitions de l'état. + - `addTransition(c: Char, destination: State)` : Ajoute une transition de cet état vers un autre, basée sur le caractère `c`. + +- **Méthode statique** : + - `createStates(word: String, start: Int, end: Int): MutableList` : Crée une liste d'états avec des noms basés sur `word` et des indices allant de `start` à `end`. + +### `Automate` +Cette classe représente l'automate lui-même. + +- **Attributs** : + - `s0` : L'état de départ. + - `sf` : Un ensemble d'états finaux (états d'acceptation). + - `alpha` : Un ensemble de caractères (alphabet) reconnu par l'automate. + - `etats` : Un ensemble de tous les états de l'automate. + - `delta` : Un dictionnaire des transitions entre les états. + +- **Fonctions** : + - `setStartingState(s0: State)` : Définit l'état de départ de l'automate. + - `getStartingState()` : Retourne l'état de départ. + - `addFinalState(s: State)` : Ajoute un état final (d'acceptation). + - `getFinalStates()` : Retourne l'ensemble des états finaux. + - `getDeltas()` : Retourne la table des transitions (fonction delta). + - `addDelta(source: State, c: Char, destination: State)` : Ajoute une transition de `source` à `destination` basée sur le caractère `c`. + - `addDeltaFromList(source: State, ls: List, destination: State)` : Ajoute plusieurs transitions de `source` à `destination` basées sur une liste de caractères `ls`. + - `addDeltaFromString(source: State, exp: String, destination: State)` : Ajoute des transitions basées sur une expression sous forme de chaîne (supporte les intervalles comme `a..z` ou des caractères individuels comme `a | b`). + - `getAlpha()` : Retourne l'ensemble des caractères de l'alphabet. + - `getStates()` : Retourne l'ensemble de tous les états. + - `getNom()` : Retourne le nom de l'automate. + - `DoYouAccept(word: String, debug_Output: Boolean = true): Boolean` : Vérifie si l'automate accepte un mot donné et affiche les étapes de transition si `debug_Output` est défini à `true`. + +## Exemple + +L'exemple suivant montre comment créer un automate qui n'accepte que les nombre de 01 (inclus) à 57 (inclus), définir des transitions et vérifier si un mot est accepté. + +[![Automate 01-57](src/main/resources/auto_exo7-01-57.jpg)](src/main/resources/auto_exo7-01-57.jpg) + +```kotlin +val Etats_0157 = State.createStates("A", 0, 7) +val Auto_0157 = Automate("01-57") + +// Ajout des transitions +Auto_0157.addDeltaFromString(Etats_0157[0], "0", Etats_0157[1]) +Auto_0157.addDeltaFromString(Etats_0157[1], "1..9", Etats_0157[7]) +Auto_0157.addDeltaFromString(Etats_0157[0], "1..4", Etats_0157[3]) +Auto_0157.addDeltaFromString(Etats_0157[3], "0..9", Etats_0157[7]) +Auto_0157.addDeltaFromString(Etats_0157[0], "5", Etats_0157[5]) +Auto_0157.addDeltaFromString(Etats_0157[5], "0..7", Etats_0157[7]) + +// Définition de l'état de départ et de l'état final +Auto_0157.setStartingState(Etats_0157[0]) +Auto_0157.addFinalState(Etats_0157[7]) + +// Vérification si un mot est accepté +var isAccepted = Auto_0157.DoYouAccept("111") +println("Mot accepté : $isAccepted") //Mot accepté : false +isAccepted = Auto_0157.DoYouAccept("24") +println("Mot accepté : $isAccepted") //Mot accepté : true +``` +Dans cet exemple : +- On crée 8 états (de A0 à A7). +- On définit des transitions pour les caractères entre les états. +- L'automate commence à l'état A0 et accepte le mot lorsqu'il atteint l'état A7. +- Les mots 111 et 24 sont vérifiés pour être acceptés. + +## Conclusion + +Cet automate basé sur Kotlin permet de modéliser et simuler des systèmes à états avec des transitions entre les états selon des entrées de caractères. La fonction DoYouAccept() évalue si un mot est valide selon les règles de l'automate. \ No newline at end of file diff --git a/automateDemo.jar b/automateDemo.jar new file mode 100644 index 0000000..d5266d9 Binary files /dev/null and b/automateDemo.jar differ diff --git a/lib/apiguardian-api-1.1.2.jar b/lib/apiguardian-api-1.1.2.jar new file mode 100644 index 0000000..2b678e1 Binary files /dev/null and b/lib/apiguardian-api-1.1.2.jar differ diff --git a/lib/hamcrest-core-1.3-sources.jar b/lib/hamcrest-core-1.3-sources.jar new file mode 100644 index 0000000..c3c110b Binary files /dev/null and b/lib/hamcrest-core-1.3-sources.jar differ diff --git a/lib/hamcrest-core-1.3.jar b/lib/hamcrest-core-1.3.jar new file mode 100644 index 0000000..9d5fe16 Binary files /dev/null and b/lib/hamcrest-core-1.3.jar differ diff --git a/lib/junit-4.13.1-sources.jar b/lib/junit-4.13.1-sources.jar new file mode 100644 index 0000000..b68ac35 Binary files /dev/null and b/lib/junit-4.13.1-sources.jar differ diff --git a/lib/junit-4.13.1.jar b/lib/junit-4.13.1.jar new file mode 100644 index 0000000..b376ffc Binary files /dev/null and b/lib/junit-4.13.1.jar differ diff --git a/lib/junit-jupiter-5.8.1.jar b/lib/junit-jupiter-5.8.1.jar new file mode 100644 index 0000000..730b9ae Binary files /dev/null and b/lib/junit-jupiter-5.8.1.jar differ diff --git a/lib/junit-jupiter-api-5.8.1.jar b/lib/junit-jupiter-api-5.8.1.jar new file mode 100644 index 0000000..8424eca Binary files /dev/null and b/lib/junit-jupiter-api-5.8.1.jar differ diff --git a/lib/junit-jupiter-engine-5.8.1.jar b/lib/junit-jupiter-engine-5.8.1.jar new file mode 100644 index 0000000..cfa38d2 Binary files /dev/null and b/lib/junit-jupiter-engine-5.8.1.jar differ diff --git a/lib/junit-jupiter-params-5.8.1.jar b/lib/junit-jupiter-params-5.8.1.jar new file mode 100644 index 0000000..1e4d0ec Binary files /dev/null and b/lib/junit-jupiter-params-5.8.1.jar differ diff --git a/lib/junit-platform-commons-1.8.1.jar b/lib/junit-platform-commons-1.8.1.jar new file mode 100644 index 0000000..20185cd Binary files /dev/null and b/lib/junit-platform-commons-1.8.1.jar differ diff --git a/lib/junit-platform-engine-1.8.1.jar b/lib/junit-platform-engine-1.8.1.jar new file mode 100644 index 0000000..54ce076 Binary files /dev/null and b/lib/junit-platform-engine-1.8.1.jar differ diff --git a/lib/opentest4j-1.2.0.jar b/lib/opentest4j-1.2.0.jar new file mode 100644 index 0000000..d500636 Binary files /dev/null and b/lib/opentest4j-1.2.0.jar differ diff --git a/src/main/kotlin/Automate.kt b/src/main/kotlin/Automate.kt new file mode 100644 index 0000000..1b78bde --- /dev/null +++ b/src/main/kotlin/Automate.kt @@ -0,0 +1,101 @@ +class Automate(nom : String) { + + private lateinit var s0 : State + private var sf : MutableSet = mutableSetOf() + private var nom : String = nom + private var alpha : MutableSet = mutableSetOf() + private var etats : MutableSet = mutableSetOf() + private var delta : HashMap> = hashMapOf() /// E0 -> {'c' -> {"E1"}} + ///////////////////////////////////Starting State | where we start + fun setStartingState(s0 : State) { + this.s0 = s0 + } + + fun getStartingState() = this.s0 + ///////////////////////////////////Final State | set of ending states + fun addFinalState(s : State) { + this.sf.add(s) + } + + fun getFinalStates() = this.sf + + ///////////////////////////////////Delta | all transition within + fun getDeltas() = this.delta // + + fun addDelta(source : State, c : Char ,destination : State) { + alpha.add(c) + etats.add(source) + etats.add(destination) + + val h : HashMap = hashMapOf() + source.addTransition(c,destination) + + delta.put(source,source.getTransition()) + } + + fun addDeltaFromList(source : State, ls : List ,destination : State) { + ls.forEach{it -> ( + addDelta(source,it,destination) + )} + } + + fun addDeltaFromString(source : State, exp : String, destination : State) { //from like "a | b..c" + val orexp = exp.split(" | ") + orexp.forEach { it -> ( + if (it.contains("..")) { //is a..b + val interexp = it.split("..") + val a = interexp[0] + val b = interexp[1] + if (a.length==1 && b.length==1) { + addDeltaFromList(source,(a.toCharArray()[0]..b.toCharArray()[0]).toList(),destination) + } else { + println("Impossible d'ajouté l'expression suivante : "+interexp) + } + + } else { + if (it.length==1) { //is just a char + addDelta(source,it.toCharArray()[0],destination) + } else { + println("Impossible d'ajouté l'expression suivante : "+it) + } + } + )} + } + ///////////////////////////////////Alpha | all characters that can be checked + fun getAlpha() = this.alpha + + ///////////////////////////////////States | all states within + fun getStates() = this.etats + + ///////////////////////////////////Nom + fun getNom() = this.nom + + ///////////////////////////////////Acceptor + fun DoYouAccept(word : String, debug_Output : Boolean = true) : Boolean { + var finalsState = getFinalStates() + if (finalsState.size==0) { + error("Pas de point de fin déclaré") + } + + var currentState = getStartingState() + var currentWord = word + + while (currentWord.isNotEmpty() || !finalsState.contains(currentState)) { // while not at one of the end AND still has characters left to check + try { + val old = currentState //save the state we are on + + currentState = currentState.getTransition().get(currentWord[0]) ?: return false // if it found one state linked to the 1st letter then move to it, else return false (nothing linked, stuck) + + if (debug_Output) { + println(old.getNom()+" ➜ "+currentState.getNom()) //told where we moved + } + + currentWord = currentWord.drop(1) // edit word so that it remove the letter that was analysed + } catch (e : Exception) { //In case of StringIndexesOutOfBound + return false + } + } + + return true // no characters left AND reach one of the end + } +} \ No newline at end of file diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt new file mode 100644 index 0000000..eeb32f2 --- /dev/null +++ b/src/main/kotlin/Main.kt @@ -0,0 +1,176 @@ +import kotlin.Exception + +fun createAuto_Heure() : Automate { + + val Etats_heure = State.createStates("e",0,9) + val Auto_heure = Automate("heure") + Auto_heure.addDeltaFromString(Etats_heure[0],"0 | 1",Etats_heure[1]) + Auto_heure.addDeltaFromString(Etats_heure[0],"2",Etats_heure[2]) + Auto_heure.addDeltaFromString(Etats_heure[1],"0..9",Etats_heure[3]) + Auto_heure.addDeltaFromString(Etats_heure[2],"0..3",Etats_heure[3]) + Auto_heure.addDeltaFromString(Etats_heure[3],":",Etats_heure[4]) + Auto_heure.addDeltaFromString(Etats_heure[4],"0..5",Etats_heure[5]) + Auto_heure.addDeltaFromString(Etats_heure[5],"0..9",Etats_heure[6]) + Auto_heure.addDeltaFromString(Etats_heure[6],":",Etats_heure[7]) + Auto_heure.addDeltaFromString(Etats_heure[7],"0..5",Etats_heure[8]) + Auto_heure.addDeltaFromString(Etats_heure[8],"0..9",Etats_heure[9]) + + Auto_heure.setStartingState(Etats_heure[0]) + Auto_heure.addFinalState(Etats_heure[9]) + + return Auto_heure +} + +fun createAuto_Date() : Automate { + val Etats_Date = State.createStates("D",0,29) + val Auto_Date = Automate("jj/mm/aaaa") + + Auto_Date.addDeltaFromString(Etats_Date[0], "0", Etats_Date[1]) + Auto_Date.addDeltaFromString(Etats_Date[0], "1", Etats_Date[2]) + Auto_Date.addDeltaFromString(Etats_Date[0], "2", Etats_Date[3]) + Auto_Date.addDeltaFromString(Etats_Date[1], "1..9", Etats_Date[4]) + Auto_Date.addDeltaFromString(Etats_Date[2], "0..9", Etats_Date[4]) + Auto_Date.addDeltaFromString(Etats_Date[3], "0..8", Etats_Date[4]) + Auto_Date.addDeltaFromString(Etats_Date[4], "/", Etats_Date[5]) + Auto_Date.addDeltaFromString(Etats_Date[5], "0", Etats_Date[6]) + Auto_Date.addDeltaFromString(Etats_Date[5], "1", Etats_Date[7]) + Auto_Date.addDeltaFromString(Etats_Date[3], "9", Etats_Date[8]) + Auto_Date.addDeltaFromString(Etats_Date[8], "/", Etats_Date[9]) + Auto_Date.addDeltaFromString(Etats_Date[9], "0", Etats_Date[10]) + Auto_Date.addDeltaFromString(Etats_Date[9], "1", Etats_Date[11]) + Auto_Date.addDeltaFromString(Etats_Date[12], "0", Etats_Date[13]) + Auto_Date.addDeltaFromString(Etats_Date[13], "/", Etats_Date[14]) + Auto_Date.addDeltaFromString(Etats_Date[14], "0", Etats_Date[15]) + Auto_Date.addDeltaFromString(Etats_Date[14], "1", Etats_Date[16]) + Auto_Date.addDeltaFromString(Etats_Date[12], "1", Etats_Date[17]) + Auto_Date.addDeltaFromString(Etats_Date[17], "1", Etats_Date[18]) + Auto_Date.addDeltaFromString(Etats_Date[18], "0", Etats_Date[19]) + Auto_Date.addDeltaFromString(Etats_Date[18], "1", Etats_Date[20]) + Auto_Date.addDeltaFromString(Etats_Date[6], "1..9", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[7], "0..2", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[10], "1 | 3..9", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[11], "0..2", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[15], "1 | 3..9", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[16], "0..2", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[19], "1 | 3 | 5 | 7 | 8", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[20], "0 | 2", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[21], "/", Etats_Date[22]) + Auto_Date.addDeltaFromString(Etats_Date[22], "0", Etats_Date[23]) + Auto_Date.addDeltaFromString(Etats_Date[23], "0", Etats_Date[24]) + Auto_Date.addDeltaFromString(Etats_Date[24], "0", Etats_Date[25]) + Auto_Date.addDeltaFromString(Etats_Date[22], "1..9", Etats_Date[26]) + Auto_Date.addDeltaFromString(Etats_Date[26], "0..9", Etats_Date[27]) + Auto_Date.addDeltaFromString(Etats_Date[27], "0..9", Etats_Date[28]) + Auto_Date.addDeltaFromString(Etats_Date[28], "0..9", Etats_Date[29]) + Auto_Date.addDeltaFromString(Etats_Date[25], "1..9", Etats_Date[29]) + Auto_Date.addDeltaFromString(Etats_Date[23], "1..9", Etats_Date[27]) + Auto_Date.addDeltaFromString(Etats_Date[24], "1..9", Etats_Date[28]) + //set Start and End + Auto_Date.setStartingState(Etats_Date[0]) + Auto_Date.addFinalState(Etats_Date[29]) + return Auto_Date +} + +fun createAuto_0157() : Automate { + val Etats_0157 = State.createStates("A",0,7) + val Auto_0157 = Automate("01-57") + + Auto_0157.addDeltaFromString(Etats_0157[0],"0",Etats_0157[1]) + Auto_0157.addDeltaFromString(Etats_0157[1],"1..9",Etats_0157[7]) + Auto_0157.addDeltaFromString(Etats_0157[0],"1..4",Etats_0157[3]) + Auto_0157.addDeltaFromString(Etats_0157[3],"0..9",Etats_0157[7]) + Auto_0157.addDeltaFromString(Etats_0157[0],"5",Etats_0157[5]) + Auto_0157.addDeltaFromString(Etats_0157[5],"0..7",Etats_0157[7]) + + Auto_0157.setStartingState(Etats_0157[0]) + Auto_0157.addFinalState(Etats_0157[7]) + return Auto_0157 +} + + +// ANSI Codes found online : https://gist.github.com/JBlond/2fea43a3049b38287e5e9cefc87b2124 +// light red : ${"\u001B[91m"} +// light purple : ${"\u001B[95m"} +// light yellow : ${"\u001B[93m"} +// light green : ${"\u001B[92m"} +// blue : ${"\u001B[34m"} +// end ANSI : ${"\u001B[0m"} + +fun main(args: Array) { + lateinit var auto : Automate + var input : String + + while (true) { + + ////INPUT CHOIX AUTOMATE + println(""" + ${"\u001B[93m"}--------------- Menu de mon TP ------------------${"\u001B[0m"} + ${"\u001B[93m"}1. 01-57 (pour reconnaitre un chiffre entre 01 et 57)${"\u001B[0m"} + ${"\u001B[93m"}2. HH:MM (pour reconnaitre une heure bien formée)${"\u001B[0m"} + ${"\u001B[93m"}3. JJ/MM/AAAA (pour reconnaitre une date bien formée)${"\u001B[0m"} + ${"\u001B[93m"}99. Arrêt de l'application${"\u001B[0m"} + """.trimIndent()) + println(""" + ${"\u001B[95m"}--------------- Question ------------------------${"\u001B[0m"} + ${"\u001B[95m"}Quel est votre choix ? (1-99)${"\u001B[0m"} + ${"\u001B[95m"}-------------------------------------------------${"\u001B[0m"} + """.trimIndent()) + input = readln() + try { + input.toInt() + when(input.toInt()) { + 99 -> {break} + 1 -> auto = createAuto_0157() + 2 -> auto = createAuto_Heure() + 3 -> auto = createAuto_Date() + else -> throw Exception() + } + + while (true) { + ////INPUT CHAINE A ANALYSER + println(""" + ${"\u001B[95m"}--------------- Question ------------------------${"\u001B[0m"} + ${"\u001B[95m"}Quel est la chaine de caractère que vous voulez analyser ?${"\u001B[0m"} + ${"\u001B[95m"}-------------------------------------------------${"\u001B[0m"} + """.trimIndent()) + + input = readln() + + val answer = auto.DoYouAccept(input,false) + var m = "" + m = if (answer) { + "la chaine \""+input+"\" \u001B[92m est acceptée\u001B[0m" + } else { + "la chaine \""+input+"\" \u001B[91m n'est pas acceptée\u001B[0m" + } + + ////INPUT ACTION RETOUR MENU (OU NON) + + + println(""" + --------------- Résultat ------------------------ + ${m} + """.trimIndent()) + println(""" + ${"\u001B[95m"}--------------- Question ------------------------${"\u001B[0m"} + ${"\u001B[95m"}Voulez-vous retourner au menu [o/n] ?${"\u001B[0m"} + ${"\u001B[95m"}-------------------------------------------------${"\u001B[0m"} + """.trimIndent()) + + input = readln() + + when(input) { + "O" -> {break} + "o" -> {break} + } + } + } catch (e : Exception) { + println(""" + ${"\u001B[91m"}--------------- Erreur --------------------------${"\u001B[0m"} + ${"\u001B[91m"}"${input}" n'est pas mode disponible, ${"\u001B[0m"} + ${"\u001B[91m"}Veuillez réessayer${"\u001B[0m"} + """.trimIndent()) + } + } + println("\n\u001B[34mAurevoir \uD83D\uDC4B \u001B[0m \n") +} \ No newline at end of file diff --git a/src/main/kotlin/State.kt b/src/main/kotlin/State.kt new file mode 100644 index 0000000..f8b2f29 --- /dev/null +++ b/src/main/kotlin/State.kt @@ -0,0 +1,23 @@ +class State(nom : String) { + private var nom : String + private var transitions: HashMap = hashMapOf() + + public fun getNom() = this.nom + public fun getTransition() = this.transitions + public fun addTransition(c : Char, destination : State) { + transitions.put(c,destination) + } + init { + this.nom = nom + } + + companion object { + public fun createStates(word : String,start : Int,end : Int) : MutableList { + val ls = mutableListOf() + (start..end).toList().forEach{ it -> ( + ls.add(State(word+it)) + )} + return ls + } + } +} \ No newline at end of file diff --git a/src/main/resources/.$auto_exo7.drawio.bkp b/src/main/resources/.$auto_exo7.drawio.bkp new file mode 100644 index 0000000..7e3febf --- /dev/null +++ b/src/main/resources/.$auto_exo7.drawio.bkp @@ -0,0 +1,767 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/auto_exo7-01-57.jpg b/src/main/resources/auto_exo7-01-57.jpg new file mode 100644 index 0000000..b45ddae Binary files /dev/null and b/src/main/resources/auto_exo7-01-57.jpg differ diff --git a/src/main/resources/auto_exo7-Date.jpg b/src/main/resources/auto_exo7-Date.jpg new file mode 100644 index 0000000..d4baf6a Binary files /dev/null and b/src/main/resources/auto_exo7-Date.jpg differ diff --git a/src/main/resources/auto_exo7-Heure.jpg b/src/main/resources/auto_exo7-Heure.jpg new file mode 100644 index 0000000..7ddc743 Binary files /dev/null and b/src/main/resources/auto_exo7-Heure.jpg differ diff --git a/src/main/resources/auto_exo7-structure_delta_exemp.jpg b/src/main/resources/auto_exo7-structure_delta_exemp.jpg new file mode 100644 index 0000000..762e1ea Binary files /dev/null and b/src/main/resources/auto_exo7-structure_delta_exemp.jpg differ diff --git a/src/main/resources/auto_exo7-structure_delta_expli.jpg b/src/main/resources/auto_exo7-structure_delta_expli.jpg new file mode 100644 index 0000000..d5f49a9 Binary files /dev/null and b/src/main/resources/auto_exo7-structure_delta_expli.jpg differ diff --git a/src/main/resources/auto_exo7.drawio b/src/main/resources/auto_exo7.drawio new file mode 100644 index 0000000..d299818 --- /dev/null +++ b/src/main/resources/auto_exo7.drawio @@ -0,0 +1,767 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/kotlin/Automate0157.kt b/src/test/kotlin/Automate0157.kt new file mode 100644 index 0000000..957020c --- /dev/null +++ b/src/test/kotlin/Automate0157.kt @@ -0,0 +1,52 @@ +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class Automate0157 { + val Etats_0157 = State.createStates("A",0,7) + val Auto_0157 = Automate("01-57") + + @BeforeEach + fun initAuto() { + Auto_0157.addDeltaFromString(Etats_0157[0],"0",Etats_0157[1]) + Auto_0157.addDeltaFromString(Etats_0157[1],"1..9",Etats_0157[7]) + Auto_0157.addDeltaFromString(Etats_0157[0],"1..4",Etats_0157[3]) + Auto_0157.addDeltaFromString(Etats_0157[3],"0..9",Etats_0157[7]) + Auto_0157.addDeltaFromString(Etats_0157[0],"5",Etats_0157[5]) + Auto_0157.addDeltaFromString(Etats_0157[5],"0..7",Etats_0157[7]) + + Auto_0157.setStartingState(Etats_0157[0]) + Auto_0157.addFinalState(Etats_0157[7]) + } + @Test + fun AcceptIncorrectSize1() { // too long + assertFalse(Auto_0157.DoYouAccept("111")) + } + @Test + fun AcceptIncorrectSize2() { // too short + assertFalse(Auto_0157.DoYouAccept("1")) + } + + @Test + fun AcceptIncorrectValue1() { // under the possible value + assertFalse(Auto_0157.DoYouAccept("00")) + } + @Test + fun AcceptIncorrectValue2() { // above the last possible value + assertFalse(Auto_0157.DoYouAccept("58")) + } + + + @Test + fun AcceptCorrectValue1() { // something in 01-09 + assertTrue(Auto_0157.DoYouAccept("01")) + } + @Test + fun AcceptCorrectValue2() { // something in 10-49 + assertTrue(Auto_0157.DoYouAccept("42")) + } + @Test + fun AcceptCorrectValue3() { // something in 50-57 + assertTrue(Auto_0157.DoYouAccept("55")) + } +} \ No newline at end of file diff --git a/src/test/kotlin/AutomateBasic.kt b/src/test/kotlin/AutomateBasic.kt new file mode 100644 index 0000000..2ccf7f4 --- /dev/null +++ b/src/test/kotlin/AutomateBasic.kt @@ -0,0 +1,64 @@ +import org.junit.Before +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class AutomateBasic { + + var auto = Automate("test") + val a = State("A") + val b = State("B") + val c = State("C") + + @BeforeEach + fun initauto() //autorize : "00" "1" + { + auto.addDelta(a,'0',b)// a -> 0 b + auto.addDelta(a,'1',c)// a -> 1 c + auto.addDelta(b,'0',c)// b -> 0 c + } + + @Test + fun addDelta() { + val res = hashMapOf(a to hashMapOf('1' to c,'0' to b),b to hashMapOf('0' to c)) + assertEquals(auto.getDeltas(),res) + } + + @Test + fun getAlpha() { + assertEquals(auto.getAlpha(),mutableSetOf('0','1')) + } + + @Test + fun getStates() { + assertEquals(auto.getStates(),mutableSetOf(a,b,c)) + } + + @Test + fun noFinalState() { + auto.setStartingState(a) + assertThrows({auto.DoYouAccept("something")}) + } + + @Test + fun noStartingState() { + auto.addFinalState(c) + assertThrows({auto.DoYouAccept("something")}) + } + + @Test + fun Accepting() { + auto.setStartingState(a) + auto.addFinalState(c) + assertTrue(auto.DoYouAccept("00",true)) + assertTrue(auto.DoYouAccept("1",true)) + } + + @Test + fun NotAccepting() { + auto.setStartingState(a) + auto.addFinalState(c) + assertFalse(auto.DoYouAccept("11",true)) + } +} \ No newline at end of file diff --git a/src/test/kotlin/AutomateDate.kt b/src/test/kotlin/AutomateDate.kt new file mode 100644 index 0000000..4d71ba5 --- /dev/null +++ b/src/test/kotlin/AutomateDate.kt @@ -0,0 +1,116 @@ +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class AutomateDate { + val Etats_Date = State.createStates("D",0,29) + val Auto_Date = Automate("jj/mm/aaaa") + + @BeforeEach + fun initAuto() { + Auto_Date.addDeltaFromString(Etats_Date[0], "0", Etats_Date[1]) + Auto_Date.addDeltaFromString(Etats_Date[0], "1", Etats_Date[2]) + Auto_Date.addDeltaFromString(Etats_Date[0], "2", Etats_Date[3]) + Auto_Date.addDeltaFromString(Etats_Date[1], "1..9", Etats_Date[4]) + Auto_Date.addDeltaFromString(Etats_Date[2], "0..9", Etats_Date[4]) + Auto_Date.addDeltaFromString(Etats_Date[3], "0..8", Etats_Date[4]) + Auto_Date.addDeltaFromString(Etats_Date[4], "/", Etats_Date[5]) + Auto_Date.addDeltaFromString(Etats_Date[5], "0", Etats_Date[6]) + Auto_Date.addDeltaFromString(Etats_Date[5], "1", Etats_Date[7]) + Auto_Date.addDeltaFromString(Etats_Date[3], "9", Etats_Date[8]) + Auto_Date.addDeltaFromString(Etats_Date[8], "/", Etats_Date[9]) + Auto_Date.addDeltaFromString(Etats_Date[9], "0", Etats_Date[10]) + Auto_Date.addDeltaFromString(Etats_Date[9], "1", Etats_Date[11]) + Auto_Date.addDeltaFromString(Etats_Date[12], "0", Etats_Date[13]) + Auto_Date.addDeltaFromString(Etats_Date[13], "/", Etats_Date[14]) + Auto_Date.addDeltaFromString(Etats_Date[14], "0", Etats_Date[15]) + Auto_Date.addDeltaFromString(Etats_Date[14], "1", Etats_Date[16]) + Auto_Date.addDeltaFromString(Etats_Date[12], "1", Etats_Date[17]) + Auto_Date.addDeltaFromString(Etats_Date[17], "1", Etats_Date[18]) + Auto_Date.addDeltaFromString(Etats_Date[18], "0", Etats_Date[19]) + Auto_Date.addDeltaFromString(Etats_Date[18], "1", Etats_Date[20]) + Auto_Date.addDeltaFromString(Etats_Date[6], "1..9", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[7], "0..2", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[10], "1 | 3..9", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[11], "0..2", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[15], "1 | 3..9", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[16], "0..2", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[19], "1 | 3 | 5 | 7 | 8", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[20], "0 | 2", Etats_Date[21]) + Auto_Date.addDeltaFromString(Etats_Date[21], "/", Etats_Date[22]) + Auto_Date.addDeltaFromString(Etats_Date[22], "0", Etats_Date[23]) + Auto_Date.addDeltaFromString(Etats_Date[23], "0", Etats_Date[24]) + Auto_Date.addDeltaFromString(Etats_Date[24], "0", Etats_Date[25]) + Auto_Date.addDeltaFromString(Etats_Date[22], "1..9", Etats_Date[26]) + Auto_Date.addDeltaFromString(Etats_Date[26], "0..9", Etats_Date[27]) + Auto_Date.addDeltaFromString(Etats_Date[27], "0..9", Etats_Date[28]) + Auto_Date.addDeltaFromString(Etats_Date[28], "0..9", Etats_Date[29]) + Auto_Date.addDeltaFromString(Etats_Date[25], "1..9", Etats_Date[29]) + Auto_Date.addDeltaFromString(Etats_Date[23], "1..9", Etats_Date[27]) + Auto_Date.addDeltaFromString(Etats_Date[24], "1..9", Etats_Date[28]) + //set Start and End + Auto_Date.setStartingState(Etats_Date[0]) + Auto_Date.addFinalState(Etats_Date[29]) + } + + @Test + fun AcceptIncorrectSize1() { // one digit missing for the year + assertFalse(Auto_Date.DoYouAccept("01/01/005")) + } + @Test + fun AcceptIncorrectSize2() { // one digit missing for the month + assertFalse(Auto_Date.DoYouAccept("01/1/1000")) + } + @Test + fun AcceptIncorrectSize3() { // one digit missing for the day + assertFalse(Auto_Date.DoYouAccept("1/01/1000")) + } + + + @Test + fun AcceptIncorrectDayMonth1() { // 30 day's month not allowed to have 31 + assertFalse(Auto_Date.DoYouAccept("31/04/9999")) + } + @Test + fun AcceptIncorrectDayMonth2() { // 29th of february not allowed + assertFalse(Auto_Date.DoYouAccept("29/02/9999")) + } + @Test + fun AcceptIncorrectDayMonth3() { // zero day not allowed + assertFalse(Auto_Date.DoYouAccept("00/01/9999")) + } + @Test + fun AcceptIncorrectDayMonth4() { // zero month not allowed + assertFalse(Auto_Date.DoYouAccept("01/00/9999")) + } + @Test + fun AcceptIncorrectYear() { // zero year not allowed + assertFalse(Auto_Date.DoYouAccept("01/01/0000")) + } + + + @Test + fun AcceptCorrectYear1() { // Year of the form ---- + assertTrue(Auto_Date.DoYouAccept("02/09/9999")) + } + @Test + fun AcceptCorrectYear2() { // Year of the form 0--- + assertTrue(Auto_Date.DoYouAccept("01/01/0999")) + } + @Test + fun AcceptCorrectYear3() { // Year of the form -0-- + assertTrue(Auto_Date.DoYouAccept("01/01/9099")) + } + @Test + fun AcceptCorrectYear4() { // Year of the form --0- + assertTrue(Auto_Date.DoYouAccept("01/01/9909")) + } + @Test + fun AcceptCorrectYear5() { // Year of the form ---0 + assertTrue(Auto_Date.DoYouAccept("01/01/9990")) + } + @Test + fun AcceptCorrectDayMonth() { + assertTrue(Auto_Date.DoYouAccept("28/02/9999")) + } +} \ No newline at end of file diff --git a/src/test/kotlin/AutomateHeure.kt b/src/test/kotlin/AutomateHeure.kt new file mode 100644 index 0000000..74330ce --- /dev/null +++ b/src/test/kotlin/AutomateHeure.kt @@ -0,0 +1,58 @@ +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class AutomateHeure { + val Etats_heure = State.createStates("e",0,9) + val Auto_heure = Automate("heure") + + @BeforeEach + fun initAuto() { + Auto_heure.addDeltaFromString(Etats_heure[0],"0 | 1",Etats_heure[1]) + Auto_heure.addDeltaFromString(Etats_heure[0],"2",Etats_heure[2]) + Auto_heure.addDeltaFromString(Etats_heure[1],"0..9",Etats_heure[3]) + Auto_heure.addDeltaFromString(Etats_heure[2],"0..3",Etats_heure[3]) + Auto_heure.addDeltaFromString(Etats_heure[3],":",Etats_heure[4]) + Auto_heure.addDeltaFromString(Etats_heure[4],"0..5",Etats_heure[5]) + Auto_heure.addDeltaFromString(Etats_heure[5],"0..9",Etats_heure[6]) + Auto_heure.addDeltaFromString(Etats_heure[6],":",Etats_heure[7]) + Auto_heure.addDeltaFromString(Etats_heure[7],"0..5",Etats_heure[8]) + Auto_heure.addDeltaFromString(Etats_heure[8],"0..9",Etats_heure[9]) + + Auto_heure.setStartingState(Etats_heure[0]) + Auto_heure.addFinalState(Etats_heure[9]) + } + + @Test + fun AcceptIncorrectSize1() { // one digit missing for the hour + assertFalse(Auto_heure.DoYouAccept("0:01:01")) + } + @Test + fun AcceptIncorrectSize2() { // one digit missing for the day + assertFalse(Auto_heure.DoYouAccept("01:0:01")) + } + @Test + fun AcceptIncorrectSize3() { // one digit missing for the second + assertFalse(Auto_heure.DoYouAccept("01:01:0")) + } + + + @Test + fun AcceptIncorrectValue1() { // too many hour + assertFalse(Auto_heure.DoYouAccept("24:01:01")) + } + @Test + fun AcceptIncorrectValue2() { // too many minute + assertFalse(Auto_heure.DoYouAccept("01:60:01")) + } + @Test + fun AcceptIncorrectValue3() { // too many second + assertFalse(Auto_heure.DoYouAccept("01:01:60")) + } + + + @Test + fun AcceptCorrectValue1() { // too many second + assertTrue(Auto_heure.DoYouAccept("01:01:01")) + } +} \ No newline at end of file