#include <iostream>
#include <string.h>
#include <locale>
#include <stdlib.h>
#include <math.h>
using namespace std;
// Функция для прямой подстановки
void forward_substitution(double *y, int n, double **L, double *b) {
y[n] = {};
double Sum;
for (int i = 0; i< n; i++) {
Sum = 0;
for (int j = 0; j <= i-1 ;j++) {
Sum+= L[i][j]* y[j];
}
y[i] = (b[i] - Sum);
}
}
// Функция обратной подстановки
void reverse_substitution(double *x, int n, double **U, double *b) {
x[n] = {};
double Sum;
for (int i = n - 1; i >= 0; i--) {
Sum = 0;
for (int j = i + 1; j <= n ;j++) {
Sum+= U[i][j]* x[j];
}
x[i] = (b[i] - Sum) / U[i][i];
}
}
// Функция для ввода/вывода матриц.
void inputOutputMatrix(int n, double **matrix, int mode) {
if(mode < 2) cout << " ----------------" << endl;
for (int i = 0; i < n ; i++) {
for (int j = 0; j < n ; j++) {
if (mode == 0) {
cout << " | Ввод | M[" << i << "][" << j << "] = ";
cin >> matrix[i][j];
} // mode - режим работы: 0 - ввод, 1 - вывод, 2 - заполнение единичной матрицы, 3 - заполнение нулевой.
else if (mode == 1) {
//cout << "M[" << i << "][" << j << "] = " << matrix[i][j] << " ";
cout << matrix[i][j] << " ";
if (j == n - 1) cout << endl;
}
else if (mode>1) {
if ((i == j) and (mode == 2)) {
matrix[i][j] = 1;
}
else {
matrix[i][j] = 0;
}
}
}
}
if (mode < 2) cout << " ----------------" << endl;
}
// Функция для LU - разложения (прямая реализация по алгоритму)
void lu_decomposition(int n,double **L, double **U, double **A) {
double Sum;
int k;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
Sum = 0;
if (i<= j) {
for (k = 0; k <= i-1; k++) {
Sum += L[i][k] * U[k][j];
}
U[i][j] = A[i][j] - Sum ;
}
else if(i> j) {
for (k = 0; k <= j-1; k++) {
Sum += L[i][k] * U[k][j];
}
L[i][j] = (A[i][j] - Sum) / U[j][j];
}
}
}
}
// Функция для решения СЛАУ.
void SLAU(int rows, double **L, double **U, double *x, double *y, double *b ) {
forward_substitution(y,rows, L, b);
reverse_substitution(x,rows, U, y);
}
//Функция для нахождения обратной матрицы.
void reverse_matrix(int rows, double **L, double **U, double *x, double *y, double **reverse) {
for (int i = 0; i < rows; i++) {
double b[rows] = {};
b[i] = 1;
SLAU(rows, L, U, x, y, b );
for (int k = 0; k < rows; k++) {
reverse[k][i] = x[k];
}
}
}
//Функция для умножения матрицы на вектор.
void key_multiplication(int rows, double **key, double *vector, double *response) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < rows; j ++) {
response[i] += key[i][j] * vector[j];
}
}
}
//Функция для шифровки.
void hill_encryption(int rows, int wordSize, int dictSize, char *word, char *dict, double **key, double *response) {
double vector[rows];
int count = 0;
for (int i = 0; i < wordSize; i++) {
for (int k = 0; k < dictSize; k++) {
if (word[i] == dict[k]) {
vector[count] = k+1;
count+=1;
}
if (count == 3) {
count = 0;
key_multiplication(rows, key, vector, response);
for (int i = 0; i < rows; i ++) {
cout << response[i] << " ";
response[i] = 0;
}
double vector[rows];
}
}
}
}
//Функция для разшифровки.
void hill_decryption(int rows, double **L, double **U, double *x, double *y, char *dict) {
int length;
cout << " Введите длину: " << endl;
cin >> length;
char word[length];
double vector[rows];
cout << " Введите зашифрованное сообщение: " << endl;
int count = 0;
int all_count = 0;
for (int i = 0; i < length; i++) {
cin >> vector[count];
count+=1;
if (count == 3) {
cout << "ok";
count = 0;
SLAU(rows, L, U, x, y, vector);
int index;
for (int k = 0; k < rows; k++) {
index = x[k];
word[all_count] = dict[index-1];
all_count += 1;
}
cout << endl;
}
}
for (int i = 0; i < length; i++) {
cout << word[i];
}
}
int main(int argc, char** argv) {
setlocale( LC_ALL,"Russian" );
int rows = 3, cols = 3;
char rus_letters[]{"абвгдеёжзийклмнопрстуфхцчшщъыьэюя ?.,"}; // Русский алфавит
char word[]{"игорькабв"}; // Послед-ть символов для шифровки
// Инициализация матриц.
double **matrixA = new double *[rows]; // Матрица A.
double **matrixL = new double *[rows]; // Матрица L.
double **matrixU = new double *[rows]; // Матрица U.
double **key = new double *[rows]; // Матрица-ключ.
double **reverse = new double *[rows]; // Обратная матрица.
double matrixb[rows];
double y[rows];
double x[rows];
double c[rows];
double response[rows];
for(int i = 0; i < rows; i++) {
matrixA[i] = new double[cols];
matrixL[i] = new double[cols];
matrixU[i] = new double[cols];
reverse[i] = new double[cols];
key[i] = new double[cols];
}
// Ввод матриц A, L, U
inputOutputMatrix(rows, matrixL, 2); // Создание единичной матрицы L
inputOutputMatrix(rows, matrixU, 3); // Создание нулевой матрицы U
cout << endl << " Введите ключ-матрицу: " << endl;
inputOutputMatrix(rows, key, 0);
int mode;
cout << endl << " Введите что необходимо сделать:" << endl << " 1.Зашифровать" << endl << " 2.Разшифровать " << endl;
cin >> mode;
if (mode == 1) {
cout << " Результат:" << endl;
cout << " ";
hill_encryption(rows, sizeof(word) - 1, sizeof(rus_letters) - 1, word, rus_letters, key, response);
}
if (mode == 2) {
lu_decomposition(rows, matrixL, matrixU, key);
hill_decryption(rows, matrixL, matrixU, x, y, rus_letters);
}
return 0;
}