Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.52/25: Рейтинг темы: голосов - 25, средняя оценка - 4.52
2 / 2 / 0
Регистрация: 28.05.2020
Сообщений: 58

Перебор вариантов

29.05.2020, 11:26. Показов 6047. Ответов 72

Студворк — интернет-сервис помощи студентам
Здравствуйте, нужна помощь новичку (мне).
Есть набор k букв, каждой букве может соответствовать несколько значений, например:
А: 1,2,7
Б: 3,6
В: 4
Г: 5
Все значения разные.
Вопрос: как организовать цикл, чтобы на каждой итерации выдавался набор значений по одному от каждой буквы? То есть в этом примере по 4 значения. Чтобы в итоге перебрались все варианты. Следует сказать, что букв может быть до 33, количество значений не ограничено.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.05.2020, 11:26
Ответы с готовыми решениями:

перебор вариантов...
имеется строка, содержащая слово. (например слово "лампа") Как можно перебрать всевозможные сочитания букв этого слова? разбил слово на...

Перебор всех вариантов
Всем привет! Это моя первая проблема, с которой хотелось бы поделиться. Проблема сложная, но хотелось бы верить, что получится найти ее...

Перебор вариантов из строки
Здравствуйте! Задачка такая. Есть строка с текстом "Ананас; Абрикос; Банан". Требуется, что бы программа выбирала эти элементы...

72
2 / 2 / 0
Регистрация: 28.05.2020
Сообщений: 58
02.06.2020, 12:04  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от samana Посмотреть сообщение
Я ещё не знаю как это придумать
И если придумаете, вставьте, пожалуйста, исправления сразу в мою форму, которую я сейчас скинул, так будет гораздо удобнее
0
1533 / 540 / 127
Регистрация: 09.01.2018
Сообщений: 1,756
02.06.2020, 12:07
Цитата Сообщение от shabserg Посмотреть сообщение
так и должно быть. Просто нужно заменять не все буквы в слове одновременно, а друг за другом. Например, сначала все а на б. Затем все б на в. И тогда в конце замены получится "врабнушнпбн"
Не получится.
Меняем все а на б - все а заменились на б.
Меняет все б на еще что то, и так далее.
Мы никак не сможем получить таким образом разные значения для а.

Вот например
абракадабра
врабнушнпбн

Если мы просто заменим а на в (как в первой букве результата)
То получим
вбрвквдвбрв

И вместо в мы никак не сможем получить теперь у как здесь:
врабнушнпбн

Потому что у нас нет замен для в. Вообще нет в правиле.
Это говорит о том, что вы скорее всего не поняли задание.


Попозже перепишу генератор ключей, посмотрю на результаты.
1
2 / 2 / 0
Регистрация: 28.05.2020
Сообщений: 58
02.06.2020, 12:26  [ТС]
escoult, жесть какое задание, действительно, я понял его неправильно (
То есть, получается, что одна и та же буква (а) в итоге может быть заменена на совсем разные, я даже не обратил на это внимание... первая а там заменилась на в, вторая на б, третья на у, четвертая и пятая на н. Извините.

Добавлено через 3 минуты
samana, вы тогда тоже были правы, одна буква может меняться на разные
Дело в том, что сейчас перебор включает одновременно все возможные варианты для одной буквы. Например если слово "кок" с заменами
ккк
123

то у меня формируются такие варианты

1о1
1о2
1о3
2о1
2о2
2о3
3о1
3о2
3о3

то-есть одна и та же буква в слове может быть заменена одновременно разными предложенными для неё вариациями.

А вы говорите, что если буква в слове повторяется, то для проверки меняются все одинаковые буквы на одно значение и ваш вариант перебора получится куда меньше

1о1
2о2
3о3
0
1533 / 540 / 127
Регистрация: 09.01.2018
Сообщений: 1,756
02.06.2020, 13:28
shabserg, вообщем переписал я этот класс, теперь он учитывает повторяющиеся символы и находит вашу заветную "врабнушнпбн".
Правда работает теперь немного дольше, из-за увеличившегося числа ключей, 1.2 с на коротком словаре, на длинном еще не тестил.

Вот обновленные участки кода:

Кликните здесь для просмотра всего текста

C#
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
 
namespace Brutforce
{
    public class PasswordHack : IPasswordHack, ISourceData
    {
        private readonly Dictionary<char, List<char>> _map;
        public string Rule { get; }
        public string Alphabet { get; }
 
        public PasswordHack(string rule, string alphabet)
        {
            Rule = rule;
            Alphabet = alphabet;
 
            //заполняем карту
            _map = new Dictionary<char, List<char>>();
            for (int i = 0; i < Rule.Length; i++)
            {
                if (_map.ContainsKey(Rule[i]))
                {
                    _map[Rule[i]].Add(Alphabet[i]);
                }
                else
                {
                    _map.Add(Rule[i], new List<char>() { Alphabet[i] });
                }
            }
        }
 
        public string Encrypt(string src, int[] key)
        {
            var res = src.ToCharArray();
            for (int i = 0, k = 0; i < res.Length && k < key.Length; i++)
            {
                var currentSymbol = res[i];
                if (_map.ContainsKey(currentSymbol))
                {
                    res[i] = _map[currentSymbol][key[k++]];
                }
            }
 
            return new string(res);
        }
        public IEnumerable<int[]> GetKeys(string wordFromDict)
        {
            //выбираем из слова те символы, которые содержатся в карте 
            //(имеют варианты замены), включая повторяющиеся символы,
            //и вычисляем для каждого максимальные значения ключа
            //(количество возможных замен - 1)
            var keyMaxValues = wordFromDict
                .Where(c => _map.ContainsKey(c))
                .Select(c => _map[c].Count - 1)
                .ToArray();
 
            //создадим массив, который будем преобразовывать для получения всех комбинаций
            var key = new int[keyMaxValues.Length];
 
            //скопируем в него максимальные значения ключа - это первая комбинация
            Array.Copy(keyMaxValues, key, keyMaxValues.Length);
 
            //вернем первую комбинацию
            yield return key;
 
            //в последней комбинации все разряды ключа равны 0
            //это условие выхода из цикла
            while(!key.All(x => x == 0))
            {
                var n = key.Length;
 
                for (int i = n - 1; i >= 0; i--)
                {
                    if (key[i] > 0)
                    {
                        key[i]--;
                        if (i == n - 1)
                        {
                            yield return key;
                            i++;
                            continue;
                        }
 
                        key[i + 1] = keyMaxValues[i + 1] + 1;
                        i += 2;
                    }
                }
            }
        }
 
    }
}


Тест:
Кликните здесь для просмотра всего текста

C#
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
 static void Main(string[] args)
        {
            //исходные данные
            string[] dict = { "барк", "ведро", "вишня", "долина", "колос", "кость", "кот", 
                "остров", "порт", "абракадабра", "кадабраабра" };
            
            var rule = "аааааббббррркд";
            var alphabet = "уврнбрапенабнш";
            var hash = MD5Helpers.GetMD5Hash("врабнушнпбн"); //абракадабра
 
            var sw = new Stopwatch();
            sw.Start();
 
            var tool = new HackTool(dict, rule, alphabet, hash);
            if (tool.TryHack(out var result_abra))
            {
                Console.WriteLine("Пароль найден:");
                Console.WriteLine(result_abra);
            }
            else
            {
                Console.WriteLine("Пароль не найден");
            }
 
            Console.WriteLine();
            Console.WriteLine("Длина словаря: " + dict.Length);
 
            sw.Stop();
            Console.WriteLine("Затраченное время: " + sw.Elapsed);
 
        }


Результаты
Code
1
2
3
4
5
Пароль найден:
абракадабра
 
Длина словаря: 11
Затраченное время: 00:00:01.2292337
Добавлено через 15 минут

Не используйте в словаре слишком длинные слова как это "абракадабракадабраабра". Слишком большое число символов увеличит время перебора до неразумных значений, даже если искомое слово другое, а это просто лежит "по дороге". Программе все равно придется его перебирать и время ожидания будет очень велико.

Лучше всего короткие слова 4-5 букв.
2
 Аватар для samana
2639 / 1567 / 853
Регистрация: 23.02.2019
Сообщений: 3,876
02.06.2020, 13:48
Цитата Сообщение от escoult Посмотреть сообщение
вообщем переписал я этот класс, теперь он учитывает повторяющиеся символы и находит вашу заветную "врабнушнпбн".
escoult, это просто шикарно! Вот это мозги! А я так и не придумал вариант с более быстрым просчётом.. Но хорошо, что наконец-то задача решена!

Не по теме:

хотел написать: лайк и подписка, но вовремя опомнился.

1
2 / 2 / 0
Регистрация: 28.05.2020
Сообщений: 58
02.06.2020, 13:53  [ТС]
escoult, не могу собрать ваш код воедино, выдает ошибки при компиляции.
У меня получилось так:
C#
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
 
namespace Brutforce
{
    class Program
    {
        static void Main(string[] args)
        {
            //исходные данные
            string[] dict = { "барк", "ведро", "вишня", "долина", "колос", "кость", "кот",
                "остров", "порт", "абракадабра", "кадабраабра" };
 
            var rule = "аааааббббррркд";
            var alphabet = "уврнбрапенабнш";
            var hash = MD5Helpers.GetMD5Hash("врабнушнпбн"); //абракадабра
 
            var sw = new Stopwatch();
            sw.Start();
 
            var tool = new HackTool(dict, rule, alphabet, hash);
            if (tool.TryHack(out var result_abra))
            {
                Console.WriteLine("Пароль найден:");
                Console.WriteLine(result_abra);
            }
            else
            {
                Console.WriteLine("Пароль не найден");
            }
 
            Console.WriteLine();
            Console.WriteLine("Длина словаря: " + dict.Length);
 
            sw.Stop();
            Console.WriteLine("Затраченное время: " + sw.Elapsed);
 
        }
    }
    public interface IPasswordHack : ISourceData
    {
        string Encrypt(string src, int[] key);
        IEnumerable<int[]> GetKeys(string wordFromDict);
    }
 
    public interface ISourceData
    {
        string Rule { get; } //верхняя строка правила
        string Alphabet { get; } //нижняя строка
    }
    public interface IHackTool : ISourceData
    {
        public string[] Dict { get; }
        public string ControlHash { get; }
        bool TryHack(out string result);
    }
    public static class MD5Helpers
    {
        public static string GetMD5Hash(string input)
        {
            var md5 = MD5.Create();
            byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
 
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sb.Append(data[i].ToString("x2"));
            }
 
            return sb.ToString();
        }
 
        public static bool CheckMD5Hash(string input, string controlHash)
        {
            var hash = GetMD5Hash(input);
            return hash.Equals(controlHash);
        }
    }
    public class HackTool : IHackTool
    {
        readonly IPasswordHack _hack;
        public string[] Dict { get; }
        public string Rule { get; }
        public string Alphabet { get; }
        public string ControlHash { get; }
 
        public HackTool(string[] dict, string rule, string alphabet, string controlHash)
        {
            Dict = dict;
            Rule = rule;
            Alphabet = alphabet;
            ControlHash = controlHash;
            _hack = new PasswordHack(Rule, Alphabet);
        }
 
        public bool TryHack(out string result)
        {
            //Для сокращения времени перебора, сортируем словарь по количеству входящих в него символов из правила
            //Далее будем работать с этим словарем
            var actualDict = Dict.Select(s => s.ToLower())
                .OrderByDescending(s => s.Intersect(Rule.ToLower()).Count());
 
            foreach (var item in actualDict)
            {
                //получаем перечисление ключей
                var keys = _hack.GetKeys(item);
 
                //шифруем и проверяем
                foreach (var key in keys)
                {
                    var encrypted = _hack.Encrypt(item, key);
                    if (MD5Helpers.CheckMD5Hash(encrypted, ControlHash))
                    {
                        result = item;
                        return true;
                    }
                }
            }
 
            result = null;
            return false;
        }
 
    }
 
    public class PasswordHack : IPasswordHack, ISourceData
    {
        private readonly Dictionary<char, List<char>> _map;
        public string Rule { get; }
        public string Alphabet { get; }
 
        public PasswordHack(string rule, string alphabet)
        {
            Rule = rule;
            Alphabet = alphabet;
 
            //заполняем карту
            _map = new Dictionary<char, List<char>>();
            for (int i = 0; i < Rule.Length; i++)
            {
                if (_map.ContainsKey(Rule[i]))
                {
                    _map[Rule[i]].Add(Alphabet[i]);
                }
                else
                {
                    _map.Add(Rule[i], new List<char>() { Alphabet[i] });
                }
            }
        }
 
        public string Encrypt(string src, int[] key)
        {
            var res = src.ToCharArray();
            for (int i = 0, k = 0; i < res.Length && k < key.Length; i++)
            {
                var currentSymbol = res[i];
                if (_map.ContainsKey(currentSymbol))
                {
                    res[i] = _map[currentSymbol][key[k++]];
                }
            }
 
            return new string(res);
        }
        public IEnumerable<int[]> GetKeys(string wordFromDict)
        {
            //выбираем из слова те символы, которые содержатся в карте 
            //(имеют варианты замены), включая повторяющиеся символы,
            //и вычисляем для каждого максимальные значения ключа
            //(количество возможных замен - 1)
            var keyMaxValues = wordFromDict
                .Where(c => _map.ContainsKey(c))
                .Select(c => _map[c].Count - 1)
                .ToArray();
 
            //создадим массив, который будем преобразовывать для получения всех комбинаций
            var key = new int[keyMaxValues.Length];
 
            //скопируем в него максимальные значения ключа - это первая комбинация
            Array.Copy(keyMaxValues, key, keyMaxValues.Length);
 
            //вернем первую комбинацию
            yield return key;
 
            //в последней комбинации все разряды ключа равны 0
            //это условие выхода из цикла
            while (!key.All(x => x == 0))
            {
                var n = key.Length;
 
                for (int i = n - 1; i >= 0; i--)
                {
                    if (key[i] > 0)
                    {
                        key[i]--;
                        if (i == n - 1)
                        {
                            yield return key;
                            i++;
                            continue;
                        }
 
                        key[i + 1] = keyMaxValues[i + 1] + 1;
                        i += 2;
                    }
                }
            }
        }
 
    }
}
Можете, пожалуйста, прислать новый код полностью?
0
1533 / 540 / 127
Регистрация: 09.01.2018
Сообщений: 1,756
02.06.2020, 14:13
Лучший ответ Сообщение было отмечено shabserg как решение

Решение

Цитата Сообщение от samana Посмотреть сообщение
хотел написать: лайк и подписка, но вовремя опомнился.


Цитата Сообщение от shabserg Посмотреть сообщение
Можете, пожалуйста, прислать новый код полностью?
Вложения
Тип файла: 7z Brutforce.7z (114.7 Кб, 5 просмотров)
1
 Аватар для samana
2639 / 1567 / 853
Регистрация: 23.02.2019
Сообщений: 3,876
02.06.2020, 14:44
shabserg, Попробовал внедрить код от escoult, в ваш Winforms проект. Попробуйте: Lab2CSapp.zip
1
2 / 2 / 0
Регистрация: 28.05.2020
Сообщений: 58
02.06.2020, 19:29  [ТС]
escoult, спасибо.
А можно, пожалуйста, еще раз поподробнее про ключи, их длину, мин. и макс. значение? А то я сижу, читаю код и никак не могу понять(.. почему -1...
Что мы можем знять о ключе.
Длина ключа равна количеству символов из верхней строки, совпадающих с символами шифруемого слова без повторов.
Максимальное значение для каждой цифры ключа равно количеству возможных замен для символа, информацию о котором предоставляет цифра ключа минус 1.
Минимальное значение цифры ключа - 0

Таким образом, сгруппировав все возможные замены для отдельного слова, мы можем узнать как длину ключа так и максимальные значения для каждой цифры.
Добавлено через 19 минут
escoult, И еще мне по заданию нужно вывести не только само слово из словаря (абракадабра), но и пароль (врабнушнпбн) в случае успешного подбора.
Как я понял, он хранится в encrypted, но если я пытаюсь к нему обратиться в form1, то он не разрешает (строка 27).
C#
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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.IO;
using System.Diagnostics;
 
namespace Brutforce
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        void StartHacking(string[] dict, string rule, string alphabet, string hash )//аналог main, было static
        {
            var tool = new HackTool(dict, rule, alphabet, hash);//подаем входные параметры и начинаем искать пароль
            if (tool.TryHack(out var result_abra))
            {
                //password_with_change_box2.Text = encrypted;
                word_dict_box.Text = result_abra; //вывод найденного слова из словаря
            }
            else
            {
                word_dict_box.Text = "Пароль не найден";
            }
            
        }
        private void button1_Click(object sender, EventArgs e)
        {
            string password = null;
            if (password_box.Text.Length != 0)
            { password = password_box.Text; }
 
            if (password_box.Text.Length != 0)
            {
                using (MD5 md5Hash = MD5.Create()) //вычисление хэша для пароля
                {
                    string hashed_pass = GetMd5Hash(md5Hash, password);
                    hash_of_password1_box.Text = (hashed_pass).ToString();
                }
                string GetMd5Hash(MD5 md5Hash, string input)
                {
                    // Convert the input string to a byte array and compute the hash.
                    byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
                    // Create a new Stringbuilder to collect the bytes
                    // and create a string.
                    StringBuilder sBuilder = new StringBuilder();
                    // Loop through each byte of the hashed data 
                    // and format each one as a hexadecimal string.
                    for (int i = 0; i < data.Length; i++)
                    {
                        sBuilder.Append(data[i].ToString("x2"));
                    }
                    // Return the hexadecimal string.
                    return sBuilder.ToString();
                }
            }
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            string path = @"dictionary.txt";
            string[] dict = File.ReadAllLines(path);//словарь слов
            string rule = source_letters_box2.Text;//верхняя строка замен
            string alphabet = final_letters_box2.Text;//нижняя строка замен
            string hash = hash_of_password2_box.Text;//скопированный хэш пароля
            StartHacking(dict, rule, alphabet, hash);
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            Process.Start(@"dictionary.txt");
        }
    }
}
Скажите, где что нужно изменить, чтобы можно было выводить?
0
1533 / 540 / 127
Регистрация: 09.01.2018
Сообщений: 1,756
02.06.2020, 21:34
Цитата Сообщение от shabserg Посмотреть сообщение
А то я сижу, читаю код и никак не могу понять
Ключ это аргумент, необходимый для преобразования пароля с однозначным результатом.
Мы исходим из того, что пароль, который мы пытаемся найти - это пароль на каком то сайте, так говорится в задании. Сам пароль не хранится в чистом виде, вместо этого на сайте хранится его хеш. Теперь предположим, что пользователь пытается авторизоваться и вводит свой пароль, например "кот". Как сайт сможет удостовериться, что пароль верный? Ведь его можно зашифровать используя тысячи вариантов перестановок. А среди этих тысяч верным окажется только один. Однако сайт всегда должен получать один и тот же результат хеша.

Значит помимо пароля необходим еще и ключ, по которому можно зашифровать пароль и всегда получить один и тот же результат.

Что представляет собой ключ.
Чтобы ответить на этот вопрос, необходимо разобраться в том, какую информацию должен предоставлять ключ.
Он должен предоставлять данные о перестановке (заменах). Т.е. какую именно замену из всех возможных необходимо использовать для каждой буквы.

Например, пароль "кот" и вот такая верхняя строка перестановок:
ккккоотттрд

Из этой строки видно, что для буквы К возможны 4 варианта замены, для буквы О их всего два, а для буквы Т их три. Какую именно из замен использовать? Если у нас есть ключ, то он мог бы нам подсказать. Вот пример ключа:
211.

Этот ключ означает следующее:
Для буквы К использовать 2-ю замену
Для буквы О использовать 1-ю замену
Для буквы Т использовать 1-ю замену.

Т.е. ключ в нашем случае - это просто цифры означающие номер замены для символа. А располагаются эти номера в порядке следования символов в слове.
Если буква слова имеется в верхней строке, то для нее указывается номер замены,
Если ее нет в верхней строке, то и замен для нее нет и в ключе ничего не указывается.

И соответственно наша задача сводится к тому, чтобы определить этот ключ. А определить его мы можем (по условию) только полным перебором. В нашем случае ключ это набор цифр, означающих замены.

Например для буквы К возможны 4 варианта замены - С, Ф, Л, А. Если мы поместим эти символы в массив, то получим
[c][ф][д][а].
Индексация массивов начинается с 0, поэтому возможные замены в цифрах будут такими: 0, 1, 2, 3

0 будет означать что символ следует заменить на С
2 - на Д

И так далее.
Получается, что минимальное значение цифры ключа - это 0. И таковым оно будет для всех символов, потому, что у всех заменяемых символов имеется хотя бы одна замена. А максимальным значением будет количество возможных замен -1.
Вот в примере выше 4 возможных замены (длина массива), а максимальный индекс это 3. То есть длина -1.
Ну и само собой понятно, что мы всегда можем узнать максимальное значение отдельно взятой цифры ключа, потому что количество замен для символа нам известно (мы составляли карту).

А длина ключа нам тоже известна. Мы уже знаем, что ключ содержит только замены, Т.е. если для какой то буквы слова замен нет, то в ключе не будет цифры для этой замены. Значит если мы посчитаем сколько букв отдельного слова имеется в верхней строке правила, это и будет длина ключа.

Например:
КОТ
ккввббт
В строке правила из этого слова имеются только 2 буквы - К и Т. Длина ключа 2. Для остальных символов замен нет. И этих 2 цифр достаточно, чтобы перебрать все возможные варианты ключа.

Теперь как осуществить перебор. Не скажу, что это идеальный или лучший способ, но он достаточно удобен. Ключ представить как массив цифр.
Например [0][1][1][3]

Минимальное значение каждой цифры уже знаем, это 0
Максимальное - вычисляем из карты. в ней хранятся все замены.
Теперь если для каждой ячейки массива установить ее максимальное значение и затем последовательно уменьшать на 1, то все возможные значения ключа будут получены.

Т.е уменьшаем 3 пока не дойдем до 0. Затем 3 возвращаем на максимальное значение и уменьшаем 2, и так далее, пока не переберем все или не подойдет ключ.

Цитата Сообщение от shabserg Посмотреть сообщение
escoult, И еще мне по заданию нужно вывести не только само слово из словаря (абракадабра), но и пароль (врабнушнпбн) в случае успешного подбора.
Как я понял, он хранится в encrypted, но если я пытаюсь к нему обратиться в form1, то он не разрешает (строка 27).
С ключами работает метод TryHack. Значит надо его изменить, пусть возвращает и зашифрованный пароль тоже:
Кликните здесь для просмотра всего текста

C#
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
   public interface IHackTool : ISourceData
    {
        public string[] Dict { get; }
        public string ControlHash { get; }
        bool TryHack(out string result, out string encryptedPass);
    }
 
    public bool TryHack(out string result, out string encryptedPass)
        {
            //Для сокращения времени перебора, сортируем словарь по количеству входящих в него символов из правила
            //Далее будем работать с этим словарем
            var actualDict = Dict.Select(s => s.ToLower())
                .OrderByDescending(s => s.Length)
                .ThenBy(s => s.Intersect(Rule.ToLower()).Count());
 
            var encrypted = null;
            foreach (var item in Dict)
            {
                var keys = _hack.GetKeys(item);
                foreach (var key in keys)
                {
                    encrypted = _hack.Encrypt(item, key);
                    if (MD5Helpers.CheckMD5Hash(encrypted, ControlHash))
                    {
                        result = item;
                        encryptedPass = encrypted;
                        return true;
                    }
                }
            }
 
            result = null;
            encryptedPass = encrypted;
            return false;
         }


Применить:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
            var tool = new HackTool(dict, rule, alphabet, hash);//подаем входные параметры и начинаем искать пароль
            if (tool.TryHack(out var result, out var encrypted))
            {
                password_with_change_box2.Text = encrypted;
                word_dict_box.Text = result; //вывод найденного слова из словаря
            }
            else
            {
                word_dict_box.Text = "Пароль не найден";
            }
2
2 / 2 / 0
Регистрация: 28.05.2020
Сообщений: 58
03.06.2020, 19:56  [ТС]
escoult, samana, огромнейшее спасибо за помощь! Вы очень здорово меня выручили, честно говоря, не знаю, что делал бы, если не вы. Все понятно и доступно мне объяснили и задание удалось успешно выполнить. Это круто, что существуют такие отзывчивые люди, как вы, еще раз спасибо, за то, что уделили мне так много свободного времени. Я потом внедрил код escoult в Forms, все прекрасно работает.

Добавлено через 1 минуту
IamRain, вам тоже большое спасибо за ваш вариант перебора вариантов
2
 Аватар для samana
2639 / 1567 / 853
Регистрация: 23.02.2019
Сообщений: 3,876
03.06.2020, 21:17
shabserg, это было интересное задание и мне тоже было приятно, что всё у вас получилось.
А я совсем недавно ведь скинул архив для вашего винформс с вариантом от escoult, может вы не заметили просто.
1
2 / 2 / 0
Регистрация: 28.05.2020
Сообщений: 58
03.06.2020, 21:25  [ТС]
samana, заметил, но, к сожалению, он у меня не работал вообще(. Не знаю, с чем связано
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.06.2020, 21:25

Перебор всех возможных вариантов
Доброго всем дня! Есть задача: На вход дается строка из символов '0' '1' и '2' длиной не более 50. Нужно изменить число 0 на 1...

Алгоритм перебора вариантов
Кто нибудь может подсказать эффективный алгоритм без рекурсии желательно: на входе есть массив массива, нужно получить все возможные...

Диаграммы вариантов использования
Мне задали сделать презентацию на тему: &quot;Диаграммы вариантов использования. Наглядное представление ожидаемых действий и поведения системы....

Перечисление возможных вариантов
Приветствую всех. Как можно сделать перечисление всевозможных вариантов? Пример: Ввод чисел с большим количеством знаков после...

Как сделать один из 3 вариантов?
textBox1.Text = new { &quot;А&quot; &quot;У&quot; &quot;Э&quot; }; Добавлено через 2 минуты Чтобы выводилось рандомная буква из этих...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
73
Ответ Создать тему
Новые блоги и статьи
Ноутбук Альфария
kumehtar 24.08.2026
Встретился тут в сети ноутбук Альфария, примарха Альфа-Легиона. Хотя возможно, это ноутбук Омегона, разумеется. Ну как вам?
Мастера простых решений
DevAlt 23.08.2026
В сишарп стэках winforms, да и wpf существует сложная система связывания источниках данных и элементов формы(текстовые поля и метки), опирается все это на технологию событий и мета. . .
Цена ошибки
DevAlt 23.08.2026
Человек я беспокойный и потому заинтересовался OCaml, в чате форсили функторы модулей как суперфичу. Пытаясь отдуплить концепт, наткнулся на тутор с простым примером. А главный принцип обучения от. . .
Сегодня суббота, 22.08.2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины.
zorxor 22.08.2026
Сегодня суббота, 22. 08. 2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины. Кто Я, откуда Я пришел и куда Я иду? Эти вопросы не оставляют меня ни на секунду. Жизнь на планете Земля. . .
Жизня: рисунок укладки багажа, сделанный клодом
anaschu 21.08.2026
Сделал 15 снимков, он по снимкам сделал схему.
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru