summaryrefslogtreecommitdiff
path: root/labs/src/lab3.rs
diff options
context:
space:
mode:
Diffstat (limited to 'labs/src/lab3.rs')
-rw-r--r--labs/src/lab3.rs128
1 files changed, 128 insertions, 0 deletions
diff --git a/labs/src/lab3.rs b/labs/src/lab3.rs
new file mode 100644
index 0000000..7f8edf5
--- /dev/null
+++ b/labs/src/lab3.rs
@@ -0,0 +1,128 @@
+use crate::lab_trait::Lab;
+use eframe::egui;
+use rug::{Complete, Integer};
+
+enum State {
+ Clean,
+ Done,
+ Error,
+}
+
+pub struct Window {
+ str_num: String,
+ factors: Vec<Integer>,
+ state: State,
+}
+
+impl Default for Window {
+ fn default() -> Self {
+ Self {
+ str_num: String::from("21894583143407671"),
+ factors: Vec::new(),
+ state: State::Clean,
+ }
+ }
+}
+
+impl Lab for Window {
+ fn get_name(&self) -> &str { "Задача №3" }
+
+ fn update(&mut self, ui: &mut egui::Ui) {
+ ui.horizontal(|ui| {
+ ui.label("Число: ");
+ let field = ui.add(egui::TextEdit::singleline(&mut self.str_num));
+ if field.changed() {
+ self.state = State::Clean;
+ self.factors.clear();
+ }
+ });
+ if ui.button("Разложить на множители").clicked() {
+ self.factors.clear();
+ match Integer::parse(&self.str_num) {
+ Ok(number) => {
+ self.factors.append(&mut factorize(&number.complete()));
+ self.state = State::Done;
+ },
+ Err(_) => self.state = State::Error,
+ };
+ }
+ if let State::Done = self.state {
+ if self.factors.len() == 1 {
+ ui.label(format!("Число является простым"));
+ }
+ else {
+ ui.label(format!("Множители: {:?}", self.factors));
+ }
+ }
+ if let State::Error = self.state {
+ ui.label("В числе имеются недопустимые символы");
+ }
+ }
+}
+
+fn factorize(n: &Integer) -> Vec<Integer> {
+ let mut factors = Vec::new();
+ let mut front = vec![n.clone()];
+
+ while !front.is_empty() {
+ let num = front.pop().unwrap();
+ match lehman(&num) {
+ Some(factor) => {
+ let other = num.div_exact_ref(&factor).complete();
+ front.push(factor);
+ front.push(other);
+ },
+ None => factors.push(num)
+ };
+ }
+
+ return factors;
+}
+
+fn lehman(n: &Integer) -> Option<Integer> {
+ let one = &Integer::from(1u32);
+ let mut a = Integer::from(2u32);
+ let root3 = n.root_ref(3).complete();
+
+ while a <= root3 {
+ let (_, r) = n.div_rem_ref(&a).complete();
+ if r == 0 {
+ return Some(a);
+ }
+ a += one;
+ }
+
+ let root6 = n.root_ref(6).complete();
+ let mut k = Integer::from(1u32);
+ while k <= root3 {
+ let mut d = Integer::ZERO;
+ let sqrtk4 = k.sqrt_ref().complete() * 4;
+ let (r6sk4, _) = root6.div_rem_ref(&sqrtk4).complete();
+ while d <= (&r6sk4 + one).complete() {
+ let kn4: Integer = k.clone() * n.clone() * 4;
+ let sqrt_kn4 = kn4.sqrt_ref().complete();
+
+ let number = (sqrt_kn4.clone() + d.clone()).square() - kn4.clone();
+ if number.is_perfect_square() {
+ let big_a = sqrt_kn4 + d.clone();
+ let big_b = (big_a.square_ref() - kn4).sqrt();
+
+ let gcd1 = (big_a.clone() + big_b.clone()).gcd_ref(n).complete();
+ let gcd2 = (big_a.clone() - big_b.clone()).gcd_ref(n).complete();
+
+ if &gcd1 > one && &gcd1 < n {
+ return Some(gcd1);
+ }
+ else if &gcd2 > one && &gcd2 < n {
+ return Some(gcd2);
+ }
+ }
+
+ d += one;
+ }
+ k += one;
+ }
+
+ return None;
+}
+