feat(*): prep 42

This commit is contained in:
gbrochar 2023-11-22 19:33:45 +01:00
parent 0f363e0452
commit 8260e7fc92
4 changed files with 143 additions and 46 deletions

View File

@ -8,14 +8,29 @@ pub mod parser;
pub mod maths; pub mod maths;
pub fn pretty(v: &Vec<GaussianRational>) { pub fn format(v: &Vec<GaussianRational>) -> String {
v[0].print(); let mut format;
for i in 1..v.len() { format = v[0].format();
print!(" + "); if v.len() > 1 {
v[i].print(); if format == "" {
print!("x^{i}"); format = format!("{}x", v[1].format());
} else {
format = format!("{format} + {}x", v[1].format());
} }
println!(""); }
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>> { pub fn parse(query: &str) -> Result<Node, Box<dyn Error>> {

View File

@ -16,8 +16,10 @@ fn main() {
println!("Error during evaluation: {e}"); println!("Error during evaluation: {e}");
process::exit(1); process::exit(1);
}); });
computorv1::pretty(&evaluated);
if is_equation { if is_equation {
println!("{} = 0", computorv1::format(&evaluated));
computorv1::maths::solver::solve(evaluated); computorv1::maths::solver::solve(evaluated);
} else {
println!("{}", computorv1::format(&evaluated));
} }
} }

View File

@ -16,6 +16,33 @@ fn one() -> GaussianRational {
GaussianRational::new(Rational::new(1, 1), Rational::new(0, 1)) GaussianRational::new(Rational::new(1, 1), Rational::new(0, 1))
} }
fn get_prime_factors(mut n: i128) -> Vec<i128> {
if n == 0 {
return [0].to_vec();
}
let mut prime_factors = vec![];
let mut prime = 3;
while n != 1 && prime * prime < n + 8 {
if n % (prime - 1) == 0 {
prime_factors.push(prime - 1);
n /= prime - 1;
} else if n % (prime + 1) == 0 {
prime_factors.push(prime + 1);
n /= prime + 1;
} else {
if prime > 5 {
prime += 6;
} else {
prime += 1;
}
}
}
if n != 1 {
prime_factors.push(n);
}
prime_factors
}
//TODO slow ? check Stein's algorithm (binaryGCD) + tests //TODO slow ? check Stein's algorithm (binaryGCD) + tests
fn gcd(a: i128, b: i128) -> i128 { fn gcd(a: i128, b: i128) -> i128 {
if b == 0 { if b == 0 {
@ -56,12 +83,40 @@ impl Rational {
Rational::new(self.numerator, self.denominator * 10) Rational::new(self.numerator, self.denominator * 10)
} }
fn format_fract(&self) -> String {
let mut copy = self.clone();
let factors = get_prime_factors(self.denominator);
dbg!(&factors);
let mut two_count = 0;
let mut five_count = 0;
for factor in factors {
if factor == 2 {
two_count += 1;
} else if factor == 5 {
five_count += 1;
} else {
return format!("{}/{}", self.numerator, self.denominator);
}
}
while two_count < five_count {
copy.numerator *= 2;
copy.denominator *= 2;
two_count += 1;
}
while five_count < two_count {
copy.numerator *= 5;
copy.denominator *= 5;
five_count += 1;
}
format!("{}.{}", copy.numerator / copy.denominator, copy.numerator % copy.denominator)
}
// TODO return string // TODO return string
pub fn print(&self) { pub fn format(&self) -> String {
match (self.numerator, self.denominator) { match (self.numerator, self.denominator) {
(_, 1) => print!("{}", self.numerator), (_, 1) => format!("{}", self.numerator),
_ => print!("{}/{}", self.numerator, self.denominator), _ => format!("{}", self.format_fract()),
}; }
} }
// TODO rename or move to better scope, only used in complex div ? // TODO rename or move to better scope, only used in complex div ?
@ -199,11 +254,13 @@ impl GaussianRational {
} }
// TODO return string, avoid printing real or imag part if zero // TODO return string, avoid printing real or imag part if zero
pub fn print(&self) { pub fn format(&self) -> String {
self.real.print(); match (self.real().is_zero(), self.imaginary.is_zero()) {
print!("+"); (true, true) => format!(""),
self.imaginary.print(); (true, false) => format!("{}i", self.imaginary.format()),
print!("i"); (false, true) => format!("{}", self.real.format()),
(false, false) => format!("{} + {}i", self.real.format(), self.imaginary.format())
}
} }
pub fn is_real(&self) -> bool { pub fn is_real(&self) -> bool {
@ -272,6 +329,24 @@ impl ops::Div<GaussianRational> for GaussianRational {
mod tests { mod tests {
use super::*; use super::*;
#[test]
fn constant_generators() {
assert_eq!(zero(), GaussianRational::new(Rational::new(0, 1), Rational::new(0, 1)));
assert_eq!(minus_one(), GaussianRational::new(Rational::new(-1, 1), Rational::new(0, 1)));
assert_eq!(one(), GaussianRational::new(Rational::new(1, 1), Rational::new(0, 1)));
}
#[test]
fn get_prime_factors_test() {
assert_eq!(get_prime_factors(5), vec![5]);
assert_eq!(get_prime_factors(8), vec![2, 2, 2]);
assert_eq!(get_prime_factors(4), vec![2, 2]);
assert_eq!(get_prime_factors(9), vec![3, 3]);
assert_eq!(get_prime_factors(10), vec![2, 5]);
assert_eq!(get_prime_factors(18), vec![2, 3, 3]);
assert_eq!(get_prime_factors(16), vec![2, 2, 2, 2]);
}
#[test] #[test]
fn gcd_test() { fn gcd_test() {
assert_eq!(gcd(7, 3), 1); assert_eq!(gcd(7, 3), 1);
@ -343,6 +418,18 @@ mod tests {
assert_eq!(rational.is_zero(), false); assert_eq!(rational.is_zero(), false);
} }
#[test]
fn format() {
let whole = Rational::new(5, 1);
let rational = Rational::new(5, 3);
let floating = Rational::new(5, 4);
assert_eq!(whole.format(), String::from("5"));
assert_eq!(rational.format(), String::from("5/3"));
assert_eq!(floating.format(), String::from("1.25"));
let floating = Rational::new(37, 25);
assert_eq!(floating.format(), String::from("1.48"));
}
#[test] #[test]
fn getters() { fn getters() {
let rational = Rational::new(5, 7); let rational = Rational::new(5, 7);
@ -399,6 +486,21 @@ mod tests {
assert_eq!(gaussian_rational.is_real(), true); assert_eq!(gaussian_rational.is_real(), true);
} }
#[test]
fn format() {
let whole = Rational::new(5, 1);
let rational = Rational::new(5, 3);
let zero = Rational::new(0, 1);
let a = GaussianRational::new(zero, zero);
let b = GaussianRational::new(zero, rational);
let c = GaussianRational::new(whole, zero);
let d = GaussianRational::new(whole, rational);
assert_eq!(a.format(), String::from(""));
assert_eq!(b.format(), String::from("5/3i"));
assert_eq!(c.format(), String::from("5"));
assert_eq!(d.format(), String::from("5 + 5/3i"));
}
#[test] #[test]
fn getters() { fn getters() {
let gaussian_rational = GaussianRational::new(Rational::new(5, 7), Rational::new(8, 3)); let gaussian_rational = GaussianRational::new(Rational::new(5, 7), Rational::new(8, 3));

View File

@ -13,7 +13,11 @@ fn degree_one(equation: Vec<GaussianRational>) {
println!("Polynomial degree: 1"); println!("Polynomial degree: 1");
let x = minus_one() * equation[0] / equation[1]; let x = minus_one() * equation[0] / equation[1];
println!("The solution is"); println!("The solution is");
println!("{:?}", x); let mut format = x.format();
if format == "" {
format = String::from("0");
}
println!("x = {}", format);
} }
#[derive(Debug)] #[derive(Debug)]
@ -30,34 +34,13 @@ struct MyCompSqrt {
sign: i128, sign: i128,
} }
fn simplify_sqrt(n: i128) -> (i128, i128) {
fn simplify_sqrt(mut n: i128) -> (i128, i128) {
if n == 0 { if n == 0 {
return (0, 0); return (0, 0);
} }
let mut prime_factors = vec![]; let mut prime_factors = get_prime_factors(n);
let mut prime = 3;
while n != 1 && prime * prime < n {
if n % (prime - 1) == 0 {
prime_factors.push(prime - 1);
n /= prime - 1;
} else if n % (prime + 1) == 0 {
prime_factors.push(prime + 1);
n /= prime + 1;
} else {
if prime > 5 {
prime += 6;
} else {
prime += 1;
}
}
}
if n != 1 {
prime_factors.push(n);
}
let (mut natural, mut irrational) = (1, 1); let (mut natural, mut irrational) = (1, 1);
prime_factors = prime_factors.into_iter().rev().collect(); prime_factors = prime_factors.into_iter().rev().collect();
dbg!(&prime_factors);
while prime_factors.len() > 1 { while prime_factors.len() > 1 {
let pop = prime_factors.pop().unwrap(); let pop = prime_factors.pop().unwrap();
if *prime_factors.last().unwrap() == pop { if *prime_factors.last().unwrap() == pop {
@ -265,10 +248,7 @@ fn degree_two_complex(a: GaussianRational, b: GaussianRational, c: GaussianRatio
fn sqrt(n: Rational, a: Rational) -> MySqrt { fn sqrt(n: Rational, a: Rational) -> MySqrt {
let numerator_irrational = n.numerator * n.denominator; let numerator_irrational = n.numerator * n.denominator;
dbg!(numerator_irrational);
let (mut numerator_natural, numerator_irrational) = simplify_sqrt(numerator_irrational); let (mut numerator_natural, numerator_irrational) = simplify_sqrt(numerator_irrational);
dbg!(numerator_natural);
dbg!(numerator_irrational);
numerator_natural *= a.denominator; numerator_natural *= a.denominator;
let mut denominator = n.denominator * 2 * a.numerator; let mut denominator = n.denominator * 2 * a.numerator;
@ -386,7 +366,6 @@ fn degree_two(equation: Vec<GaussianRational>) {
} }
} }
pub fn solve(mut equation: Vec<GaussianRational>) -> Vec<GaussianRational> { pub fn solve(mut equation: Vec<GaussianRational>) -> Vec<GaussianRational> {
for i in (1..equation.len()).rev() { for i in (1..equation.len()).rev() {
if equation[i] == zero() { if equation[i] == zero() {
@ -395,7 +374,6 @@ pub fn solve(mut equation: Vec<GaussianRational>) -> Vec<GaussianRational> {
break; break;
} }
} }
crate::pretty(&equation);
match equation.len() { match equation.len() {
0 => unreachable!(), 0 => unreachable!(),
1 => degree_zero(equation), 1 => degree_zero(equation),