Представим, что существуют пароли,
состоящие из n цифр, причем каждая цифра должна принадлежать интервалу [1..n],
так же цифры не могут повторяться, например пароль из трех символ может быть
одним из следующих:
123
132
213
231
312
321
Так вот если
существуют такие пароли, то можно написать пргограмму которая будет их
перебирать. Для числа 4, это будут перестановки (возможные
пароли):
1234
1243
1432
...
...
...
4321
Число таких
перестановок определяется как n! Для числа 3, количество перестановок будет
равно 3! = 3 * 2 * 1 = 6. Для четырех: 4! = 4 * 3 * 2 * 1 = 24.
Число 9! -
уже не малое, поэтому в нашей программе сделаем ограничения для числа n, пусть
оно будет находиться в интервале [1 <= n <= 9].
Для генерации
перестановок используется алгоритм Дейкстры для получения всех перестановок по
алфавиту.
Разберем этот алгоритм:
Пусть у нас есть первая
перестановка (например 1234). Для нахождения следующей выполняем три шага. 1.
Двигаясь с предпоследнего элемента перестановки, ищем элемент a[i],
удовлетворяющий неравенству a[i] < a[i + 1]. Для перестановки 1234, это
число 3, т. к. (3 < 4).
2. Меняем местами элемент a[i] с наименьшим
элементом, который:
а) находится праве a[i].
б) является больше чем
a[i].
В нашем случае меняем 3 и 4.
3. Все элементы стоящие за a[i]
сортируем. В нашем случем нужно отсортировать число 4, но это единственный
элемент, следовательно так его и оставляем.
В результате выполнения
этих трех шагов получаем следующую по алфавиту перестановку 1243.
Выполнять
эти шаги нужно циклически до тех пор, пока в перестановке не будет находится
искомый в первом шаге элемент a[i], т. е. пока перестановка не станет
отсортированной по убыванию: 4321.
Ниже преведенна программа на языке Си, в
которой используется данный алгоритм.
В файле input.txt, находящемся в
одном каталоге с программой должно быть записанно число 1 <= n <= 9,
после выполнения программы, в том же каталоге появится файл output.txt, в
котором на каждую строчку и будут вывденны перестановки.
#include<stdio.h>
#define bool int
#define true 0
#define false 1
int main() {
FILE *in, *out;
int per[10], obr[10];
int i, j, k, tmp, min, raz, n;
bool flag;
in = fopen("input.txt", "r");
out = fopen("output.txt", "w");
fscanf(in, "%d", &n);
for (i = 0; i < n; i++) {
per[i] = i+1;
}
while (1) {
for (k = 0; k < n; k++) {
fprintf(out, "%d", per[k]);
}
flag = false;
for (i = n - 2; i >= 0; i--) {
if (per[i] < per[i + 1]) {
flag = true;
break;
}
}
if (flag == false) {
break;
}
fprintf(out, "\n");
raz = per[i+1];
for (j = i+1; j < n; j++) {
if (((per[j] - per[i]) < raz) && (per[i] < per[j])) {
min = j;
}
}
tmp = per[i];
per[i] = per[min];
per[min] = tmp;
for (j = i + 1; j < n; j++) {
obr[j] = per[j];
}
j = i + 1;
for (k = n-1; k >= i+1; k--) {
per[j] = obr[k];
j++;
}
}
fclose(in);
fclose(out);
return 0;
}
© dushik