Рандомизация текста

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by kokoulin, 1 Nov 2011.

  1. kokoulin

    kokoulin Member

    Joined:
    8 Jan 2011
    Messages:
    64
    Likes Received:
    5
    Reputations:
    5
    основной принцип работы твой, регулярка там используется только для удаления куска который обработали ибо лень уже было доделывать/
    кусок с регуляркой можно заменить на:

    //string rep = Convert.ToString(rx.Match(message));
    message = message.Replace(random, word);
     
  2. B0ri$ka

    B0ri$ka Banned

    Joined:
    1 Jul 2011
    Messages:
    33
    Likes Received:
    2
    Reputations:
    0
    он вообще-то несколько другой способ описывал. с введением кучей дополнительных переменных и обработкой строки "через Ж"
     
  3. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    ув. бориска, не шарите - марш на выход.
    в том классе "regEx" который Вы так нахваливаете объявляется гораздо больше переменных (не говоря уже о времени на создание объекта (а это самая затратная по времени процедура. хотя вряд ли Вам это известно)), которые Вам для выполнения простейшей (!!!) задачи просто не нужны. расход памяти ГОРАЗДО выше, чем при объявлении 2 (двух) переменных
     
  4. X-rus

    X-rus Member

    Joined:
    22 Dec 2010
    Messages:
    88
    Likes Received:
    22
    Reputations:
    4
    Вот моя реализация на C#, похожая на то, что предложил xophet, только у меня без копирования и вставок + дополнительные проверки. Работает она, конечно, быстрее, но в данном случае нужно выбирать, стоит ли оптимизировать. Если данный метод будет работать с большим текстом (тысячи символов), либо если будет очень часто вызываться, то тогда стоит задуматься об оптимизации, так как увеличение скорости может быть существенным. Иначе проще использовать регулярные выражения.

    Пример такой оптимизации:
    Code:
            private static Random _rand = new Random();
            ***
            private static string Generate(string str)
            {
                int begPosition = -1;
                List<int> separatorsPos = new List<int>();
                StringBuilder strBuilder = new StringBuilder(str);
    
                for (int i = 0; i < strBuilder.Length; ++i)
                {
                    if (strBuilder[i] == '{')
                    {
                        begPosition = i;
                    }
                    else if (strBuilder[i] == '}' && begPosition != -1)
                    {
                        for (int j = begPosition + 1; j < i; ++j)
                        {
                            if (strBuilder[j] == '|')
                            {
                                separatorsPos.Add(j);
                            }
                        }
    
                        int offset = strBuilder.Length;
                        int randValueIndex = _rand.Next(0, separatorsPos.Count + 1);
    
                        if (separatorsPos.Count == 0)
                        {
                            // Удаляем скобку после x: {x} = {x
                            strBuilder.Remove(i, 1);
                            // Удаляем скобку перед x: {x = x
                            strBuilder.Remove(begPosition, 1);
                        }
                        else if (randValueIndex == 0)
                        {
                            // Удаляем всё, что идёт после x: {x|1|2|..n} = {x
                            strBuilder.Remove(separatorsPos[0], i - separatorsPos[0] + 1);
                            // Удаляем скобку перед x: {x = x
                            strBuilder.Remove(begPosition, 1);
                        }
                        else if (randValueIndex == separatorsPos.Count)
                        {
                            // Удаляем скобку после x: {1|2|..n|x} = {1|2|..n|x
                            strBuilder.Remove(i, 1);
                            // Удаляем всё, что идёт перед x: {1|2|..n|x = x
                            strBuilder.Remove(begPosition, separatorsPos[randValueIndex - 1] - begPosition + 1);
                        }
                        else
                        {
                            // Удаляем всё, что идёт после x: {..n|x|..n} = {..n|x
                            strBuilder.Remove(separatorsPos[randValueIndex], i - separatorsPos[randValueIndex] + 1);
                            // Удаляем всё, что идёт перед x: {..n|x = x
                            strBuilder.Remove(begPosition, separatorsPos[randValueIndex - 1] - begPosition + 1);
                        }
    
                        begPosition = -1;
                        separatorsPos.Clear();
    
                        offset -= strBuilder.Length;
                        i -= offset;
                    }
                }
    
                return strBuilder.ToString();
            }
     
  5. B0ri$ka

    B0ri$ka Banned

    Joined:
    1 Jul 2011
    Messages:
    33
    Likes Received:
    2
    Reputations:
    0
    Я представляю, насколько сложно устроен и трудозатратен регэксп.
    Я говорю о том, что программист не должен сам реализовывать подобную сложность, если она уже реализована.
    Если что-то можно записать в 3-х строчках против 30, то лучше этой простотой и воспользоваться.
    Это не критично для всяких регеров и спамеров. Мы тут не софт для космических аппаратов пишем, а менее критичные к ресурсам вещи.

    Да, и напиши-ка свой код здесь. Пусть для наглядности он здесь полежит, посмеёмся над говнокодом.
     
  6. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    Версия БЕЗ регулярок
    Code:
    function CopyRandomizeText(s:string;var open,close:Integer):string;
    begin
      Result:='';
      if (Pos('{',s)=0)or(Pos('}',s)=0) then
        Exit;
      open:=Pos('{',s);
      close:=Pos('}',s);
      Result:=Copy(s,open+1,close-open-1);
    end;
    
    function GetRandomTextFromRandomized(s:string):string;
    var DelimitedText:TStringList;
    begin
      if Pos('|',s)=0 then
      begin
        Result:=s;
        Exit;
      end;
      DelimitedText:=TStringList.Create;
      try
        ExtractStrings(['|'],[' '],PChar(s),DelimitedText);
        Result:=DelimitedText[Random(DelimitedText.Count)];
      finally
        DelimitedText.Free;
      end;
    end;
    
    function GetRandomTextFromRandomized(s:string):string;
    var DelimitedText:TStringList;
    begin
      if Pos('|',s)=0 then
      begin
        Result:=s;
        Exit;
      end;
      DelimitedText:=TStringList.Create;
      try
        ExtractStrings(['|'],[' '],PChar(s),DelimitedText);
        Result:=DelimitedText[Random(DelimitedText.Count)];
      finally
        DelimitedText.Free;
      end;
    end;
    
    function ReplaceAllRandomizersInText(s:string):string;
    var tmp:string;
        open,close:Integer;
    begin
      Result:=s;
      repeat
        tmp:=CopyRandomizeText(Result,open,close);
        if tmp='' then
          Exit;
        Delete(Result,open,close-open+1);
        Insert(GetRandomTextFromRandomized(tmp),Result,open);
      until tmp='';
    end;
    
    procedure TfrmMain.btn1Click(Sender: TObject);
    var i:Integer;
        t1, t2, tf: int64;
    begin
      QueryPerformanceFrequency(tf);
      QueryPerformanceCounter(t1);
    for i:=1 to 1000 do
      begin
        ReplaceAllRandomizersInText(mmo1.Text);
        Application.ProcessMessages;
      end;
      QueryPerformanceCounter(t2);
      mmo1.text:='time = ' + floattostr((t2-t1) / tf);
    end;
    Версия с регулярками:
    Code:
    function StrReplaceOne(const Str, Str1, Str2: string): string;
    //заменяет в строке Str подстроку Str1 На строку Str2
    var
      P, L: Integer;
    begin
      Result := str;
      L := Length(Str1);
      P := Pos((Str1),(Result)); // ищем подстроку
      if P > 0 then
      begin
        Delete(Result, P, L); // удаляем ее
        Insert(Str2, Result, P); // вставляем новую
      end;
    end;
    
    function CopyRandomizeText(s:string):string;
    var reg:TRegExpr;
    begin
      reg:=TRegExpr.Create;
      try
        Result:='';
        reg.Expression:='{(.*?)}';
        if reg.Exec(s) then
          Result:=reg.Match[1];
      finally
        reg.Free;
      end;
    end;
    
    function ReplaceAllRandomizersInText(s:string):string;
    var tmp:string;
        open,close:Integer;
    begin
      Result:=s;
      repeat
        tmp:=CopyRandomizeText(Result);
        if tmp='' then
          Exit;
        StrReplaceOne(Result,'{'+tmp+'}',GetRandomTextFromRandomized(tmp))
      until tmp='';
    end;
    
    procedure TfrmMain.btn1Click(Sender: TObject);
    var i:Integer;
        t1, t2, tf: int64;
    begin
      QueryPerformanceFrequency(tf);
      QueryPerformanceCounter(t1);
    //  for i:=1 to 1000 do
      begin
        ReplaceAllRandomizersInText(mmo1.Text);
        Application.ProcessMessages;
      end;
      QueryPerformanceCounter(t2);
      mmo1.text:='time = ' + floattostr((t2-t1) / tf);
    end;
    Можете сравнить: нигде никаких задержек не ставил, все честно.
    Результаты теста на куске текста 270 КБ, по которому в 26-ти местах раскиданы соответствующие группу вида
    Code:
    {aasdas das asd asdas da|asdasdas asd|SAD|AS|DA|SD|AS|DAS|D|AS|D|ASD|AS|D|ASD|AS|D|AS|DA|SDASDAS|DAS|DA|SD|SA|DAS|DA|SD|AS|DAS|D|ASD|AS|DAS|D|AS|DAS|D}
    Версия БЕЗ РЕГУЛЯРОК (1000 итераций) = 33,37 секунды
    Версия С РЕГУЛЯРКАМИ (1 итерация) = уже больше 10ти минут
    и она все еще не выполнилась. при чем нагрузка на проц не падает ниже 50%

    P.S. Rafaello - вместо тысячи слов :))))))))))))))

    Не-а, не представляете.
    Какую такую сложность? с каких пор скопировать подстроку из строки стало "сложностью"?
    Как мы видим в обоих вариантах количество строк примерно одинаково
    Я не знаю что лично Вы тут пишете (почему-то мне кажеться, что ничего), но Вам видимо не доводилось писать тот же спамер (хотя как же могло доводиться писать, если Вы ничего не пишете, кроме 2х страниц срача), который работает в 300 потоков (открою Вам большой секрет: в моем опыте загрузка процессора не поднялась болешь 50% т.к. один поток не может грузить больше одного ядра процессора. Будь потоков два - комп бы "умер")
     
    #26 xophet, 6 Nov 2011
    Last edited: 6 Nov 2011
  7. altblitz

    altblitz Elder - Старейшина

    Joined:
    5 Jun 2009
    Messages:
    3,694
    Likes Received:
    3,149
    Reputations:
    236
    предоставлю.
    если отвечаете за свои слова,
    будьте любезны - предоставьте 50 WMZ за совет.

    не мне нужно - собакам и кошкам в приютах.
     
  8. kokoulin

    kokoulin Member

    Joined:
    8 Jan 2011
    Messages:
    64
    Likes Received:
    5
    Reputations:
    5
    1. вы это сейчас к чему?
    2. большое спасибо за вашу отзывчивость но перед вами предоставили 4 разных варианта реализации совершенно бескорыстно.
     
  9. B0ri$ka

    B0ri$ka Banned

    Joined:
    1 Jul 2011
    Messages:
    33
    Likes Received:
    2
    Reputations:
    0
    Эээээ.... Регулярки на Дельфях? Я когда-то видел это убожество в действии, да.
    Но я говорил про регулярки на .NET, которые работают там очень шустро.

    Но на код, что ты тут привёл, смотреть просто грустно. Что с регулярками, что без них.
    Такое ощущение, что на дворе 1998-й год наступил...
     
    1 person likes this.
  10. seosimf

    seosimf Member

    Joined:
    3 Mar 2011
    Messages:
    271
    Likes Received:
    44
    Reputations:
    6
    Все что нужно Regex.Replace (String, MatchEvaluator) быстро, понятно, красивооо(можно и рекурсию для вложенных иголок сделать).
    KISS.
     
  11. kokoulin

    kokoulin Member

    Joined:
    8 Jan 2011
    Messages:
    64
    Likes Received:
    5
    Reputations:
    5
    без них оказалось быстрее красивее и короче но пришлось немного подумать)
    в принципе с ними тоже хорошо смотрелось)
     
  12. altblitz

    altblitz Elder - Старейшина

    Joined:
    5 Jun 2009
    Messages:
    3,694
    Likes Received:
    3,149
    Reputations:
    236
    предоставили Вам, и за-бесплатно?

    во всём топике нашёл лишь одну правильную мессагу.
    всё остальное - "Если бы у меня был рот, то это был бы полный огород"

    --- добавлено ---
    посмотрел, что пишут в топике. тянет на двойку.
    спам - не так пишется.

    как правильно написать - "совершенно бескорыстно", за 100 WMZ ))
    скупой платит дважды, и наступает на свои грабли.
     
    #32 altblitz, 6 Nov 2011
    Last edited: 6 Nov 2011
  13. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    предоставьте аналогичные данные в .Net, посмотрим как у Вас "шустро" работает.
    Я почему-то уверен, что на аналогичном куске текста Вы не дождетесь ее выполнения.

    Ну вообще-то ночь была на дворе, тупанул. не спорю :)
    Ну Вы в курсе, что иначе повисла бы форма и время выполнения только увеличилось, да?
    P.S. к стати в случае с регулярками форма все равно повисла :)
    Это сделано исключительно ради того, чтобы в версии с регулярками меньше пришлось менять, и для наглядности того факта, что я нигде ничего не перемудрил.
    Да Вы не понимаете всю серьезность происходящего. Дождаться выполнения регулярки на куске текста не представлялось возможным, вполне возможно, что не совсем красиво написано (про regex.replace не знал, спасибо) и там еще какие-то косяки. Но регулярка-то не выполнилась за 10 минут, а одна итерация с copy-delete-insert выполнялась 0.03 секунды
    По-крайней мере я подтвердил свою точку зрения фактом. Все остальные (на данный момент) остались голословными

    Ваш код в студию.
     
    #33 xophet, 6 Nov 2011
    Last edited: 6 Nov 2011
  14. seosimf

    seosimf Member

    Joined:
    3 Mar 2011
    Messages:
    271
    Likes Received:
    44
    Reputations:
    6
    Если вы вот "это" называете красивей:
    то дальнейшая дискуссия в принципе бессмысленна.
    Зачем конкатенацию в string.Format заключать string.Format(result + message), string.Format(result + message.Remove(firstq)?
    И если такая забота о скорости то в условии while неплохо бы присвоить значения firstq.

    Вот вам приблизительный пример с Regex.Replace(String, MatchEvaluator)
    Ну куда уж мне осознать всю не серьезность ситуации, с моим то не серьезным умом.
    Насчет 10 минут ожидания на 270кб текста:
    файл ~1,1 мегабайта, 35 вхождений {aasdas das asd asdas da|asdasdas asd|SAD|AS|DA|SD|AS|DAS|D|AS|D|ASD|AS|D|ASD|AS|D|A S|DA|SDASDAS|DAS|DA|SD|SA|DAS|DA|SD|AS|DAS|D|ASD|A S|DAS|D|AS|DAS|D}.
     
    #34 seosimf, 6 Nov 2011
    Last edited: 4 Feb 2014
    2 people like this.