Просмотр полной версии : перебор символов(DELPHI)
qwerty001
05.04.2010, 20:26
подскажите пожалуйсто как организовать перебор всех возможных вариантов символов?
например:
a
..
z
aa
ab
..
az
..
ba
bb
..
bz
..
zz
aaa
aab
...
zzz
....
zzzzzzz.........
GhostOnline
05.04.2010, 20:30
Всех вариантов - бесконечное количество (т.к. ты макс. длину не указал)
А как можно организовать бесконечное?
fenixelite
05.04.2010, 20:46
Допиши условие, тогда уже можно будет обсуждать как сделать!
qwerty001
05.04.2010, 20:59
условие - подобрать пароль методом перебора символов. длину пароля не знаю. (: если не сложно подскажите как такое организовать.
Jingo Bo
05.04.2010, 21:04
Кури перевод чисел из одной системы счисления в другую, в твоём случае основатель системы 26(число англ. букв), каждый разряд будет в диапазоне [0..25], перевести тебе надо будет из десятичной в то которую я указал. Потом получаное число прогоняем по всем разрярам и к разряду прибавляем 0x61 и поучлаем нужный символ, профит?:)
qwerty001
05.04.2010, 21:13
не профит. я ничего не понял. =\
qwerty001
05.04.2010, 21:15
а если ещё цифры вкючить и символы в перебор?
Jingo Bo
05.04.2010, 21:19
Эх, щас напишу тада как это сделать
условие - подобрать пароль методом перебора символов. длину пароля не знаю. (: если не сложно подскажите как такое организовать.
1. В бесконечном цикле пробегать по ASCII отвечающий за буквы, цифры.
myChar := Chr(66); // Использование Char для конвертирования
Подробнее (http://www.delphisources.ru/pages/faq/faq_delphi_basics/Char.php.html)
2. Объявить в const базу пароля и по ней пробегать в цикле.
Вот пример как реализовывать через const:
const
m='qwertyuioplkjhgfdsa'; // база
Var
i,j:integer;
s,str:string;
begin
str:='';
for j:=1 to 15 do // кол-во символов*на базу
begin
for i:=1 to length(m) do
begin
s:=str+m[i];
memo1.Lines.Add(s); // что то делаем с генер, строкой
end;
str:=s;
end;
end;
P.s. но лучше сделать 1 циклом, например в While (i=255) do.
Jingo Bo
05.04.2010, 21:28
const ci_interval = 26; {â àãë. ñëîâàðå 26 áóêàô:)}
ci_index = $61; { èíäåêñ ñèìâîë "à" â ascii}
function IntToSymbols(Const bound : Cardinal) : String;
Var i, curBound, c_mod : Cardinal;
c_tmp : Char;
Begin
Result := '';
curBound := bound;
while true do
Begin
if curBound < ci_interval then
Begin
Result := Result + Chr(ci_index + curBound);
Break;
end;
c_mod := curBound mod ci_interval;
curBound := curBound div ci_interval;
Result := Result + Chr(ci_index + c_mod);
end;
{ïåðåâîðà÷èâàåì ñòðîêó}
for i := 1 to Length(Result) div 2 do
Begin
c_tmp := Result[i];
Result[i] := Result[Length(Result)-i+1];
Result[Length(Result)-i+1] := c_tmp;
end;
end;
Используем так :
procedure TForm1.Button1Click(Sender: TObject);
var i : Integer;
begin
for i := 0 to *сколько надо вариантов* do
Memo1.Lines.Add(IntToSymbols(i));
end;
Будет выводить
a
b
c
..
z
aa
ab
ac
...
А как можно организовать бесконечное?
While (1=1) do // или while true do
begin
.... // прервать команда Break;
end;
While (1<>1) do
begin
....
end;
Точнее так:
While (1=1) do
begin
....
end;
qwerty001
05.04.2010, 21:35
спасибо большое (:
Jingo Bo
05.04.2010, 21:37
Я вообще не понимаю смысла кода от JnK, выше код который даёт бесконечное число комбинации(точнее максимальное от Cardinal / 26) :)
GhostOnline
05.04.2010, 22:02
While (1<>1) do // или while true do
begin
.... // прервать команда Break;
end;
Дурак?
while true do
begin
end;
где здесь организация?
AlexTheC0d3r
05.04.2010, 22:16
интересно, что будет занимать больше времени?
while (1=1) do
либо while true do
??
Мне кажется что 1е, т.к. в цикле мы дополнительно сравниваем действительно ли 1=1...или я ошибаюсь?
UPD: при 4х различных тестах пришел к выводу, что как бы ни было парадоксально, на 1 выполнение цикла while 1=1 do уходит меньше времени чем на while true do
Jingo Bo, У тебя пропускается вывод на aa .. az сразу с b
a
..
z
ba
..
bz
ca
P.s. Прогонял в цикле 1000.
Насчет кода я показывал метод реализации, и ниже дописал, что лучше сделать 1 циклом, насчет "бесконечного цикла" то ниже приведен код. Т.к. пароли имеют чувствительность к регистру и используются цифры, сделал на основе константы.
const
base='0987654321ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvuts rqponmlkjihgfedcba';
var
s,str:string;
i:integer;
begin
i:=1;
while true do
begin
s:=str+base[i];
memo1.Lines.add(s);
if i>=length(base) then
begin
i:=1;
str:=s;
end;
inc(i);
end;
интересно, что будет занимать больше времени?
либо
??
Мне кажется что 1е, т.к. в цикле мы дополнительно сравниваем действительно ли 1=1...или я ошибаюсь?
В обоих циклах идет сравние:
1. 1=1
2. true=true; (т.е. -1=-1)
2 GhostOnline, обзываться не стоит, перепутал условие.
P.s. Сорри за оффтоп.
Jingo Bo
05.04.2010, 22:47
Jingo Bo, У тебя пропускается вывод на aa .. az сразу с b
Это да, но это не сложно исправить, писалось та на скорую руку.
В обоих циклах идет сравние:
1. 1=1
2. true=true; (т.е. -1=-1)
Взорвал мозг))) Во-первых while 1=1 do уже удивляет и доставляет своей нелепостью(пс, первый раз такое вижу):) Во-вторых при 1=1 будет 2 проверки, а с true - одна(не веришь - гоу в отладчик) :) В третьих действительно часто при проверки пишут такие обсурдные вещи как 1<>1 и т.д. для того что delphi со включённым(по дефолту) ключём {$OPTIMIZATION ON} не отбрасывала код в условии if false then (подобное используют что имитировать вложенную процедуру через метки(для оптимизации и уменьшения кода). Но всё равно это только от не знания деректив.
AlexTheC0d3r
05.04.2010, 22:51
В обоих циклах идет сравние:
1. 1=1
2. true=true; (т.е. -1=-1)
2 GhostOnline, обзываться не стоит, перепутал условие.
P.s. Сорри за оффтоп.
Проверьте код:
program TestCycleDuration;
{$APPTYPE CONSOLE}
uses
SysUtils, DateUtils;
var
i: integer;
timeStart, timeEnd: TDateTime;
begin
Writeln('................................');
Writeln('................................');
Writeln('................................');
Writeln('................................');
Writeln('First test, cycle "while true do"');
Writeln('Testing...');
i := 0;
timeStart := now;
while true do
begin
i := i + 1;
if i = 2000000000 then
Break;
end;
timeEnd := Now;
Writeln('Test duration: ' + inttostr(MilliSecondsBetween(timeEnd, timeStart)) +
'ms');
Writeln('................................');
Writeln('................................');
Writeln('................................');
Writeln('................................');
Writeln('Second test, cycle "while 1=1 do"');
Writeln('Testing...');
i := 0;
timeStart := now;
while 1 = 1 do
begin
i := i + 1;
if i = 2000000000 then
Break;
end;
timeEnd := Now;
Writeln('Test duration: ' + inttostr(MilliSecondsBetween(timeEnd, timeStart)) +
'ms');
Readln;
end.
UPD2: подправил
Рекомендуется тестировать при как можно меньшем кол-ве запущенных приложений!
тест общий занимает около 2х секунд... интересны результаты... Абсолютно не претендую на адекватность теста, тем более скорее всего он не особо адекватен..
UPD3: Прогнав пару-тройку раз, заметил что результаты примерно одинаковые, на моей машине значения либо 671ms ибо 687ms
GhostOnline
06.04.2010, 01:05
правильно, потому что 1=1 сравниваются константы
компилятор такие вещи вычисляет заранее
кстати, AlexTheC0d3r советую для таких вещей установить себе профайлер чтобы каждый раз не мучаться с настройкой велика - GProfile
Намного хуже когда я вижу такой код:
if Button1.Enabled = True then ...
Jingo Bo
06.04.2010, 02:06
if Button1.Enabled = True then ...
Да, это тоже лол:)
Эт я тоже давно читал примеры говнокода и вот до сих пор вспоминаю код :
if Length(IntToStr(number)) = 1 then
{один разряд у числа} else { не один }
или
if true then
{что то делаем} else {а дальше сплошной профит}
Такие мастера находятся:))
Jingo Bo
06.04.2010, 02:13
Потестил код, короче с true как ни крути выигрывает, 672ms, при 1=1 686ms. Но в отладчике код одинаков, то есть ни там ни там нет проверки, но разница есть, во всём виноваты массоны:))
AlexTheC0d3r
06.04.2010, 15:04
Новый тест, без оптимизации...
Действительно, как бы не парадоксально это выглядело, но while true do проигрывает по скорости коду -> while 1=1 do
Также можно заметить, что добавление в условие цикла сторонних вычислений во много раз замедляет его работу, вот доказательства:
{$OPTIMIZATION OFF}
program TestCycleDuration;
{$APPTYPE CONSOLE}
uses
SysUtils, DateUtils;
var
i: integer;
timeStart, timeEnd: TDateTime;
firstRes, secondRes, thirdRes: string;
begin
Writeln('................................');
Writeln('................................');
Writeln('................................');
Writeln('................................');
Writeln('First test, cycle "while true do"');
Writeln('Testing...');
i := 0;
timeStart := now;
while True do
begin
i := i + 1;
if i = 2000000000 then
Break;
end;
timeEnd := Now;
Writeln('Test duration: ' + inttostr(MilliSecondsBetween(timeEnd, timeStart))
+
'ms');
firstRes := inttostr(MilliSecondsBetween(timeEnd, timeStart));
Writeln('................................');
Writeln('................................');
Writeln('................................');
Writeln('................................');
Writeln('Second test, cycle "while 1=1 do"');
Writeln('Testing...');
i := 0;
timeStart := now;
while 1 = 1 do
begin
i := i + 1;
if i = 2000000000 then
Break;
end;
timeEnd := Now;
Writeln('Test duration: ' + inttostr(MilliSecondsBetween(timeEnd, timeStart))
+
'ms');
secondRes := inttostr(MilliSecondsBetween(timeEnd, timeStart));
Writeln('................................');
Writeln('................................');
Writeln('................................');
Writeln('................................');
Writeln('Tird test, moron'#39's cycle "while StrToInt(1)=StrToInt(1) do"');
Writeln('Testing...');
i := 0;
timeStart := now;
while StrToInt('1') = StrToInt('1') do
begin
i := i + 1;
if i = 2000000000 then
Break;
end;
timeEnd := Now;
Writeln('Test duration: ' + inttostr(MilliSecondsBetween(timeEnd, timeStart))
+
'ms');
thirdRes := inttostr(MilliSecondsBetween(timeEnd, timeStart));
WriteLn('Two tests: 1: ' + firstRes + 'ms' + ' 2: ' + secondRes + 'ms' + ' 3:'
+ thirdRes + 'ms');
Readln;
end.
Результаты: 1- 4812ms 2-4750ms 3-36265ms
Один раз было, что True на 10 мс быстрее выполнилось чем 1=1:
1: 3859ms 2: 3844ms 3: 91609ms
1: 4249ms 2: 4000ms 3: 92421ms
P.s. 3 метод просто убивает :)
AlexTheC0d3r
06.04.2010, 19:51
Один раз было, что True на 10 мс быстрее выполнилось чем 1=1:
1: 3859ms 2: 3844ms 3: 91609ms
1: 4249ms 2: 4000ms 3: 92421ms
P.s. 3 метод просто убивает :)
Дак там и написано идиотский тест)
GhostOnline
07.04.2010, 11:40
Хватит гадать, в обоих случаях константные выражения.
Точная скорость выполнения зависит от слишком многих факторов
qwerty001
07.04.2010, 15:24
const ci_interval = 79;
ci_index = 32;
function IntToSymbols(Const bound : Cardinal) : String;
Var i, curBound, c_mod : Cardinal;
c_tmp : Char;
Begin
Result := '';
curBound := bound;
while true do
Begin
if curBound < ci_interval then
Begin
Result := Result + Chr(ci_index + curBound);
Break;
end;
c_mod := curBound mod ci_interval;
curBound := curBound div ci_interval;
Result := Result + Chr(ci_index + c_mod);
end;
for i := 1 to Length(Result) div 2 do
Begin
c_tmp := Result[i];
Result[i] := Result[Length(Result)-i+1];
Result[Length(Result)-i+1] := c_tmp;
end;
end;
объясните пожалуйста почему когда использую этот код и подключаю icqclient, то код рожает совсем другие символы?
qwerty001
08.04.2010, 01:21
всё, разобрался. но возникла другая проблема. по коду Jingo Bo, если брать словарь 79 символов и переменную int64, то перебор возможен до ~7(длина пароля) символов, потом всё по новой переберает. =\
vBulletin® v3.8.14, Copyright ©2000-2026, vBulletin Solutions, Inc. Перевод: zCarot