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 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>> {
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
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))
|
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));
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Reference in New Issue