feat(*): prep 42
This commit is contained in:
parent
0f363e0452
commit
8260e7fc92
29
src/lib.rs
29
src/lib.rs
|
@ -8,14 +8,29 @@ pub mod parser;
|
|||
pub mod maths;
|
||||
|
||||
|
||||
pub fn pretty(v: &Vec<GaussianRational>) {
|
||||
v[0].print();
|
||||
for i in 1..v.len() {
|
||||
print!(" + ");
|
||||
v[i].print();
|
||||
print!("x^{i}");
|
||||
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());
|
||||
}
|
||||
}
|
||||
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>> {
|
||||
|
|
|
@ -16,8 +16,10 @@ fn main() {
|
|||
println!("Error during evaluation: {e}");
|
||||
process::exit(1);
|
||||
});
|
||||
computorv1::pretty(&evaluated);
|
||||
if is_equation {
|
||||
println!("{} = 0", computorv1::format(&evaluated));
|
||||
computorv1::maths::solver::solve(evaluated);
|
||||
} else {
|
||||
println!("{}", computorv1::format(&evaluated));
|
||||
}
|
||||
}
|
||||
|
|
120
src/maths.rs
120
src/maths.rs
|
@ -16,6 +16,33 @@ fn one() -> GaussianRational {
|
|||
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
|
||||
fn gcd(a: i128, b: i128) -> i128 {
|
||||
if b == 0 {
|
||||
|
@ -56,12 +83,40 @@ impl Rational {
|
|||
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
|
||||
pub fn print(&self) {
|
||||
pub fn format(&self) -> String {
|
||||
match (self.numerator, self.denominator) {
|
||||
(_, 1) => print!("{}", self.numerator),
|
||||
_ => print!("{}/{}", self.numerator, self.denominator),
|
||||
};
|
||||
(_, 1) => format!("{}", self.numerator),
|
||||
_ => format!("{}", self.format_fract()),
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
pub fn print(&self) {
|
||||
self.real.print();
|
||||
print!("+");
|
||||
self.imaginary.print();
|
||||
print!("i");
|
||||
pub fn format(&self) -> String {
|
||||
match (self.real().is_zero(), self.imaginary.is_zero()) {
|
||||
(true, true) => format!(""),
|
||||
(true, false) => format!("{}i", self.imaginary.format()),
|
||||
(false, true) => format!("{}", self.real.format()),
|
||||
(false, false) => format!("{} + {}i", self.real.format(), self.imaginary.format())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_real(&self) -> bool {
|
||||
|
@ -272,6 +329,24 @@ impl ops::Div<GaussianRational> for GaussianRational {
|
|||
mod tests {
|
||||
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]
|
||||
fn gcd_test() {
|
||||
assert_eq!(gcd(7, 3), 1);
|
||||
|
@ -343,6 +418,18 @@ mod tests {
|
|||
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]
|
||||
fn getters() {
|
||||
let rational = Rational::new(5, 7);
|
||||
|
@ -399,6 +486,21 @@ mod tests {
|
|||
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]
|
||||
fn getters() {
|
||||
let gaussian_rational = GaussianRational::new(Rational::new(5, 7), Rational::new(8, 3));
|
||||
|
|
|
@ -13,7 +13,11 @@ fn degree_one(equation: Vec<GaussianRational>) {
|
|||
println!("Polynomial degree: 1");
|
||||
let x = minus_one() * equation[0] / equation[1];
|
||||
println!("The solution is");
|
||||
println!("{:?}", x);
|
||||
let mut format = x.format();
|
||||
if format == "" {
|
||||
format = String::from("0");
|
||||
}
|
||||
println!("x = {}", format);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -30,34 +34,13 @@ struct MyCompSqrt {
|
|||
sign: i128,
|
||||
}
|
||||
|
||||
|
||||
fn simplify_sqrt(mut n: i128) -> (i128, i128) {
|
||||
fn simplify_sqrt(n: i128) -> (i128, i128) {
|
||||
if n == 0 {
|
||||
return (0, 0);
|
||||
}
|
||||
let mut prime_factors = vec![];
|
||||
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 prime_factors = get_prime_factors(n);
|
||||
let (mut natural, mut irrational) = (1, 1);
|
||||
prime_factors = prime_factors.into_iter().rev().collect();
|
||||
dbg!(&prime_factors);
|
||||
while prime_factors.len() > 1 {
|
||||
let pop = prime_factors.pop().unwrap();
|
||||
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 {
|
||||
let numerator_irrational = n.numerator * n.denominator;
|
||||
dbg!(numerator_irrational);
|
||||
let (mut numerator_natural, numerator_irrational) = simplify_sqrt(numerator_irrational);
|
||||
dbg!(numerator_natural);
|
||||
dbg!(numerator_irrational);
|
||||
|
||||
numerator_natural *= a.denominator;
|
||||
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> {
|
||||
for i in (1..equation.len()).rev() {
|
||||
if equation[i] == zero() {
|
||||
|
@ -395,7 +374,6 @@ pub fn solve(mut equation: Vec<GaussianRational>) -> Vec<GaussianRational> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
crate::pretty(&equation);
|
||||
match equation.len() {
|
||||
0 => unreachable!(),
|
||||
1 => degree_zero(equation),
|
||||
|
|
Loading…
Reference in New Issue