use crate::utils::{find_key_for_value, text_preprocessor};
use crate::Solve;
use modinverse::modinverse;
use std::collections::HashMap;
pub struct AffineCiphertext {
ciphertext: String,
a: i32,
b: i32,
}
impl Solve for AffineCiphertext {
fn solve(&self) -> String {
decrypt(self.a, self.b, &self.ciphertext)
}
}
impl ToString for AffineCiphertext {
fn to_string(&self) -> String {
self.ciphertext.to_string()
}
}
pub fn encrypt(a: i32, b: i32, plaintext: &str) -> AffineCiphertext {
let plaintext = text_preprocessor(plaintext);
let mut alphabet: HashMap<char, i32> = HashMap::new();
let alph = "abcdefghijklmnopqrstuvwxyz ";
for (index, c) in alph.chars().enumerate() {
alphabet.insert(c, index.try_into().unwrap());
}
let text_values: Vec<i32> = plaintext
.chars()
.map(|pc| *(alphabet.get(&pc).unwrap()))
.collect();
for i in 0..plaintext.len() {
let _math: i32 = (a * i as i32 + b) % plaintext.len() as i32;
}
let text_values: Vec<i32> = text_values
.iter()
.map(|value| (a * value + b) % 26)
.collect();
let new_value: Vec<char> = text_values
.iter()
.map(|val| find_key_for_value(&alphabet, *val))
.collect();
let ciphertext = new_value.into_iter().collect::<String>().to_uppercase();
AffineCiphertext { ciphertext, a, b }
}
pub fn decrypt(a: i32, b: i32, ciphertext: &str) -> String {
let ciphertext = text_preprocessor(ciphertext);
let a_modinverse = modinverse(a, 26).unwrap();
let mut alphabet: HashMap<char, i32> = HashMap::new();
let alph = "abcdefghijklmnopqrstuvwxyz";
let mut index = 0;
for c in alph.chars() {
alphabet.insert(c, index);
index += 1;
}
let text_values: Vec<i32> = ciphertext
.chars()
.map(|pc| *(alphabet.get(&pc).unwrap()))
.collect();
let text_values: Vec<i32> = text_values
.iter()
.map(|value| ((a_modinverse * (value - b) % 26 + 26) % 26))
.collect();
let new_value: Vec<char> = text_values
.iter()
.map(|val| find_key_for_value(&alphabet, *val))
.collect();
new_value.into_iter().collect::<String>().to_uppercase()
}