computorv1/src/lib.rs

124 lines
3.4 KiB
Rust

use std::error::Error;
use crate::parser::tokenizer::tokenize;
use crate::parser::sanitizer::sanitize_tokens;
use crate::parser::ast_builder::{build_ast, Node};
use crate::maths::GaussianRational;
pub mod parser;
pub mod maths;
pub fn format(v: &Vec<GaussianRational>) -> String {
let mut format;
format = v[0].format();
if v.len() > 1 {
if format == "" {
format = format!("{}x", v[1].format());
} else {
format = format!("{format} + {}x", v[1].format());
}
}
for i in 2..v.len() {
let tmp = v[i].format();
if tmp != "" {
if format == ""{
format = format!("{tmp}x^{i}");
} else {
format = format!("{format} + {}x^{i}", tmp);
}
}
}
format = format.split("+ -").collect::<Vec<_>>().join("- ");
format = format.split("1x").collect::<Vec<_>>().join("x");
format.split("1i").collect::<Vec<_>>().join("i")
}
pub fn parse(query: &str) -> Result<Node, Box<dyn Error>> {
let tokens = tokenize(query)?;
let sanitized_tokens = sanitize_tokens(tokens)?;
let ast = build_ast(sanitized_tokens);
Ok(ast)
}
fn print_reduced_form(equation: &Vec<f64>) {
let mut string = String::from("Reduced form: ");
for (i, n) in equation.iter().enumerate() {
let mut n = *n;
if n < 0. {
string += " - ";
n *= -1.;
} else if i != 0 {
string += " + ";
}
string.push_str(&n.to_string());
string.push_str(" * X^");
string.push_str(&i.to_string());
}
string += " = 0";
println!("{string}");
}
fn sqrt(n: f64) -> f64 {
let mut z = 1.;
for _ in 0..10 {
z -= (z * z - n) / (2. * z);
}
z
}
fn solve_degree_0(equation: Vec<f64>) {
if equation[0] == 0. {
println!("Each real number is a solution.");
} else {
println!("There are no solutions to this equation");
}
}
fn solve_degree_1(equation: Vec<f64>) {
println!("The solution is:");
println!("{}", -1. * equation[0] / equation[1]);
}
fn solve_degree_2(equation: Vec<f64>) {
let delta = equation[1] * equation[1] - 4. * equation[2] * equation[0];
if delta > 0. {
let sqrt_delta = sqrt(delta);
let x1 = (-equation[1] - sqrt_delta) / (2. * equation[2]);
let x2 = (-equation[1] + sqrt_delta) / (2. * equation[2]);
println!("Discriminant is strictly positive, the two solutions are:");
println!("{x1}");
println!("{x2}");
} else if delta < 0. {
let sqrt_delta = sqrt(delta);
let a = -equation[1] / (2. * equation[2]);
let b = sqrt_delta / (2. * equation[2]);
println!("Discriminant is strictly negative, the two complex solutions are:");
println!("{a} + {b}i");
println!("{a} - {b}i");
} else {
let x = -equation[1] / (2. * equation[2]);
println!("Discriminant is zero, the solution is:");
println!("{x}");
}
}
pub fn solve(equation: Vec<f64>) {
let degree = equation.len() - 1;
print_reduced_form(&equation);
println!("Polynomial degree: {degree}");
match degree {
0 => solve_degree_0(equation),
1 => solve_degree_1(equation),
2 => solve_degree_2(equation),
_ if degree > 2 => println!("The polynomial degree is strictly greater than 2, I can't solve."),
_ => unreachable!(),
}
}