LINUX.ORG.RU

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

 , ,


3

2

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

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

Для 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';

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

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

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

#!/usr/bin/env python3

data = (
    ("шлакоблок", "окунь"),
    ("папа", "папаха"),
    ("карусель", "сельдь"),
    ("спорткар", "карась"),
    ("форель", "рельса"),
)

for incoming_pair in data:

    first_word, second_word = incoming_pair[0], incoming_pair[1]

    results = []

    for index in range(len(second_word)):

        if first_word[-index:] == second_word[:index]:
            results = first_word[:-index] + second_word

    print(
        '{input}: "{output}"'.format(
            input=" + ".join(['"{}"'.format(i) for i in incoming_pair]),
            output="".join(results),
        )
    )
kompospec ()
Последнее исправление: kompospec (всего исправлений: 1)
Ответ на: комментарий от kompospec
import sys
for line in sys.stdin:
    first, second = line.replace('+', '').split()
    best = next(i for i in range(0, len(first)) if second.startswith(first[i:]))
    print(first[:best] + second) if best is not None else print(first + second)

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

kompospec ()
Последнее исправление: kompospec (всего исправлений: 1)
Ответ на: комментарий от kompospec
#!/usr/bin/perl
 
$_= "шлакоблок + окунь";
#$_= "папа + папаха";

($u1,$u2) = split/[+\s]+/;

for(split(//,$u2)){
  $v .= $_;
  if ($u1 =~ /$v$/) {$v1=$v}  
  }

$u2 =~ s/$v1//;

print "$u1$u2";

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

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

Rust. Для указанных примеров работает. Для всего остального - условие слишком жидкое.

use std::io::{stdin, BufRead, BufReader};

fn main() {
    'outter: for line in BufReader::new(stdin()).lines() {
        let line = line.expect("Error while reading a line").replace('+', " ");
        let (first, second) = line
            .split_once(char::is_whitespace)
            .map(|(s1, s2)| (s1, s2.trim_start()))
            .expect("Error while extracting strings");

        for i in 0..first.len() {
            if second.as_bytes().starts_with(&first.as_bytes()[i..]) {
                println!("{}{}", &first[..i], second);
                continue 'outter;
            }
        }

        println!("{}{}", first, second);
    }
}

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

kompospec ()

Не знаю как сейчас, а ранее Perl имел весьма эффективный API для работы с текстом.

Регулярки для высоконагруженных алгоритмов не применял бы.

Perl не нужно противопоставлять Си  

Имеется ниша задача в которых Perl целесообразно использовать.
Впрочем это суждение годится для любого языка программирования.

Для Perl написаны тонны API.
Для Си - мегатонны.

Еще раз акцентирую на то, что выбор языка программирования для разработки алгоритмов зависит от контекста задач и требования к эффективности использования алгоритма …

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

Вы говорите прописные истены. У нас есть конкретная задача:

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

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

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

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

Нужно проверить скорость её выполнения для различных языков. Есть уже решения для Перл и для С++ и для Питона.

kompospec ()
Ответ на: комментарий от kompospec
vadim@aquila:/tmp/111$ cat 1.txt 
шлакоблок + окунь
папа + папаха
карусель + сельдь
спорткар + карась
форель + рельса
хрен + нога
бугага + несовпало
ааа + бб
vadim@aquila:/tmp/111$ cat 1.rb 
STDIN.read.lines do |line|
    a, b = line.strip.split(/[ +]+/)
    i = [a.size, b.size].min
    while i > 0 do
        break if b.start_with? a[a.size - i .. -1]
        i -= 1
    end
    puts "#{a} + #{b} = #{a}#{b[i..-1]}"
end
vadim@aquila:/tmp/111$ ruby 1.rb < 1.txt 
шлакоблок + окунь = шлакоблокунь
папа + папаха = папаха
карусель + сельдь = карусельдь
спорткар + карась = спорткарась
форель + рельса = форельса
хрен + нога = хренога
бугага + несовпало = бугаганесовпало
ааа + бб = ааабб
vadim@aquila:/tmp/111$ 

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

kompospec ()
Ответ на: комментарий от kompospec
<?php
while($line = fgets(STDIN)){
    [$a, $b] = preg_split('/[ +]+/', trim($line));
    $i = min(mb_strlen($a), mb_strlen($b));
    while ($i > 0) if (str_starts_with($b, mb_substr($a, -$i))) break; else $i--;
    $c = mb_substr($b, $i); echo "$a + $b = $a$c\n";
}

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

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

Вы говорите прописные истены.

Зачем проверять?
И без проверки сразу можно сказать, что на Си можно разработать эффективный алгоритм.
Да, текст кода будет содержать больше строк чем на Perl, но будет более эффективным.

Все давно проверено.  

Еще раз акцентирую на то, что Perl имеет высокоэффективный API для работы с текстом и для многих задач его можно использовать …

anonymous ()
Ответ на: комментарий от kompospec
// let str = 'шлакоблок + окунь';
// let str = 'спорткар + карась';
// let str = ' папа  +  папаха ';
let str = 'карусель + сельдь';

let [str1, str2] = str.split('+').map(el => el.replace(/\s/g, ''));

let res = str1.replace(str1.split('').filter((el, i) => str2.includes(str1.slice(i))).join(''), '').concat(str2)

console.log(res);

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

kompospec ()
Ответ на: комментарий от kompospec
module Main where
import Data.List
test xs ys = xs ++ drop (last $ findIndices (`isSuffixOf` xs) $ inits ys) ys
main = getLine >>= \xs -> getLine >>= \ys -> putStrLn (test xs ys)
[a, b] = 'карусель + сельдь'.split('+').map(e => e.replace(/\s/g, ''));
console.log(a.replace(a.split('').filter((e, i) => b.includes(a.slice(i))).join(''), '').concat(b))

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

kompospec ()
Последнее исправление: kompospec (всего исправлений: 1)
Ответ на: комментарий от kompospec
((x,y) => alert(x.concat(y.replace(x.split("").reduce(([xP, p], v) => v === y[p] ? [xP + v, p + 1] : [xP, p], ["", 0])[0], ""))))(prompt("слово раз"), prompt("слово два"))


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

kompospec ()
Ответ на: комментарий от kompospec
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class FunStringJoiner {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNextLine()) {
            String arg = scanner.nextLine();

            List<String> words = Stream.of(arg.split("\\+")).map(String::trim).collect(Collectors.toList());
            if (words.size() == 2) {
                String substr = "";
                int len = words.get(0).length();
                for (int pos = len; pos > 0; pos--) {
                    String seq = words.get(0).substring(len - pos, len);
                    if (words.get(1).startsWith(seq)) {
                        substr = seq;
                        break;
                    }
                }
                System.out.printf("%s + %s = %s%s\n", words.get(0), words.get(1), words.get(0), words.get(1).replace(substr, ""));
            }
        }
    }
}

https://www.linux.org.ru/forum/development/16616396?cid=16617752
kompospec ()
Ответ на: комментарий от kompospec
import Data.List

joinPref s1 s2 = noPref s1 ++ s2
    where noPref [] = []
          noPref (c:s) | (c:s) `isPrefixOf` s2 = []
                       | otherwise = c : noPref s
                       
solution s = joinPref s1 (tail s2)
    where (s1, s2) = break (=='+') s

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

kompospec ()
Ответ на: комментарий от kompospec
perl сливает даже жабоподобному шарпу, получается?

List<string> strings = Console.ReadLine().Split('+').Select(s => s.Trim()).ToList();
var counter = 0;
for (int i = 1; i <= strings.Min(s=>s.Length); i++)
    if(strings[0].Substring(strings[0].Length-i)==strings[1].Substring(0, i))
        counter = i;
Console.WriteLine("{0}{1}", strings[0], strings[1].Substring(counter));


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

kompospec ()
Ответ на: комментарий от kompospec
Ок, на наших, так на наших. Сплит делать не интересно, зато покажу как обойтись без подстрок (и без скобочек, конечно).

def main
    #*s1 @string "шлакоблок"
    #*s2 @string "окунь"
    *s1 @string "папа"
    *s2 @string "папаха"
    *len1 @int @size s1
    *len2 @int @size s2
    *i @int 0
    *j @int 0
    for
        if i len1
            break
        if j len2
            break
        if s1|i s2|j
            j + 1
        else
            j = 0
        i + 1
    s2 @erase 0 j
    s1 + s2
    @print s1


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

kompospec ()
Ответ на: комментарий от kompospec
Ещё немного синтаксических чудес принёс вам, добрые мои друзья:

my (\x, \y) = < форель рельса >;

( 0 .. * )
    .map({ substr( x, 0, $_ ) ~ y })
    .first({ .starts-with: x })
    .put

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

kompospec ()
Ответ на: комментарий от kompospec
По условиям задачи правильнее только будет так:

> for $*IN.lines {
    if .words.elems != 2 { say "I want two words..."; next }
    my ($x, $y) = |.words;
    say $y.comb.produce(&[~]).map({ $x.ends-with($_) ?? $x ~ $y.substr(.chars) !! Empty }).max // "$x$y"
}
о к
ок
шлакоблок окунь
шлакоблокунь
форель рельса
форельса
папа папаха
папаха
^CPressed CTRL-c, press CTRL-c again to exit

5 строчек с вводом-выводом, всё по канонам Супер-пупер языков.

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

kompospec ()
Ответ на: комментарий от kompospec
На супер-пупер языках достаточно одной строчки.

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.13.0.0.0

SQL> with x as (select column_value str from table(sys.odcivarchar2list('шлакоблок + окунь', 'папа + папаха', 'карусель + сельдь', 'спорткар + карась', 'форель + рельса'))),words as (select substr(str, 1, instr(str, ' + ') - 1) w1, substr(str, instr(str, ' + ') + length(' + ')) w2 from x) select w1, w2, res from (select w1, w2, res, lvl, max(lvl) over(partition by w1, w2) maxlvl from (select w1, w2, substr(w1, 1, length(w1) - lvl) || w2 res, lvl from (select w.w1, w.w2, l.* from words w, lateral(select  level lvl, substr(w.w2, 1, level) w1s, substr(w.w1, length(w.w1) - level + 1) w2s from dual connect by level <= length(w.w2)) l) where w1s = w2s)) where lvl = maxlvl;

W1                   W2                   RES                                     
-------------------- -------------------- ----------------------------------------
карусель             сельдь               карусельдь                              
папа                 папаха               папаха                                  
спорткар             карась               спорткарась                             
форель               рельса               форельса                                
шлакоблок            окунь                шлакоблокунь  

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

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

У sed по-моему флага для не жадных регулярок нет, поэтому для пары "авантюристка авантюрность" получим максимум "тюр", на питоне это должно выглядеть так: r'\w*?(\w{3,})\w* \w*\1\w*', тогда для "авантюристка авантюрность" получим "авантюр".

anonymous ()
Ответ на: комментарий от anonymous
$ echo 'авантюристка авантюрность' | sed -E 's/(.+)[ +]+\1/\1/'
авантюристкавантюрность

Вроде норм. Тут же не просто максимальную подстроку ищут, а максимальную подстроку в конце одного слова, совпадающую с подстрокой в начале второго слова. Порядок слов имеет значение.

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

Вы упорно не хотите видеть задание для этого Топика. Оно другое совсем:

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

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

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

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

kompospec ()
Ответ на: комментарий от kompospec
Ок, выступлю на С++, одна строка:

using namespace std;int main(int a, char *v[]){for(int i=0;i<a/3;i++){int index=1+i*3;auto l=string(v[index]);auto r=string(v[index+2]);for(int x=0;x<l.length()-2;x+=2){if(l.compare(r.substr(0,l.length()))==0){cout<<r<<endl;break;}string o="";o+=l.substr(0,x+2);o+=r;auto c=o.substr(0,l.length());if(l.compare(c)==0){cout<<o<<endl;break;}}}};

Проверяем

clang++ -include"iostream" minifiedMax.cpp && ./a.out шлакоблок + окунь петух + тухлятина дырявый + сарай папа + папаха

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

kompospec ()
Ответ на: комментарий от kompospec
    Давай я за джавистов скажу.

Лови извращенца! Вот jshell чтобы на классы строки не тратить

//usr/bin/env jshell -J-Darg="$1" --execution local "$0"; exit $?
String[] str = System.getProperty("arg").split("\\s*\\+\\s*");
System.out.println(java.util.stream.IntStream.iterate(Math.min(str[0].length(), str[1].length()), len -> len - 1).filter(len -> str[0].substring(str[0].length() - len, str[0].length()).equals(str[1].substring(0, len))).mapToObj(len -> System.getProperty("arg") + "=" + str[0] + str[1].substring(len, str[1].length())).findFirst().orElseGet(() -> str[0] + str[1]));
/exit

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

kompospec ()
Ответ на: комментарий от kompospec
Та тут даже баш в 140 символов укладывется

while read a;do b=${a%+*};c=${a#*+};i=0;while [ $i -lt ${#b} ] && [[ ! ${c} == ${b:i}* ]];do ((i++));done;echo "$a=${b:0:i}$c";done < input

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

kompospec ()