summaryrefslogtreecommitdiff
path: root/labs/src/lab6.rs
blob: a2d64bcf05a179f40fa80a4342ded16f9a9d4c31 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::lab_trait::Lab;
use eframe::egui;
use std::collections::HashMap;
use std::collections::HashSet;

enum State<'a> {
    Clean,
    Done1,
    Done2,
    Error(&'a str),
}

pub struct Window<'a> {
    n: u32,
    q: u32,
    subgroup: Vec<u32>,
    subgroups: HashMap<u32, Vec<u32>>,
    state: State<'a>,
}

impl<'a> Default for Window<'a> {
    fn default() -> Self {
        Self {
            n: 6,
            q: 3,
            subgroup: Vec::new(),
            subgroups: HashMap::new(),
            state: State::Clean,
        }
    }
}

impl<'a> Lab for Window<'a> {
    fn get_name(&self) -> &str {
        "Задача №6"
    }

    fn update(&mut self, ui: &mut egui::Ui) {
        ui.horizontal(|ui| {
            ui.label("Порядок группы Z_n: ");
            if ui
                .add(egui::DragValue::new(&mut self.n).clamp_range(2..=u32::MAX))
                .changed()
            {
                self.state = State::Clean;
                self.subgroup.clear();
            }
        });
        ui.horizontal(|ui| {
            ui.label("Порядок q подгруппы: ");
            if ui
                .add(egui::DragValue::new(&mut self.q).clamp_range(1..=self.n))
                .changed()
            {
                self.state = State::Clean;
                self.subgroup.clear();
            }
        });
        if ui.button("Вычислить подгруппу").clicked() {
            self.subgroups.clear();
            if self.n % self.q != 0 {
                self.state = State::Error("q не является делителем n");
            } else {
                self.subgroups = calculate_subgroups(self.n);
                for (_, sg) in &self.subgroups {
                    if sg.len() == self.q as usize {
                        self.subgroup = sg.clone();
                        break;
                    }
                }
                self.state = State::Done1;
            }
        }
        if ui.button("Вычислить все подгруппы").clicked() {
            self.subgroups.clear();
            if self.n % self.q != 0 {
                self.state = State::Error("q не является делителем n");
            } else {
                self.subgroups = calculate_subgroups(self.n);
                self.state = State::Done2;
            }
        }
        match self.state {
            State::Clean => {}
            State::Done1 => {
                ui.label(format!("Вычисленная подгруппа: {:?}", self.subgroup));
            }
            State::Done2 => {
                for (gen, set) in self.subgroups.iter() {
                    ui.label(format!("Подгруппа {:?} с генератором {}", set, gen));
                }
            }
            State::Error(msg) => {
                ui.label(msg);
            }
        }
    }
}

fn powmod(x: u32, n: u32, m: u32) -> u32 {
    let mut res = 0;
    for _ in 0..n {
        res = (res + x) % m;
    }
    return res;
}

fn calculate_subgroups(n: u32) -> HashMap<u32, Vec<u32>> {
    let mut subgroups = HashMap::new();
    for i in 0..n {
        let mut group = HashSet::new();
        group.insert(i);
        for p in 2..=n {
            let power = powmod(i, p, n);
            group.insert(power);
        }
        let mut vec = group.drain().collect::<Vec<u32>>();
        vec.sort();
        subgroups.insert(i as u32, vec);
    }
    return subgroups;
}