PDA

Просмотр полной версии : перебор символов(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
Эх, щас напишу тада как это сделать

JnK
05.04.2010, 21:25
условие - подобрать пароль методом перебора символов. длину пароля не знаю. (: если не сложно подскажите как такое организовать.

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
...

JnK
05.04.2010, 21:29
А как можно организовать бесконечное?

While (1=1) do // или while true do
begin
.... // прервать команда Break;
end;

wolmer
05.04.2010, 21:32
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

JnK
05.04.2010, 22:17
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;

JnK
05.04.2010, 22:29
интересно, что будет занимать больше времени?

либо

??

Мне кажется что 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

JnK
06.04.2010, 19:30
Один раз было, что 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(длина пароля) символов, потом всё по новой переберает. =\