LINUX.ORG.RU

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

 , , , ,


9

4

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

Задачка:

Необходимо для каждой пары слов получить новое слово, так, чтобы окончание первого совпадало с началом второго, например, шлакоблок + окунь = шлакоблокунь. Это слово надо вывести в стандартный поток вывода.Если слова возможно соединить несколькими способами, надо выбрать тот, что обеспечивает максимальную общую часть, например папа + папаха = папаха (а не папапаха). Необходимо написать последнее условие.

Я просто взял практически первое попавшаяся задание.

На Перле программа заняла 5 строк не считая ввода-вывода. С вводом-выводом - 7 строк.

А как у вас? На ваших Супер-пупер языках?

Перемещено xaizek из general

Перемещено hobbit из talks



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

Linux demensdeum-HP-Pavilion-Notebook 5.4.0-89-generic #100-Ubuntu SMP Fri Sep 24 14:50:10 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

demensdeum
()
Ответ на: комментарий от demensdeum
#!/usr/bin/perl

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

$t = time();

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

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

close D;
@d2 = @d;


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

  for $v2 (@d2) {&resh1 ()}
  
M1:  
  }
  
  #print "$sov1 $str";
  

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 - $_"}

}
  }
  
  
  }

sub resh {

  $str = $_;
  
  }

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

Там 2 решения. Вам помочь прочитать код? Спрашивайте, если что непонятно

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

perl -v This is perl 5, version 30, subversion 0 (v5.30.0) built for x86_64-linux-gnu-thread-multi

ок момент

demensdeum
()
Ответ на: комментарий от kompospec
perl test.perl 
100прошло 5 секунд. 5 атель - авансодатель-ателье
200прошло 9 секунд. 5 атель - авансодатель-ателье
300прошло 13 секунд. 5 атель - авансодатель-ателье
400прошло 17 секунд. 5 атель - авансодатель-ателье
500прошло 21 секунд. 6 бактер - азотобактер-бактериолог
600прошло 25 секунд. 6 бактер - азотобактер-бактериолог
700прошло 29 секунд. 6 бактер - азотобактер-бактериолог
800прошло 33 секунд. 6 бактер - азотобактер-бактериолог
900прошло 37 секунд. 6 бактер - азотобактер-бактериолог
1000прошло 41 секунд. 6 бактер - азотобактер-бактериолог
1100прошло 45 секунд. 6 бактер - азотобактер-бактериолог
1200прошло 49 секунд. 6 бактер - азотобактер-бактериолог
1300прошло 53 секунд. 6 бактер - азотобактер-бактериолог
1400прошло 57 секунд. 6 бактер - азотобактер-бактериолог
1500прошло 61 секунд. 6 бактер - азотобактер-бактериолог
1600прошло 65 секунд. 6 бактер - азотобактер-бактериолог
1700прошло 69 секунд. 6 бактер - азотобактер-бактериолог
1800прошло 74 секунд. 6 бактер - азотобактер-бактериолог
1900прошло 78 секунд. 6 бактер - азотобактер-бактериолог
2000прошло 82 секунд. 6 бактер - азотобактер-бактериолог
demensdeum
()
Ответ на: комментарий от kompospec

Ок, опубликуйте пожалуйста код без лишних вызовов, интерпретатору Perl будет проще

demensdeum
()
Ответ на: комментарий от demensdeum
#!/usr/bin/perl

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

$t = time();

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

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

close D;
@d2 = @d;


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

  for $v2 (@d2) {&resh2 ()}
  
M1:  
  }
  
  #print "$sov1 $str";
  

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 - $_"}

}
  }
  
  
  }

sub resh {

  $str = $_;
  
  }

kompospec
() автор топика
Ответ на: комментарий от kompospec
perl test2.perl 
100прошло 0 секунд. 5 атель - авансодатель ателье
200прошло 1 секунд. 5 атель - авансодатель ателье
300прошло 1 секунд. 5 атель - авансодатель ателье
400прошло 2 секунд. 5 атель - авансодатель ателье
500прошло 2 секунд. 6 бактер - азотобактер бактериолог
600прошло 3 секунд. 6 бактер - азотобактер бактериолог
700прошло 3 секунд. 6 бактер - азотобактер бактериолог
800прошло 3 секунд. 6 бактер - азотобактер бактериолог
900прошло 4 секунд. 6 бактер - азотобактер бактериолог
1000прошло 4 секунд. 6 бактер - азотобактер бактериолог
1100прошло 5 секунд. 6 бактер - азотобактер бактериолог
1200прошло 5 секунд. 6 бактер - азотобактер бактериолог
1300прошло 5 секунд. 6 бактер - азотобактер бактериолог
1400прошло 6 секунд. 6 бактер - азотобактер бактериолог
1500прошло 6 секунд. 6 бактер - азотобактер бактериолог
1600прошло 7 секунд. 6 бактер - азотобактер бактериолог
1700прошло 7 секунд. 6 бактер - азотобактер бактериолог
1800прошло 7 секунд. 6 бактер - азотобактер бактериолог
1900прошло 8 секунд. 6 бактер - азотобактер бактериолог
2000прошло 8 секунд. 6 бактер - азотобактер бактериолог
demensdeum
()
Ответ на: комментарий от demensdeum

??? То есть?

У меня нет пока решения на Перл без регулярок.

И почему у меня не запустился С++ ? Вообще не запустился.

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

Пока вывод только один. Регулярки на Перл - для этого - долго.

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

Хотел уточнить у вас, чем закончился эксперимент. У меня работают оба варианта, C++ запускаю так:

clang++ test.cpp -O3 -o optimizedO3 && ./optimizedO3
Perl так:
perl test2.perl
Тестовый стенд: https://support.hp.com/us-en/document/c06074117/

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

Пусть прога выдаёт чаще промежуточные результаты. Но что это нам даст - если у нас разные алгоритмы решения?

Алгоритмы решения должны быть одинаковыми.

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

Для Перла - запуск правильный. Но я запускаю прям в редакторе - в Geany

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

g++ -Wall -c «u.cpp» (в каталоге: /home//Рабочий стол/словарь)

g++ -Wall -o «u» «u.cpp» (в каталоге: /home//Рабочий стол/словарь)

Сборка прошла успешно.

Это выдаёт редактор при компиляции С++

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

Сейчас скину с промежуточным выводом, но там не как у вас, можете исправить как вам нужно

demensdeum
()
Ответ на: комментарий от kompospec
#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);
    inFile.close();
    auto i = 0;
    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;
            if (i % 1000000 == 0) {
              time_t delta = time(nullptr) - startTime;
              cout << "s1 " << s1 << endl << "s2 "<< s2 << "\t прошло: " << delta << " секунд" << endl;
            }
            i++;
            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;
    return 0;
}

Используйте флаги оптимизации O2, O3. Например g++ -O2 u.cpp && ./a.out

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

Вкачусь и я, что ли. Кресты, требуются системные вызовы open, stat и mmap. Подсчитывается длина слова в байтах / 2, а не в символах. Обычно русские буквы занимают 2 байта, отсюда деление на 2. В остальном решение полностью честное.


#include <cassert>
#include <unistd.h>
#include <iostream>
#include <string_view>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <vector>
#include <algorithm>

int main() {
    constexpr auto filename = "russian_nouns.txt";
    int file = open(filename, O_RDONLY);
    if (file < 0) {
        perror("open failed: %s");
        return EXIT_FAILURE;
    }
    struct stat statbuf;
    if (fstat(file, &statbuf)) {
        perror("fstat failed: %s");
        return EXIT_FAILURE;
    }
    auto ptr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, file, 0);
    if (ptr == MAP_FAILED) {
        perror("mmap failed: %s");
        return EXIT_FAILURE;
    }

    std::vector<const char*> newlines;
    newlines.reserve(1024 * 1024);
    {
        auto begin = reinterpret_cast<char*>(ptr);
        auto end = begin + statbuf.st_size;

        newlines.push_back(begin - 1);
        while (begin != end) {
            if (*begin == '\n') {
                newlines.push_back(begin);
            }
            ++begin;
            //begin = std::find(begin, end, '\n');
        }
        if (newlines.size() > 0 && *newlines.back() != '\n') {
            ++newlines.back();
        }
    }

    std::size_t max_common_len{ 0 };
    for (std::size_t i = 0; i + 1 < newlines.size(); ++i) {
        std::string _( newlines[i] + 1, newlines[i + 1] - newlines[i] - 1 );
        if (_.size() < max_common_len) {
            continue;
        }
        std::string_view a{ _ };
        for (std::size_t j = 0; j + 1 < newlines.size(); ++j) {
            std::string_view b( newlines[j] + 1, newlines[j + 1] - newlines[j] - 1 );
            if (newlines[i] == newlines[j] || b.size() < max_common_len) {
                continue;
            }
            auto max = std::min(a.size(), b.size());
            if (max <= max_common_len || a.ends_with(b) || b.starts_with(a)) {
                continue;
            }
            auto a_ = a;
            auto b_ = b;
            a_.remove_prefix(a.size() - max);
            b_.remove_suffix(b.size() - max);
            while (max > max_common_len) {
                if (a_.ends_with(b_)) {
                    max_common_len = max;
                    std::cout << (max / 2) << ' ' << a << " + " << b << " = " << a << b.substr(b_.size()) << '\n';
                    break;
                }
                b_.remove_suffix(1);
                --max;
            }
        }
    }
}

$ clang++ golf.cxx -std=c++2a -march=native -Wall -Wextra -Ofast
$ time ./a.out 
4 абажур + ажурность = абажурность
5 абиогенез + генезис = абиогенезис
6 авансодатель + дательница = авансодательница
9 авансодержатель + держательница = авансодержательница
11 авансодержатель + содержательность = авансодержательность
13 воспроизводитель + производительность = воспроизводительность

real	0m5.169s
user	0m5.101s
sys	0m0.026s

Твой код компилировал с такими же флагами, получаю такой выхлоп:

$ clang++ -Ofast -march=native -std=c++2a kogrom.cxx
$ time ./a.out 
417	прошло: 0 секунд, длина: 4, ажур - абажур-ажурность
878657	прошло: 0 секунд, длина: 5, генез - абиогенез-генезис
4009466	прошло: 1 секунд, длина: 6, датель - авансодатель-дательница
4061251	прошло: 1 секунд, длина: 9, держатель - авансодержатель-держательница
4093816	прошло: 1 секунд, длина: 11, содержатель - авансодержатель-содержательность
265157673	прошло: 5 секунд, длина: 13, производитель - воспроизводитель-производительность


Результат: 13, производитель - воспроизводитель-производительность
Полное время переборов: 29
real	0m28.378s
user	0m27.626s
sys	0m0.149s
Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 1)
Ответ на: комментарий от kompospec

Все и так знают что у Страуструпа толще, т.к. пока перлисты играли в код гольф, крестовики сидели и писали оптимизации компиляторов.

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

Когда Перлисты, выполнив задание, уже трахали баб на Канарах, Крестовики всё продолжали спорить о том, какую типизацию применить в данном задании. Это вроде как я даже у вас где то вычитал

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

Да я Аппалон. Спасибо. Из Греческого зала.

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

Но вот если бы вы запустили на Перл с большим количеством строк. Это здесь:

for(0..2000) {

Мне Было бы интересно. У меня тормоза начинаются (с 30000) с 30 тысяч

kompospec
() автор топика
Последнее исправление: kompospec (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.