mathhhsss

This commit is contained in:
WanderingPenwing 2024-12-08 00:00:49 +01:00
parent 61288747ae
commit 249fa1f2b2
4 changed files with 127 additions and 31 deletions

View file

@ -11,6 +11,8 @@ enum ErreurSophie {
ManqueArgument(String),
OrthographeNombre(String),
MauvaisArgument(String),
DesequilibreParenthese,
VariableInconnue(String),
}
impl fmt::Display for ErreurSophie {
@ -20,7 +22,9 @@ impl fmt::Display for ErreurSophie {
Self::PhraseVide => write!(f, "La phrase est vide."),
Self::ManqueArgument(commande) => write!(f, "Il manque un argument pour \"{}\".", commande),
Self::OrthographeNombre(nombre) => write!(f, "Le nombre \"{}\" est mal orthographié.", nombre),
Self::MauvaisArgument(message) => write!(f, "La commande a reçu un mauvais argument, {}.", message)
Self::MauvaisArgument(message) => write!(f, "La commande a reçu un mauvais argument, {}.", message),
Self::DesequilibreParenthese => write!(f, "Les parenthèses sont déséquilibrés."),
Self::VariableInconnue(nom) => write!(f, "La variable \"{}\" est inconnue", nom),
}
}
}
@ -123,31 +127,6 @@ impl Sophie {
println!("- demande : {}", arguments);
Ok(())
}
pub fn operation(&self, arguments: &str) -> Result<usize, ErreurSophie> {
let somme_texte: Vec<&str> = arguments.split("plus").collect();
let mut somme : usize = 0;
for somme_element in somme_texte {
let somme_element_propre: &str = somme_element.trim();
let produit_texte: Vec<&str> = somme_element_propre.split("fois").collect();
let mut produit : usize = 1;
for produit_element in produit_texte {
let produit_element_propre: &str = produit_element.trim();
let Some(first_char) = produit_element_propre.chars().next() else {
return Err(ErreurSophie::MauvaisArgument("il y a un argument vide pour l'operation".to_string()))
};
let nombre = if first_char.is_uppercase() {
self.variables[produit_element_propre]
} else {
nombres::texte_comme_nombre(produit_element_propre)?
};
produit *= nombre;
}
somme += produit;
}
Ok(somme)
}
}
fn main() {
@ -172,6 +151,8 @@ fn main() {
}
// -------------------------------------------------------------------------
#[cfg(test)] // Compile and run only during testing
mod tests {
@ -179,7 +160,6 @@ mod tests {
#[test]
fn teste_conversion_nombres_texte() {
// Test on a limited set of numbers to ensure feasibility
for i in [0, 1, 42, 123, 999, 1031, 1_001_091, 72_036_854_775_807usize].iter() {
let texte = nombres::nombre_comme_texte(*i); // Convert number to text
match nombres::texte_comme_nombre(&texte) { // Convert text back to number
@ -231,7 +211,7 @@ mod tests {
let mut sophie = Sophie::new();
let a = 2345678;
let b = 987654;
let phrase = format!("Modifie Variable avec {}", nombres::nombre_comme_texte(a));
let phrase = format!("Modifie Variable avec {} ", nombres::nombre_comme_texte(a));
if let Err(raison) = sophie.execute_phrase(&phrase) {
panic!("Execution échouée pour \"{}\", avec l'erreur : {}", phrase, raison);
}
@ -248,12 +228,23 @@ mod tests {
}
#[test]
fn teste_multiplication() {
fn teste_maths() {
let sophie = Sophie::new();
let resultat = sophie.operation("trois fois deux plus quatre fois sept");
let a = 2345678;
let b = 987654;
let c = 34523456;
let d = 45678;
let e = 2;
let resultat = sophie.operation(&format!("{} fois {} plus ouvre la parenthèse {} moins {} ferme la parenthèse divisé par {}",
nombres::nombre_comme_texte(a),
nombres::nombre_comme_texte(b),
nombres::nombre_comme_texte(c),
nombres::nombre_comme_texte(d),
nombres::nombre_comme_texte(e)
));
match resultat {
Ok(nombre) => {
assert_eq!(nombre, 34, "Echec de la multiplication de 3*2+4*7, got {}", nombre);
assert_eq!(nombre, a*b+(c-d)/e, "Echec de l'opération mathématique, got {}", nombre);
}
Err(raison) => {
panic!("Execution échouée pour multiplication, avec l'erreur : {}", raison);

View file

@ -1,4 +1,5 @@
use super::ErreurSophie;
use super::Sophie;
const NOMS_UNITES: [&str; 10] = ["", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf"];
const NOMS_UNITES_DIX: [&str; 10] = ["dix", "onze", "douze", "treize", "quatorze", "quinze", "seize", "dix-sept", "dix-huit", "dix-neuf"];
@ -6,6 +7,107 @@ const NOMS_DIZAINES: [&str; 9] = ["", "dix", "vingt", "trente", "quarante", "cin
const NOMS_SEPARATEURS: [&str; 7] = ["", "mille", "million", "milliard", "billion", "billiard", "trillion"];
const UNION: &str = "-";
impl Sophie {
pub fn operation(&self, arguments: &str) -> Result<usize, ErreurSophie> {
//return self.operation_elementaire(arguments);
let texte = arguments
.replace("ouvre la parenthèse", "ouvre-la-parenthese")
.replace("ferme la parenthèse", "ferme-la-parenthese")
.replace("divisé par", "divise-par");
let mut expression: Vec<String> = texte.split(" ").map(String::from).collect();
while expression.contains(&"ouvre-la-parenthese".to_string()) {
let mut ouverture: Option<usize> = None;
let mut fermeture: Option<usize> = None;
for index in 0..expression.len() {
if expression[index] == "ouvre-la-parenthese" {
ouverture = Some(index);
}
if expression[index] == "ferme-la-parenthese" && ouverture.is_some() {
fermeture = Some(index);
break;
}
}
let Some(index_ouverture) = ouverture else {
return Err(ErreurSophie::DesequilibreParenthese);
};
let Some(index_fermeture) = fermeture else {
return Err(ErreurSophie::DesequilibreParenthese);
};
let contenu: String = expression[(index_ouverture+1)..(index_fermeture)].join(" ");
let nombre = self.operation_elementaire(&contenu)?;
let nombre_texte = nombre_comme_texte(nombre);
expression[index_ouverture] = nombre_texte;
for _ in 0..(index_fermeture-index_ouverture) {
expression.remove(index_ouverture+1);
}
}
if expression.contains(&"ferme-la-parenthese".to_string()) {
return Err(ErreurSophie::DesequilibreParenthese);
}
self.operation_elementaire(&expression.join(" "))
}
pub fn operation_elementaire(&self, arguments: &str) -> Result<usize, ErreurSophie> {
let texte = arguments.replace("divisé par", "divise-par");
let mut expression: Vec<String> = texte.split(" ").map(String::from).collect();
let mut index = 0;
while index < expression.len() {
if expression[index] != "fois" && expression[index] != "divise-par" {
index += 1;
continue;
}
if index == 0 || index == expression.len() - 1 {
return Err(ErreurSophie::ManqueArgument(expression[index].to_string()));
}
let a = self.texte_comme_nombre(&expression[index - 1])?;
let b = self.texte_comme_nombre(&expression[index + 1])?;
let produit = if expression[index] == "fois" {a*b} else {a/b};
let produit_texte: String = nombre_comme_texte(produit);
index -= 1;
expression[index] = produit_texte;
expression.remove(index + 1);
expression.remove(index + 1);
}
let mut index = 0;
while index < expression.len() {
if expression[index] != "plus" && expression[index] != "moins" {
index += 1;
continue;
}
if index == 0 || index == expression.len() - 1 {
return Err(ErreurSophie::ManqueArgument(expression[index].to_string()));
}
let a = self.texte_comme_nombre(&expression[index - 1])?;
let b = self.texte_comme_nombre(&expression[index + 1])?;
let somme = if expression[index] == "plus" {a+b} else {a-b};
let somme_texte: String = nombre_comme_texte(somme);
index -= 1;
expression[index] = somme_texte;
expression.remove(index + 1);
expression.remove(index + 1);
}
if expression.len() > 1 {
return Err(ErreurSophie::MauvaisArgument("expression mathématique".to_string()))
}
self.texte_comme_nombre(&expression[0])
}
fn texte_comme_nombre(&self, texte: &str) -> Result<usize, ErreurSophie> {
if texte.chars().next().map_or(false, |c| c.is_uppercase()) {
if self.variables.contains_key(texte) {
return Ok(self.variables[texte]);
} else {
return Err(ErreurSophie::VariableInconnue(texte.to_string()))
}
}
texte_comme_nombre(texte)
}
}
pub fn nombre_comme_texte(nombre: usize) -> String {
if nombre == 0 {
return "zéro".to_string()

View file

@ -1 +1,2 @@
Affiche dix plus sept fois sept.
Affiche deux fois ouvre la parenthèse quatre plus seize ferme la parenthèse.

2
todo Normal file
View file

@ -0,0 +1,2 @@
variable types
variable = Variable::Entier(usize)