С++ |
int swap(int value, int start, int len)
{
len = len % (sizeof(value) * 8);
start = start % (sizeof(value) * 8);
int bits = (INT_MAX >> ((sizeof(value) * 8) - len - 1));
bits = bits << start;
int buf = (value >> len) & bits;
int res = value & bits;
res = res << len;
res |= buf;
int rest = value & ~bits;
rest = rest & ~(bits << len);
return rest | res;
}
//////////////////////////////////////////////////////
void scrambler(int keyword)
{
int res = keyword;
for (int i = 1; i < 16; i = i * 2)
{
for (int j = 0; j < 32 - i; j = j + i * 2)
res = swap(res, j, i);
}
if (res == -1268496634)
std::cout << "Password is correct\n";
else
std::cout << "Password is wrong\n";
}
|
Разберем представленный код и перепишем его построчно.
1. |
int swap(int value, int start, int len) |
2. |
{ |
3. |
len = len % (sizeof(value) * 8); |
4. |
start = start % (sizeof(value) * 8); |
5. |
int bits = (INT_MAX >> ((sizeof(value) * 8) - len - 1)); |
6. |
bits = bits << start; |
7. |
int buf = (value >> len) & bits; |
8. |
int res = value & bits; |
9. |
res = res << len; |
10. |
res |= buf; |
11. |
int rest = value & ~bits; |
12. |
rest = rest & ~(bits << len); |
13. |
return rest | res; |
14. |
} |
15. |
void scrambler(int keyword) |
16. |
{ |
17. |
int res = keyword; |
18. |
for (int i = 1; i < 16; i = i * 2) |
19. |
{ |
20. |
for (int j = 0; j < 32 - i; j = j + i * 2) |
21. |
res = swap(res, j, i); |
22. |
} |
23. |
if (res == -1268496634) |
24. |
std::cout << "Password is correct\n"; |
25. |
else |
26. |
std::cout << "Password is wrong\n"; |
27. |
} |
Функция scrambler() проверяет число (keyword). Если число правильное (строка 23), то выводится на экран сообщение «Password is correct» (строка 24), иначе – выводится на экран сообщение «Password is wrong» (строка 25). Проверка правильности числа осуществляется с помощью функции swap() (строки1-14) и значение этой функции сравнивается с константой ‑1268496634 (строка 23).
Существует 2 способа решения задачи:
1) Перебор.
2) Аналитический.
Способ 1.
Перебору будет подвергаться параметр функции scrambler(): от 0 до максимального значения типа данных int (MAX_INT).
Для автоматизации перебора необходимо модифицировать саму функцию scrambler():
1) Cделать так, чтобы функция возвращала результат, например, логического типа (bool). Для этого необходимо заменить объявление функции (строка 15) на:
bool scrambler(int keyword)
2) Заменить вывод на экран оператором возвращения результата:
а) строку 24 заменить на return true;
б) строку 26 заменить на return false;
Пример реализации самого цикла перебора представлен в листинге 2.2-1.
Листинг 2.2-1 – Реализация цикла перебора параметра функции scrambler() на языке программирования C++
int main()
{
// начальное время (в мс)
int startTime = GetTickCount();
// основной цикл перебора
for (int i = 0; i < INT_MAX; i++)
if (scrambler(i) == true)
{
// вывод результата на экран
std::cout << "Result: " << i << std::endl;
}
// время завершения цикла (в мс)
int finishTime = GetTickCount();
// вывод статистики по времени работы на экран
std::cout << "Worked: " << (finishTime - startTime) / 1000.0 << " sec" << std::endl;
}
В результате выполнения программа выдает следующее:
Result: 640508130
Worked: 2647.28 sec
Проверяем полученный результат:
scrambler(640508130) à «Password is correct»
Ответ найден, он равен 640508130.
Способ 2.
Можно предположить, что функция swap(), выполняемая в цикле (строки 18-22), является симметричной. То есть, если выполнить этот цикл 2 раза: первый раз – над числом, второй раз – над полученным в первом шаге результатом, то в этом случае можно получить то же самое исходное число. Это легко проверить на любом случайном числе. Пример приведен в листинге 2.1-2.
Листинг 2.1-2 – Проверка симметричности функции swap()
/// Проверка работы только цикла
/// из функции scrambler()
/// PARAMS
/// keyword - преобразуемое число
/// RETURN
/// преобразованное число (int)
///
int scrambler_test(int keyword)
{
int res = keyword;
// цикл из оригинальной функции scrambler()
for (int i = 1; i < 16; i = i * 2)
{
for (int j = 0; j < 32 - i; j = j + i * 2)
res = swap(res, j, i);
}
// возвращаем результат
return res;
}
int main()
{
int keyword1, keyword2, keyword3;
// исходное число
keyword1 = 1234567;
// первое преобразование
keyword2 = scrambler_test(keyword1);
// вотрое преобразование
keyword3 = scrambler_test(keyword2);
// вывод на экран
std::cout << "keyword1: " << keyword1 << std::endl;
std::cout << "keyword2: " << keyword2 << std::endl;
std::cout << "keyword3: " << keyword3 << std::endl;
}
Программа вернула следующий результат:
keyword1: 1234567
keyword2: 1208017259
keyword3: 1234567
Если цикл с функцией swap() симметричный (функция scrambler_test() в листинге 2.1‑2), то на вход функции scrambler() необходимо подать результат выполнения функции scrambler_test() с числом -1268496634 (строка 23).
Проверим результат на практике.
scrambler_test(-1268496634) à 640508130
scrambler(640508130) à «Password is correct»
Ответ найден, он равен 640508130.