Загрузка данных


using System;
using System.Collections.Generic;
using System.Text;

class Program
{
    static void Main()
    {
        Console.OutputEncoding = Encoding.UTF8;

        while (true)
        {
            Console.Clear();
            Console.WriteLine("=== ЛАБОРАТОРНАЯ РАБОТА №1. ШИФР ПРОСТОЙ ЗАМЕНЫ ===");
            Console.WriteLine("1. Простой сдвиг (Классический шифр Цезаря)");
            Console.WriteLine("2. Шифрование с помощью пароля (Алфавитная перестановка)");
            Console.WriteLine("3. Завершить работу");
            Console.Write("\nВыберите действие (1-3): ");

            string choice = Console.ReadLine();

            if (choice == "3") break;

            switch (choice)
            {
                case "1":
                    ModeClassicCaesar();
                    break;
                case "2":
                    ModeKeywordCaesar();
                    break;
                default:
                    ShowError("Неверный выбор меню. Нажмите любую клавишу...");
                    continue;
            }

            Console.WriteLine("\n--------------------------------------------------");
            Console.Write("Желаете продолжить работу? (1 - Да, 0 - Нет): ");
            string cont = Console.ReadLine();
            if (cont != "1") break;
        }
    }

    // Способ 1: Классический сдвиг Цезаря
    static void ModeClassicCaesar()
    {
        Console.WriteLine("\n--- Режим 1: Классический сдвиг ---");
        string alphabet = GetAlphabetChoice();
        if (alphabet == null) return;

        string text = GetInputText("Введите текст для шифрования: ", alphabet);
        int shift = GetValidInt($"Введите величину сдвига (1-{alphabet.Length - 1}): ", 1, alphabet.Length - 1);

        string encrypted = EncryptClassic(text, alphabet, shift);
        string decrypted = EncryptClassic(encrypted, alphabet, alphabet.Length - shift);

        Console.WriteLine($"\nЗашифрованный текст: {encrypted}");
        Console.WriteLine($"Расшифрованный текст: {decrypted}");
    }

    // Способ 2: Шифр с использованием парольного слова
    static void ModeKeywordCaesar()
    {
        Console.WriteLine("\n--- Режим 2: Шифрование по паролю ---");
        string alphabet = GetAlphabetChoice();
        if (alphabet == null) return;

        string text = GetInputText("Введите текст для шифрования: ", alphabet);
        string keyword = GetValidKeyword("Введите пароль (буквы выбранного алфавита без повторов): ", alphabet);
        int keyPos = GetValidInt($"Введите позицию начала пароля (0-{alphabet.Length - 1}): ", 0, alphabet.Length - 1);

        string cipherAlphabet = BuildKeywordAlphabet(alphabet, keyword, keyPos);
        
        Console.WriteLine($"\nИсходный алфавит:  {alphabet}");
        Console.WriteLine($"Шифроалфавит:      {cipherAlphabet}");

        string encrypted = SubstituteText(text, alphabet, cipherAlphabet);
        string decrypted = SubstituteText(encrypted, cipherAlphabet, alphabet);

        Console.WriteLine($"\nЗашифрованный текст: {encrypted}");
        Console.WriteLine($"Расшифрованный текст: {decrypted}");
    }

    // Определение алфавита (Русский / Английский)
    static string GetAlphabetChoice()
    {
        Console.WriteLine("Выберите алфавит:");
        Console.WriteLine("1. Русский (А-Я, 32 буквы без 'Ё')");
        Console.WriteLine("2. Английский (A-Z, 26 букв)");
        Console.Write("Ваш выбор: ");
        string type = Console.ReadLine();

        if (type == "1") return "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
        if (type == "2") return "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        ShowError("Некорректный выбор алфавита.");
        return null;
    }

    // Шифрование классическим сдвигом
    static string EncryptClassic(string input, string alphabet, int shift)
    {
        StringBuilder sb = new StringBuilder();
        int n = alphabet.Length;

        foreach (char c in input)
        {
            char upperC = char.ToUpper(c);
            int idx = alphabet.IndexOf(upperC);

if (idx != -1)
            {
                int newIdx = (idx + shift) % n;
                char newChar = alphabet[newIdx];
                sb.Append(char.IsLower(c) ? char.ToLower(newChar) : newChar);
            }
            else
            {
                sb.Append(c);
            }
        }
        return sb.ToString();
    }

    // Построение подстановочного алфавита по паролю
    static string BuildKeywordAlphabet(string alphabet, string keyword, int startPos)
    {
        char[] cipher = new char[alphabet.Length];
        keyword = keyword.ToUpper();

        // 1. Извлекаем оставшиеся буквы из стандартного алфавита
        List<char> remaining = new List<char>();
        foreach (char c in alphabet)
        {
            if (!keyword.Contains(c.ToString()))
                remaining.Add(c);
        }

        // 2. Объединяем пароль и оставшиеся буквы
        List<char> combined = new List<char>();
        foreach (char c in keyword) combined.Add(c);
        combined.AddRange(remaining);

        // 3. Заполняем массив циклически, начиная со startPos
        int n = alphabet.Length;
        for (int i = 0; i < n; i++)
        {
            cipher[(startPos + i) % n] = combined[i];
        }

        return new string(cipher);
    }

    // Замена символов по шифроалфавиту
    static string SubstituteText(string input, string sourceAlphabet, string targetAlphabet)
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < input.Length; i++)
        {
            char c = input[i];
            char upperC = char.ToUpper(c);
            int idx = sourceAlphabet.IndexOf(upperC);

            if (idx != -1)
            {
                char newChar = targetAlphabet[idx];
                sb.Append(char.IsLower(c) ? char.ToLower(newChar) : newChar);
            }
            else
            {
                sb.Append(c);
            }
        }
        return sb.ToString();
    }

    // Валидация ввода текста (проверка на принадлежность алфавиту)
    static string GetInputText(string prompt, string alphabet)
    {
        while (true)
        {
            Console.Write(prompt);
            string input = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(input))
            {
                ShowError("Текст не может быть пустым.");
                continue;
            }

            bool valid = true;
            foreach (char c in input)
            {
                if (char.IsLetter(c) && alphabet.IndexOf(char.ToUpper(c)) == -1)
                {
                    valid = false;
                    break;
                }
            }

            if (!valid)
            {
                ShowError("Текст содержит символы, не входящие в выбранный алфавит!");
                continue;
            }

            return input;
        }
    }

    // Валидация пароля
    static string GetValidKeyword(string prompt, string alphabet)
    {
        while (true)
        {
            Console.Write(prompt);
            string kw = Console.ReadLine().ToUpper();

            if (string.IsNullOrWhiteSpace(kw))
            {
                ShowError("Пароль не может быть пустым.");
                continue;
            }

            bool valid = true;
            HashSet<char> used = new HashSet<char>();

            foreach (char c in kw)
            {
                if (alphabet.IndexOf(c) == -1)
                {
                    ShowError($"Символ '{c}' не входит в выбранный алфавит.");
                    valid = false;
                    break;
                }
                if (used.Contains(c))
                {
                    ShowError("Буквы в пароле не должны повторяться!");
                    valid = false;
                    break;
                }
                used.Add(c);
            }

            if (valid) return kw;
        }
    }

// Валидация числового ввода
    static int GetValidInt(string prompt, int min, int max)
    {
        while (true)
        {
            Console.Write(prompt);
            if (int.TryParse(Console.ReadLine(), out int val) && val >= min && val <= max)
            {
                return val;
            }
            ShowError($"Введите число от {min} до {max}.");
        }
    }

    static void ShowError(string message)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine($"Ошибка: {message}");
        Console.ResetColor();
    }
}