diff --git a/zad3/Cargo.lock b/zad3/Cargo.lock new file mode 100644 index 0000000..d4fae45 --- /dev/null +++ b/zad3/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "zad3" +version = "0.1.0" diff --git a/zad3/Cargo.toml b/zad3/Cargo.toml new file mode 100644 index 0000000..c565456 --- /dev/null +++ b/zad3/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "zad3" +version = "0.1.0" +edition = "2021" diff --git a/zad3/src/main.rs b/zad3/src/main.rs new file mode 100644 index 0000000..522c727 --- /dev/null +++ b/zad3/src/main.rs @@ -0,0 +1,37 @@ +mod module; + +use std::{env, process::exit}; + +use crate::module::{Module, ModuleIter, ModuleRec}; + +fn main() { + let args = env::args().collect::>(); + if args.len() != 2 { + eprintln!("usage: {} " /* "*/, args[0]); + exit(1); + } + + let r#impl = &args[1]; + // let a = args[2].parse::().expect("failed to parse a"); + // let b = args[3].parse::().expect("failed to parse b"); + // let c = args[4].parse::().expect("failed to parse c"); + + let module: Box = + if r#impl == "iter" { + Box::new(ModuleIter {}) + } else if r#impl == "rec" { + Box::new(ModuleRec {}) + } else { + eprintln!("unknown module type"); + exit(1); + }; + + println!("gcd(a, b): {}", module.gcd(10, 5)); + println!("factorial(a): {}", module.factorial(5)); + let r = module.diophantine(1027, 712, 1); + if r.is_none() { + println!("dupa"); + } else { + println!("diophantine(a, b, c): {}, {}", r.unwrap().0, r.unwrap().1); + } +} diff --git a/zad3/src/module.rs b/zad3/src/module.rs new file mode 100644 index 0000000..6e83c7a --- /dev/null +++ b/zad3/src/module.rs @@ -0,0 +1,150 @@ +pub trait Module { + fn factorial(&self, n: u64) -> u64; + + fn gcd(&self, a: u64, b: u64) -> u64; + + fn diophantine(&self, a: i64, b: i64, c: i64) -> Option<(i64, i64)>; +} + +pub struct ModuleIter {} + +impl ModuleIter { + fn extended_gcd(&self, a: i64, b: i64, x: &mut i64, y: &mut i64) -> i64 { + *x = 1; + *y = 0; + let mut x1 = 0i64; + let mut y1 = 1i64; + let mut q: i64; + let mut temp_x: i64; + let mut temp_y: i64; + let mut temp_b: i64; + let mut _a = a; + let mut _b = b; + + while _b != 0 { + q = _a / _b; + + temp_x = *x - q * x1; + temp_y = *y - q * y1; + *x = x1; + *y = y1; + x1 = temp_x; + y1 = temp_y; + + temp_b = _a - q * _b; + _a = _b; + _b = temp_b; + } + + _a + } +} + +impl Module for ModuleIter { + fn factorial(&self, n: u64) -> u64 { + let mut result = 1u64; + + for i in 1..=n { + result *= i; + } + + result + } + + fn gcd(&self, a: u64, b: u64) -> u64 { + if a == 0 { + return b; + } + + let mut _a = a; + let mut _b = b; + + let mut r: u64; + + while _b > 0 { + r = _a % _b; + + _a = _b; + _b = r; + } + + _a + } + + fn diophantine(&self, a: i64, b: i64, c: i64) -> Option<(i64, i64)> { + if a == 0 && b == 0 { + return None; + } + let mut x0 = 0i64; + let mut y0 = 0i64; + let g = self.extended_gcd(a.abs(), b.abs(), &mut x0, &mut y0); + + if c % g != 0 { + return None; + } + + x0 *= c / g; + y0 *= c / g; + if a < 0 { x0 = -x0; } + if b < 0 { y0 = -y0; } + + Some((x0, y0)) + } +} + +pub struct ModuleRec {} + +impl ModuleRec { + fn extended_gcd(&self, a: i64, b: i64, x: &mut i64, y: &mut i64) -> i64 { + if b == 0 { + *x = 1; + *y = 0; + return a; + } + let mut x1 = 0i64; + let mut y1 = 0i64; + let d = self.extended_gcd(b, a % b, &mut x1, &mut y1); + *x = y1; + *y = x1 - y1 * (a / b); + + d + } +} + +impl Module for ModuleRec { + fn factorial(&self, n: u64) -> u64 { + if n == 0 || n == 1 { + return 1; + } + + n * self.factorial(n - 1) + } + + fn gcd(&self, a: u64, b: u64) -> u64 { + if b == 0 { + return a; + } + + self.gcd(b, a % b) + } + + fn diophantine(&self, a: i64, b: i64, c: i64) -> Option<(i64, i64)> { + if a == 0 && b == 0 { + return None; + } + let mut x0 = 0i64; + let mut y0 = 0i64; + let g = self.extended_gcd(a.abs(), b.abs(), &mut x0, &mut y0); + + if c % g != 0 { + return None; + } + + x0 *= c / g; + y0 *= c / g; + if a < 0 { x0 = -x0; } + if b < 0 { y0 = -y0; } + + Some((x0, y0)) + } +}