Конференция "Начинающим" » Получение массива строк из шаблона со счетчиками [D7, WinXP]
 
  • lazy BEGINner © (13.08.11 20:24) [0]
    Есть строка-шаблон задаваяемая в виде:
    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

    Обе строки задаются пользователем и поэтому число счетчиков заранее неизвестно.
    Как бы поизящнее решить задачку.
  • Sha © (13.08.11 22:31) [1]
    А не изящно уже решил?
  • lazy BEGINner © (13.08.11 22:42) [2]

    > А не изящно уже решил?

    Не изящно можно было бы попробовать, но получится через такую ж, что не хотелось бы даже пытаться, тем более что чувствуется, что есть простое и красивое решение. Просто я до него не могу пока дойти.
  • Jeer © (13.08.11 22:47) [3]

    > Просто я до него не могу пока дойти.


    "Иди, да и воздастся"
  • lazy BEGINner © (14.08.11 00:02) [4]

    > "Иди, да и воздастся"

    буду пока пробовать решать, как получится
  • DiamondShark © (15.08.11 13:01) [5]

    > Необходим код, результатом которого станут два массива строк.

    Программа со встроенным експлойтом?
    Скромный шаблон
    a[1-100]b[1-100]c[1-100]


    прородит массив из 1000000 строк.


    > Как бы поизящнее решить задачку.

    Твои шаблоны -- это некая грамматика. Напиши парсер, который будет преобразовывать входные строки в некую структуру. Т.к. у тебя грамматика простая, у тебя будут только два типа лексем: литералы и счётчики.
    Для внутреннего представления вполне подойдёт упорядоченный список объектов. В списке будут объекты двух типов: "Литерал" (основное свойство -- "Значение") и "Счётчик" (основные свойства -- "Мин.Знач.", "Макс.Знач", "Шаг").
    С этой структурой можно эффективно работать.

    Для разбора строк можно или написать нисходящий сканер, или взять готовый процессор регулярных выражений.
  • lazy BEGINner © (17.08.11 16:48) [6]

    > Программа со встроенным експлойтом?

    Спасибо за замечание.
    В принципе в реальности мне и нужен массив.
    От него откажусь, поэкономлю оперативку.
    Строки буду использоваться в процессе генерации.
    Разберусь с делами, допишу код.
    Выложу, может интересно кому.
    Там все гораздо проще, чем я думал.
  • lazy BEGINner © (17.08.11 17:09) [7]

    > В принципе в реальности мне и нужен массив.

    Очепятка, хотел сказать НЕ нужен
  • Oleg_teacher (17.08.11 19:07) [8]
    считали структуру... вытянули числовые значения и в двойном цыкле выполнили вывод строк.
  • Oleg_teacher (17.08.11 19:09) [9]
    ага, стоп не досмотрел троеточие (( мое решение не подходит.
  • lazy BEGINner © (18.08.11 01:52) [10]
    Алгоритм, хоть и кривой, уже продуман.
    Разберусь с делами, выкину готовый код.
    Примерная суть.
    Анализируем строку, получаем набор констант и счетчиком,
    становится ясным общее число строк.
    Отсюда рисуем цикл, перебирая счетчики подобно разрядам чисел, затрудняюсь придумать более точную аналогию.
    В общем примерно так.
    Берем начало последнего счетчика, начинаем его увеличивать,
    достигли максимума? - сбрасываем на начало, и увеличиваем предпоследний счетчик. Так идем весь цикл.
    Обрабатывать строки, действительно, разумнее прямо внутри цикла дабы не жрать оперативку ненужными массивами.
  • lazy BEGINner © (19.08.11 20:18) [11]
    Вот примерно так это выглядит.

    procedure TForm1.Button1Click(Sender: TObject);
    var
     fullstrnum: integer; //Общее число строк
     i,ii,j,ostatok: integer;
     firststring: string; //Шаблон 1
     secondstring: string; //Шаблон 2
     counters: integer; //Число счетчиков
     firstconst: array of string; //Массив констант 1
     secondconst: array of string; //Массив констант 2
     minstring: array of string; //Массив минимумов в строковом виде
     maxstring: array of string; //Массив максимумов в строковом виде
     minnum: array of integer; //Массив минимумов в целочисленном виде
     maxnum: array of integer; //Массив максимумов в целочисленном виде
     nownum: array of integer; //Массив текущих значений счетчиков при переборе
     firstitem: string; //Строка 1
     seconditem: string; //Строка 2
    begin
     //Обрабатываем данные
     firststring:=Edit1.Text;
     secondstring:=Edit2.Text;
     //Разбиение шаблонов 1 и 2 на константы и счетчики
     counters:=-1;
     SetLength(firstconst,1);
     SetLength(secondconst,1);
     SetLength(minstring,1);
     SetLength(maxstring,1);
     SetLength(minnum,1);
     SetLength(maxnum,1);
     ii:=1;
     //Разбиваем 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;
     //Разбиваем 2 шаблон
     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];

       //Строки получены. Можно с ними работать (здесь просто вывод в memo).
       Memo1.Lines.Add(firstitem));
       Memo1.Lines.Add(seconditem));
     end;
    end;                  


    Думаю, много лишних движений, но работает.
  • lazy BEGINner © (21.08.11 01:36) [12]
    Еще пару строк напоследок по сути. Если, вдруг, кому-то станет интересно.
    Задача оказалось чисто алгоритмической.
    В первую, когда взгляд зацепляется за счетчики, руки тянутся написать кучу циклов, но вот число то этих циклов заранее и неизвестно. Для меня проблема была отойти от этого подхода, и понять, что цикл на самом деле один. А счетчики, это своего рода разряды, заранее нам уже известного числа. И задача заключается в том, чтобы внутри одного цикла разбить текущее значение переменной цикла на эти разряды. В итоге все просто.

    Да и еще, данный код не совсем соответствует условием. А именно, для счетчика [01-10] он выдаст первым значением 1, а не 01, но, думаю, добавить лишний нолик, где это необходимо, уже не проблема.
 
Конференция "Начинающим" » Получение массива строк из шаблона со счетчиками [D7, WinXP]
Есть новые Нет новых   [119073   +39][b:0][p:0.004]