-
Есть строка-шаблон задаваяемая в виде: 1stconst1[min1-max1]1stconst2[min2-max2]1stconst3... И строка-шаблон вида: 2ndconst1[]2ndconst2[]2ndconst3..., где 1stconst1..2ndconst3 - любые текстовые строки; в квадратных скобках первой строки указываются минимальные и максимальные значения счетчика, разделяемые "-" (причем min и max могут быть либо числами с одинаковым числом десятичных разрядов, либо нет), величина приращения счетчика 1; квадратные скобки второй строки пустые и указывают лишь позицию счетчика. Необходим код, результатом которого станут два массива строк. Например, заданы шаблоны: firstbla[9-11]firstblabla[09-10]firstblablabla и secondbla[]secondblabla[] В результате должны получить строки: firstbla9firstblabla09firstblablabla firstbla9firstblabla10firstblablabla firstbla10firstblabla09firstblablabla firstbla10firstblabla10firstblablabla firstbla11firstblabla09firstblablabla firstbla11firstblabla10firstblablabla и secondbla9secondblabla09 secondbla9secondblabla10 secondbla10secondblabla09 secondbla10secondblabla10 secondbla11secondblabla09 secondbla11secondblabla10
Обе строки задаются пользователем и поэтому число счетчиков заранее неизвестно. Как бы поизящнее решить задачку.
-
А не изящно уже решил?
-
> А не изящно уже решил?
Не изящно можно было бы попробовать, но получится через такую ж, что не хотелось бы даже пытаться, тем более что чувствуется, что есть простое и красивое решение. Просто я до него не могу пока дойти.
-
> Просто я до него не могу пока дойти.
"Иди, да и воздастся"
-
> "Иди, да и воздастся"
буду пока пробовать решать, как получится
-
> Необходим код, результатом которого станут два массива строк.
Программа со встроенным експлойтом? Скромный шаблон a[1-100]b[1-100]c[1-100] прородит массив из 1000000 строк. > Как бы поизящнее решить задачку.
Твои шаблоны -- это некая грамматика. Напиши парсер, который будет преобразовывать входные строки в некую структуру. Т.к. у тебя грамматика простая, у тебя будут только два типа лексем: литералы и счётчики. Для внутреннего представления вполне подойдёт упорядоченный список объектов. В списке будут объекты двух типов: "Литерал" (основное свойство -- "Значение") и "Счётчик" (основные свойства -- "Мин.Знач.", "Макс.Знач", "Шаг"). С этой структурой можно эффективно работать. Для разбора строк можно или написать нисходящий сканер, или взять готовый процессор регулярных выражений.
-
> Программа со встроенным експлойтом?
Спасибо за замечание. В принципе в реальности мне и нужен массив. От него откажусь, поэкономлю оперативку. Строки буду использоваться в процессе генерации. Разберусь с делами, допишу код. Выложу, может интересно кому. Там все гораздо проще, чем я думал.
-
> В принципе в реальности мне и нужен массив.
Очепятка, хотел сказать НЕ нужен
-
считали структуру... вытянули числовые значения и в двойном цыкле выполнили вывод строк.
-
ага, стоп не досмотрел троеточие (( мое решение не подходит.
-
Алгоритм, хоть и кривой, уже продуман. Разберусь с делами, выкину готовый код. Примерная суть. Анализируем строку, получаем набор констант и счетчиком, становится ясным общее число строк. Отсюда рисуем цикл, перебирая счетчики подобно разрядам чисел, затрудняюсь придумать более точную аналогию. В общем примерно так. Берем начало последнего счетчика, начинаем его увеличивать, достигли максимума? - сбрасываем на начало, и увеличиваем предпоследний счетчик. Так идем весь цикл. Обрабатывать строки, действительно, разумнее прямо внутри цикла дабы не жрать оперативку ненужными массивами.
-
Вот примерно так это выглядит.
procedure TForm1.Button1Click(Sender: TObject);
var
fullstrnum: integer; i,ii,j,ostatok: integer;
firststring: string; secondstring: string; counters: integer; firstconst: array of string; secondconst: array of string; minstring: array of string; maxstring: array of string; minnum: array of integer; maxnum: array of integer; nownum: array of integer; firstitem: string; seconditem: string; begin
firststring:=Edit1.Text;
secondstring:=Edit2.Text;
counters:=-1;
SetLength(firstconst,1);
SetLength(secondconst,1);
SetLength(minstring,1);
SetLength(maxstring,1);
SetLength(minnum,1);
SetLength(maxnum,1);
ii:=1;
while ii<=length(firststring) do begin if firststring[ii]='['then begin ii:=ii+1; counters:=counters+1; SetLength(firstconst,(Length(firstconst)+1)); firstconst[counters+1]:='';
SetLength(minstring,(Length(minstring)+1));
SetLength(maxstring,(Length(maxstring)+1));
SetLength(minnum,(Length(minnum)+1));
SetLength(maxnum,(Length(maxnum)+1));
while firststring[ii]<>'-' do begin minstring[counters]:=minstring[counters]+firststring[ii];
ii:=ii+1;
end;
minnum[counters]:=StrToInt(minstring[counters]); ii:=ii+1; while firststring[ii]<>']' do begin maxstring[counters]:=maxstring[counters]+firststring[ii];
ii:=ii+1;
end;
maxnum[counters]:=StrToInt(maxstring[counters]); ii:=ii+1; end else begin firstconst[counters+1]:=firstconst[counters+1]+firststring[ii];
ii:=ii+1;
end;
end;
SetLength(secondconst,(Length(firstconst)));
ii:=1;
j:=0;
secondconst[j]:='';
while ii<=length(secondstring) do begin if secondstring[ii]<>'[' then begin
secondconst[j]:=secondconst[j]+secondstring[ii];
ii:=ii+1;
end
else begin
j:=j+1;
secondconst[j]:='';
ii:=ii+2;
end;
end;
fullstrnum:=1;
for i:=0 to counters do fullstrnum:=fullstrnum*(maxnum[i]-minnum[i]+1);
SetLength(nownum,(counters+1));
for i:=0 to (fullstrnum-1) do begin
firstitem:='';
seconditem:='';
ostatok:=i;
for ii:=0 to counters do begin
nownum[ii]:=ostatok;
for j:=(ii+1) to counters do nownum[ii]:=trunc(nownum[ii]/(maxnum[j]-minnum[j]+1));
for j:=(ii+1) to counters do ostatok:=ostatok-nownum[ii]*(maxnum[j]-minnum[j]+1);
end;
for ii:=0 to counters do firstitem:=firstitem+firstconst[ii]+IntToStr(nownum[ii]+minnum[ii]);
firstitem:=firstitem+firstconst[counters+1];
for ii:=0 to counters do seconditem:=seconditem+secondconst[ii]+IntToStr(nownum[ii]+minnum[ii]);
seconditem:=seconditem+secondconst[counters+1];
Memo1.Lines.Add(firstitem));
Memo1.Lines.Add(seconditem));
end;
end;
Думаю, много лишних движений, но работает.
-
Еще пару строк напоследок по сути. Если, вдруг, кому-то станет интересно. Задача оказалось чисто алгоритмической. В первую, когда взгляд зацепляется за счетчики, руки тянутся написать кучу циклов, но вот число то этих циклов заранее и неизвестно. Для меня проблема была отойти от этого подхода, и понять, что цикл на самом деле один. А счетчики, это своего рода разряды, заранее нам уже известного числа. И задача заключается в том, чтобы внутри одного цикла разбить текущее значение переменной цикла на эти разряды. В итоге все просто.
Да и еще, данный код не совсем соответствует условием. А именно, для счетчика [01-10] он выдаст первым значением 1, а не 01, но, думаю, добавить лишний нолик, где это необходимо, уже не проблема.
|