LINUX.ORG.RU

Говорили что Перл старый, ни на что не способный язык. Проверим?(часть 2)

 , ,


5

4

Задание на сейчас. найти максимальное вхождение одного слова в другое в СЛОВАРЕ - смотри ниже!!!

Перл - со словарём не справился;

Для C++ . - У меня перебирает весь словарь за 17 секунд;

Для JS - Около минуты. Говорили что Перл старый, ни на что не способный язык. Проверим?(часть 2) (комментарий);

Всё. Пока ничего другого, полностью рабочего нет.

Не нужно писать решение для единичных слов. Нужно - решение для словаря.

Возьмём список русских существительных, например отсюда: https://github.com/Harrix/Russian-Nouns/releases/download/v2.0/russian_nouns_v2.0.zip

Нужно найти максимальное вхождение одного слова в другое. Полные вхождения слов - не допускаются - это вроде было ясно и понятно всем. — Это задание. Это!!!


Самое простое и наглядное решение в составлении слов это:

/(\w+) \1/

Так-как даже я уже ничего не могу найти в первой части:

Говорили что Перл старый, ни на что не способный язык. Проверим?

Предлагаю собрать сюда наиболее значимые решения из 1 части.

Итак:

В начале, мы просто делали из

шлакоблок + окунь = шлакоблокунь

На разных языках. Там есть решения. Затем все стали зачем то уменьшать количество строк и символов - победил Перл - но это вообще не интересно.

Теперь, самое главное:

Говорили что Перл старый, ни на что не способный язык. Проверим?

Здесь все согласились что Перл хороший и годный язык, но С++ всё равно быстрее. В связи с этим, было предложено:

Говорили что Перл старый, ни на что не способный язык. Проверим?


Возьмём список русских существительных, например отсюда: https://github.com/Harrix/Russian-Nouns/releases/download/v2.0/russian_nouns_v2.0.zip На основе этого списка создадим новый, со всеми новыми сочетаниями, где перекрываются не менее 3 букв. Тут даже секундомером можно замерять. У меня на моем стареньком ноуте ушло несколько минут и сгенерировалось почти 40 Мбайт из одного. У Вас есть код на Перле и C++. Можете сравнить время. Так как здесь тоже работа со строками, то у Перла есть шанс.

Но потом договорились до изменения задания:

Тут ведь уже говорили - что основное время программы - это ввод и вывод. То есть в задании нужно сделать как можно меньше выводов.

Единственное что мне приходит в голову - найти максимальное вхождение одного слова в другое. —!!! Это и стало основным и новым заданием. !!!—


Эти все задачи были решены для Перл и С++

Для Перл. 3 варианта решения. Но ни одно не берёт весь словарь:

#!/usr/bin/perl

use utf8;
use open qw(:std :utf8); 

$t = time();

$| = 1;
open D, 'russian_nouns.txt';

for(0..3000) {
  $vv=<D>;
  $vv =~ s/\s+$//;
  @d = (@d, $vv);
  }

close D;
@d2 = @d;


for $v (@d){
    ++$ii; if (++$j>99){
    $t2 = time()-$t;
    print $ii." прошло $t2 секунд. $sov1 $str\n"; $j=0;}

  for $v2 (@d2) {&resh3 ()}
  
M1:  
  }
  
sub resh3 {
  
  $lv = length $v;
  $lv2 = length $v2;

  if($lv>$lv2) {
  
    for($i=$lv2; $i>1; $i--) {
      $c = substr ($v, -$i,);
      $c2 = substr ($v2, 0, $i);
      if (($c eq $c2) and ($c ne $v2) and ($c ne $v)){
          $sov = length $c;
          if ($sov>$sov1){$sov1=$sov; $str="$c = $v-$v2"}
          }
        
  
      }

  
  }
  else {
    
        for($i=$lv; $i>1; $i--) {
      $c = substr ($v2, -$i,);
      $c2 = substr ($v, 0, $i);
      if (($c eq $c2) and ($c ne $v2) and ($c ne $v)){
          $sov = length $c;
          if ($sov>$sov1){$sov1=$sov; $str="$c = $v-$v2"}
          }
        
  
      }
    
    
    
    }
  
  
}
  

sub resh1 {  
    $r=''; $l='';
    for(split(//,$v2)){
      $r .= $_;
      if ($v =~ /$r$/) {$l=$r}  
      }
    #print "$v-$l-$v2\n" if length $l>4 and $v ne $l;
    
    if ($l and ($l ne $v2) and ($l ne $v)){
    $sov = length $l;
    if ($sov>$sov1){$sov1=$sov; $str="$l - $v-$v2"}
}
}


sub resh2 {
  
    if($v ne $v2) {
    $_ = "$v $v2";
    /([^ ]*?)([^ ]*) \2/;
    
    if ($2 and ($2 ne $v2) and ($2 ne $v)){
    $sov = length $2;
    if ($sov>$sov1){$sov1=$sov; $str="$2 - $_"}

}
  }}
  

Для C++ . У меня перебирает весь словарь за 17 секунд.:

#include <iostream>
#include <fstream>
#include <ctime>
#include <string>
#include <vector>
using namespace std;

void check_combine(string &res, size_t &len, const string &s1, const string &s2)
{
    len = 0;
    for(auto &ch: s1)
    {
        if(len == s2.size())
        {
            break;
        }
        if(ch == s2.at(len))
        {
            len += 1;
        }
        else
        {
            len = 0;
        }
    }
    if(!len)
    {
        res = "";
    }
    else
    {
        string s3  {s2};
        s3.erase(0, len);
        res = s1;
        res += s3;
    }
}

void getlines(vector<string> &lines, fstream & f)
{
    string str;
    while(getline(f, str))
    {
        lines.push_back(str);
    }
}

int main()
{
    fstream inFile;
    inFile.open ("russian_nouns.txt", std::fstream::in);
    vector<string> lines;
    getlines(lines, inFile);
    size_t maxLen  {0};
    size_t rusMaxLen  {0};
    string maxRes  {""};
    time_t startTime = time(nullptr);
    size_t counter  {0};
    for(auto &s1: lines)
    {
        for(auto &s2: lines)
        {
            counter += 1;
            if(s1 == s2)
            {
                continue;
            }
            if(s1.size() < maxLen)
            {
                continue;
            }
            if(s2.size() < maxLen)
            {
                continue;
            }
            size_t len  {0};
            string res;
            check_combine(res, len, s1, s2);
            if(res == s1)
            {
                continue;
            }
            if(res == s2)
            {
                continue;
            }
            if(len > maxLen)
            {
                maxLen = len;
                rusMaxLen = maxLen / 2;
                time_t delta = time(nullptr) - startTime;
                string deltaStr  {s2};
                deltaStr.erase(len);
                maxRes = deltaStr + " - " + s1 + '-' + s2;
                cout << counter << "\t прошло: " << delta << " секунд, длина: ";
                cout << rusMaxLen << ", " << maxRes << '\n';
            }
        }
    }
    cout << "\n\nРезультат: " << rusMaxLen << ", " << maxRes << '\n';
    time_t delta = time(nullptr) - startTime;
    cout << "Полное время переборов: " << delta;
    inFile.close();
    return 0;
}


Ниже - не решения текущей задачи! Не решения. Ниже - просто выборка всех решений, на всех языках с прежней темы.

Блин. Как же сложно с людьми с недостаточным образованием. Я вот уже 6 раз написал - и всё равно будут писать про Шлокоблококунь.

php:

➜ php i.php "папа + папаха"
папаха%                                                                                                                                                                   ➜ php i.php "шлакоблок + окунь"
шлакоблокунь%                                                                                                                                                              
➜ cat i.php
<?php
for ($i = 1; $i <= mb_strlen(trim(explode('+', $argv[1])[0])) && $i <= mb_strlen(trim(explode('+',$argv[1])[1])); $i++)
    if (mb_substr(trim(explode('+', $argv[1])[0]), mb_strlen(trim(explode('+',$argv[1])[0])) - $i) === mb_substr(trim(explode('+',$argv[1])[1]), 0, $i)) 
        $j = $i;
echo (isset($j)) ?  trim(explode('+',$argv[1])[0]). mb_substr(trim(explode('+',$argv[1])[1]), $j) : 'error';

Говорили что Перл старый, ни на что не способный язык. Проверим? (комментарий)



Последнее исправление: sudopacman (всего исправлений: 25)

Предлагаю собрать сюда наиболее значимые решения из 1 части.

Пора это собирать не в темах на форуме, а в CVS, если тебе эта информация действительно важна.

Если не важна, то зачем ты вообще этим занимаешься?

apt_install_lrzsz ★★★
()

Шизоид, ты как из палаты убежал?

CryNet ★★★★★
()
Ответ на: комментарий от dimuska139

Про задание 2 летней давности? Вы правда думаете что на 14 листах той темы никто не говорил об Индексировании? Вы немножко не понимаете что такое Миллиард записей.

kompospec
() автор топика
Ответ на: комментарий от kompospec

Та тема мне сейчас не интересна. - я не буду на неё переходить.

Тема сейчас: Найти максимальное вхождение одного слова в другое. Из Словаря.

kompospec
() автор топика

ТС, ещё немного идейности и докатишься до Перл-шовинизма.

Лучше съезди, отдохни на Итальянском море (с), заодно расскажешь там про самый лучший Перл, шлакоблокуней, люди должны знать правду.

PhysShell ★★
()
Ответ на: комментарий от kompospec

ТС, интереснее будет тема «Переводчика».
В inet имеются словари для всех языков /включая Элочки/.
Опубликуйте ссылки на них и на формат их представления и общими усилиями

ПОСРАМИМ GOOGL-у /или останемся у разбитого корыта/

Тем более, что можно начать разработку с «простого» перевода с постепенным улучшением алгоритмов.
Задача будет ведь интересная …

anonymous
()
Ответ на: комментарий от kompospec

Я отвечал конкретно на вашу фразу: «было задание на перебор огромных БД. Перл не смог решить его именно по скорости». Дело тут не в Pearl, а в том, что вы пытались сделать то, что делать было неправильно: вытаскивать полностью содержимое из БД для последующей обработки. Эту задачу нужно делать прямо в БД либо обычным запросом, либо какой-нибудь хранимкой. Но вытаскивать такое количество строк из БД и потом пытаться их обработать, да ещё и с помощью Pearl - совершенно странная затея.

И при чём тут вхождения слов? Что это должно показать? Что Pearl не говно, а что-то да может? Ок - и что? Как уже верно заметили, эта задача на практике встречается очень редко, и то, что её можно реализовать на Pearl, не говорит вообще ни о чём.

dimuska139 ★★
()
Ответ на: комментарий от dimuska139

Откуда эти все выводы??? Откуда? Я уже даже не помню всех тонкостей той обработки. А вы так уверенно про это говорите. Откуда? С чего?

kompospec
() автор топика
Ответ на: комментарий от dimuska139

Тем более что там ничего не вытаскивалось - там генерировалось.

kompospec
() автор топика
Ответ на: комментарий от kompospec

Давайте эти словари. Я посмотрю. Я люблю словари парсить.

Бумеранг прилетел …

anonymous
()
Ответ на: комментарий от dimuska139

С ТС бесполезно спорить, он сейчас тебя про образование начнет спрашивать, жадность и дэвэ по дэтэ

anonymous
()
Ответ на: комментарий от demensdeum

Не мешай! Шлакоблокунь сам себя не напишет!

anonymous
()

Компостец - хватит флудить, иди работай!

anonymous
()
Ответ на: комментарий от anonymous

Я всё равно не понял, что именно доказывает решение этой задачи. Что Pearl - лаконичный? Ну ок, а дальше что?)

P.s. в своё время мне препод в универе показывал, как он на Prolog шахматы реализовал в сколько-то там строк. Круто? Да. Но, как мы видим, на Prolog пишут чаще, чем никогда.

dimuska139 ★★
()
Последнее исправление: dimuska139 (всего исправлений: 1)

Выводы к которым я пришел из прошлого треда: движки регулярных выражений которые работают за линейное время (re2 например) не поддерживают бектрекинг/бекреференсинг, со-но на них шлакоблокуня в одну регулярку не сделать. Движки регулярок которые поддерживают бектрекинг (pcre, Perl, regex_replace) по этой причине не работают за линейное время. Также в рамках одного языка (C++) было замечено что реализация regex_replace, при использовании бектрекинга в регулярке, медленее Perl, и Сишного PCRE.

demensdeum
()
Ответ на: комментарий от dimuska139

Какая разница на каком языке решена задача? Я правда не понимаю.

kompospec
() автор топика

Есть такая старая шутка: из математической логики следует, что любую программу можно сократить на одну команду. Из практики программирования известно, что хоть одна команда в программе будет с ошибкой. Т.о., соединяя теорию с практикой, получаем, что любую программу можно написать в виде единственной неработающей команды.

Это конкретно про Пёрл.

Вы, извиняюсь, тут сравниваете х* с гусиной шеей. Причём с серьёзным выражение лица. Нечем заняться? Идите учить Си и флаги компиляции gcc для оптимизации. Ничего быстрее пока не придумали.

mister_VA ★★
()
Ответ на: комментарий от kompospec

Лидером по производительности для задачи шлакоблокуня-петухлятины, среди движков которые поддерживают бектрекинг, оказался Си/C++ с использованием PCRE. Ознакомьтесь пожалуйста с бенчмарками и сравнением движков регулярных выражений например здесь: https://rust-leipzig.github.io/regex/2017/03/28/comparison-of-regex-engines/

demensdeum
()
Ответ на: комментарий от demensdeum

Блин. Ну а других языков то нет вообще? Я напостил 2 листа примеров на различных языках. Что вы всё С++, С++.

Вы других языков совсем не знаете?

kompospec
() автор топика
Ответ на: комментарий от kompospec

И не мешайте - На Дом2 новые девчёнки сейчас придут

kompospec
() автор топика
Ответ на: комментарий от kompospec

) Дело в том что все зависит от движка регулярных выражений. Например в Php используется PCRE, и он как не странно поддерживает бектрекинг, из этого можно сделать вывод что например на Rust невозможно решить шлакоблокуня-петухлятины в одну строку регулярки из-за отсутствия бектрекинга, а в php да. Но если в Rust запустить PCRE, то можно. Понимаете, страшно то что похоже язык не очень влияет на решение с регулярками, гораздо важнее какой движок регулярок используется.
Отсюда, по-видимому, происходят все мистификации по данной теме.

demensdeum
()
Последнее исправление: demensdeum (всего исправлений: 5)
Ответ на: комментарий от kompospec

Возьмём список русских существительных

В прошлом треде @Kogrom, @demensdeum и @Siborgium искали максимально длинное совпадение в паре слов из словаря.

Код Siborgium’а у меня, к сожалению, не запустился. Но последний вариант Kogrom’а отрабатывает норм.

Я написал свой вариант на чистом Си с примерно такой же логикой. Результаты с -O2:

$ time ./kogrom
...
Результат: 13, производитель - воспроизводитель-производительность
Полное время переборов: 10
./kogrom  10.31s user 0.01s system 99% cpu 10.354 total


$ time ./shlakoblokun
Max size: 13
воспроизводитель + производительность = воспроизводительность
./shlakoblokun  0.73s user 0.00s system 99% cpu 0.737 total

Меньше секунды :)

На основе этого списка создадим новый, со всеми новыми сочетаниями, где перекрываются не менее 3 букв.

А 40-мегабайтный список у меня создаётся за 23.905 total.

for(auto &ch: s1) { ... if(ch == s2.at(len)) { len += 1; } else { len = 0; } }

@Kogrom, с такой логикой программа не найдёт совпадение, например, в «словах» аааб и аабв, хотя оно есть.

Спасибо за внимание.

anonymous
()
Ответ на: комментарий от demensdeum

Именно это я и кричу тут на каждом шагу:

Регулярки используются на всех ЯП. И выучив их один раз - вы мгновенно сможете писать доволно таки сложные вещи на практически любом ЯП.

Но все тут сопротивляются и хотят программировать на С++ с битовым сдвигом вместо возведения в степень 2. - потому что это на милионную долю секунды быстрее.

kompospec
() автор топика
Ответ на: комментарий от kompospec

Но к вашему сожалению решение C/CPP + PCRE быстрее всех, для решения с бектрекингом на регулярках, мы так и не увидели замеры php + встроенный PCRE, Python + PCRE, а Perl проиграл тоже.

demensdeum
()
Последнее исправление: demensdeum (всего исправлений: 2)
Ответ на: комментарий от kompospec

на милионную долю секунды быстрее

Представь, что у тебя 1e9 итераций и вот ты уже сэкономил 15 минут.

anonymous
()
Ответ на: комментарий от kompospec

Ну значит то, что ты делаешь не особо критично. На всех только не стоит такое поведение проецировать.

anonymous
()
Ответ на: комментарий от kompospec

И то, там получалось так что запись в файл новых значений шла быстрее чем запись этих же значений в БД. (Там генерировался миллиард строк. Миллиард.)

Иначе бы всё решили внутри БД - где и место этим огромным словарям

kompospec
() автор топика
Последнее исправление: kompospec (всего исправлений: 2)

Никто такое не приводил? Лень весь тред читать

M {
    e.1 e.2 ' + ' e.2 e.3 = e.1 e.2 e.3 ;
    e.1 = e.1;
};
$ENTRY Go = <L <Card>>;
L {
   0 = ;
   e.1 = <Prout <M e.1>> <L <Card>>;
};

time cat vxod.txt | ./r.exe >vyxod.txt

real	0m7,794s
user	0m7,286s
sys	0m0,632s
anonymous
()
Ответ на: комментарий от kompospec

Вы немножко не понимаете что такое Миллиард записей

Ты тоже. Откуда бы тебе понимать с твоими сторублёвым эникейством?

WitcherGeralt ★★
()
Ответ на: комментарий от demensdeum

Лидером по производительности для задачи шлакоблокуня-петухлятины, среди движков которые поддерживают бектрекинг, оказался Си/C++ с использованием PCRE.

Да там вообще регулярки не нужны - сильно частный случай, и можно написать «ручками» гораздо более производительный код чем с использованием PCRE (который, кстати, ни в одном глазу не про «perl под капотом», а просто про перловый синтаксис регулярок). В пределе придётся параллелить чтобы успевать прожёвывать со скоростью чтения с диска, но это делается. Только вот нах никому не нужно - очередной «сферический конь в вакууме».

bugfixer ★★★★★
()
Ответ на: комментарий от kompospec

///Регулярки используются на всех ЯП.

Спорная фраза с т.з. как построения, так и содержания.

///И выучив их один раз - вы мгновенно сможете писать доволно таки сложные вещи на практически любом ЯП.

Решая задачи, для которых вообще не нужен ЯП, да.

Регулярки – метода для обработки ТЕКСТА, обработки, которая иначе именуется редактированием, т.е. поиском кусков текста и/или их изменением.

mister_VA ★★
()
Ответ на: комментарий от demensdeum

Любой кейс можно довести до полнейшего абсурда, но даже там Perl проиграет

Так здесь и кейса то нет - если правильно всё делать оно сводится к банальным memchr() + memcmp() которые убер-оптимизированы.

bugfixer ★★★★★
()
Ответ на: комментарий от demensdeum

кстати а у них разная реализация? перловые регулярки в перле реализованы хуже перловых регулярок в сях?

TDrive ★★★★★
()
Ответ на: комментарий от demensdeum

Верно, С/C++ и PCRE рвет Перл в любом из подходов.

Безусловно, но много задач не высоко нагруженных и в них скриптовые языки вполне применимы.
А так ТС зря начал «тягаться» с C/C++ …

anonymous
()
Ответ на: комментарий от anonymous

у них критерий сравнения сформулирован как «старый, ни на что не годный» ) это просто флуд с претензией на что то полезное)

TDrive ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.