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)

Если одна короткая строка - для вас - месево…

#!/usr/bin/perl

open D, 'vxod.txt';
open V, '>vyxod.txt';

while (<D>) {print V if s/([^+\s]*?)([^+\s]*)[\s+]+\2/$1$2/}

В этом коде нет ничего кроме регулярки. НИ-ЧЕ-ГО

Остальное - не читал - слишком много букв

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

Да вы шизанулись на пару с ТС.

lm = (wa, wb) => {for(var i=0;!!wa[i]&&!wb.startsWith(wa.slice(i));i++);return wa.slice(0,i)+wb}

Разница только в том, что этот однострочник можно расписать в несколько строк с break, комментариями и пояснениями, а его говнорегулярку — нет.

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

В этом коде нет ничего кроме регулярки. НИ-ЧЕ-ГО

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

Остальное - не читал - слишком много букв

Вот поэтому и уровень такой. Читать дятлы не любят, только по клаве долбить.

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

И какое же? В шапке треда — какой-то поток сознания и ничего конкретного. Вышеприведённый однострочник задачу построения шлакоблокуней из двух слов решает.

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

Сейчас задача на скорость уже. Вы совсем ничего читать не хотите? Тогда вам придётся говорить самому с собой.

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

Сейчас задача на скорость уже

Ну допустим.

const fs = require('fs')

function combine(nouns) {
  var nl = nouns.length, i, j, k, wa, wb, dl, maxa, maxb, maxl = 0
  for(i=0;i<nl;i++) {
    for(k=0;k<nl;k++) {
      if(i!=k) {
        wa = nouns[i]
        wb = nouns[k]
        if(wa.length > maxl && wb.length > maxl) {
          for(j=0;!!wa[j]&&!wb.startsWith(wa.slice(j));j++);
          dl = wa.length - j
          if(dl > maxl) {
            maxl = dl
            maxa = wa
            maxb = wb
          } 
        }
      }
    }
  }
  return [maxl, maxa, maxb]
}

var nouns = Object.keys(JSON.parse(fs.readFileSync('rn.json','utf-8')))

console.log('Total words:', nouns.length)

console.time('Combination time')
var res = combine(nouns)
console.timeEnd('Combination time')
console.log('Max difference:', res[0])
console.log('Word 1:', res[1])
console.log('Word 2:', res[2])
$ node shlak.js 
Total words: 55871
Combination time: 10.876s
Max difference: 20
Word 1: недисциплинированность
Word 2: дисциплинированность

И к чему весь этот цирк был?

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

Потому что ты идиот и не умеешь читать код? fs.readFileSync читает исходный файл rn.json - с того же гитхаба.

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

Добавил в код аж два условия. Такому мегапрограммисту было бы очевидно, где их надо добавить…

const fs = require('fs')

function combine(nouns) {
  var nl = nouns.length, i, j, k,
      wa, wb, dl, wal, wbl,
      maxa, maxb, maxl = 0
  for(i=0;i<nl;i++) {
    for(k=0;k<nl;k++) {
      if(i!=k) {
        wa = nouns[i]
        wb = nouns[k]
        wal = wa.length
        wbl = wb.length
        if(wal > maxl && wbl > maxl) {
          for(j=0;!!wa[j]&&!wb.startsWith(wa.slice(j));j++);
          dl = wal - j
          if(dl > maxl && dl < wbl && dl < wal) {
            maxl = dl
            maxa = wa
            maxb = wb
          } 
        }
      }
    }
  }
  return [maxl, maxa, maxb]
}

var nouns = Object.keys(JSON.parse(fs.readFileSync('rn.json','utf-8')))

console.log('Total words:', nouns.length)

console.time('Combination time')
var res = combine(nouns)
console.timeEnd('Combination time')
console.log('Max intersection:', res[0])
console.log('Word 1:', res[1])
console.log('Word 2:', res[2])

$ node shlak.js 
Total words: 55871
Combination time: 25.095s
Max intersection: 13
Word 1: воспроизводитель
Word 2: производительность
anonymous
()
Ответ на: комментарий от anonymous

Ещё одна оптимизация.

const fs = require('fs')

function combine(nouns) {
  var nl = nouns.length, i, j, k,
      wa, wb, dl, wal, wbl,
      maxa, maxb, maxl = 0
  for(i=0;i<nl;i++) {
    wa = nouns[i]
    wal = wa.length
    if(wal > maxl) {
      for(k=0;k<nl;k++) {
        if(i!=k) {
          wb = nouns[k]
          wbl = wb.length
          if(wbl > maxl) {
            for(j=0;j<wal&&!wb.startsWith(wa.slice(j));j++);
            dl = wal - j
            if(dl > maxl && dl < wbl && dl < wal) {
              maxl = dl
              maxa = wa
              maxb = wb
            } 
          }
        }
      }
    }
  }
  return [maxl, maxa, maxb]
}

var nouns = Object.keys(JSON.parse(fs.readFileSync('rn.json','utf-8')))

console.log('Total words:', nouns.length)

console.time('Combination time')
var res = combine(nouns)
console.timeEnd('Combination time')
console.log('Max intersection:', res[0])
console.log('Word 1:', res[1])
console.log('Word 2:', res[2])
$ node shlak.js 
Total words: 55871
Combination time: 10.605s
Max intersection: 13
Word 1: воспроизводитель
Word 2: производительность

Всё, утекай.

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

Господа, вам не кажется, что этому чуду в перьях место на лурке рядом с @metaprog?

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

Если ваш код не соответствует заданию - он будет рассматриваться в самом конце.

В задании, на входе - файл Словаря.

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

Ссылку на текст задания в студию, дятел.

И щас, поди, ещё что-нибудь вякнешь, что словарь в JSON не подходит, надо только в txt, да?

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

Специально для дурилки — версия с txt и параметром командной строки:

const fs = require('fs')

function combine(nouns) {
  var nl = nouns.length, i, j, k,
      wa, wb, dl, wal, wbl,
      maxa, maxb, maxl = 0
  for(i=0;i<nl;i++) {
    wa = nouns[i]
    wal = wa.length
    if(wal > maxl) {
      for(k=0;k<nl;k++) {
        if(i!=k) {
          wb = nouns[k]
          wbl = wb.length
          if(wbl > maxl) {
            for(j=0;j<wal&&!wb.startsWith(wa.slice(j));j++);
            dl = wal - j
            if(dl > maxl && dl < wbl && dl < wal) {
              maxl = dl
              maxa = wa
              maxb = wb
            } 
          }
        }
      }
    }
  }
  return [maxl, maxa, maxb]
}

var nouns = fs.readFileSync(process.argv[2], 'utf-8').split(/\s+/)

console.log('Total words:', nouns.length)

console.time('Combination time')
var res = combine(nouns)
console.timeEnd('Combination time')
console.log('Max intersection:', res[0])
console.log('Word 1:', res[1])
console.log('Word 2:', res[2])
$ node shlak.js russian_nouns.txt 
Total words: 51301
Combination time: 10.976s
Max intersection: 13
Word 1: воспроизводитель
Word 2: производительность

P.S. Perl must die.

anonymous
()
Ответ на: комментарий от anonymous
$ node shlak.js russian_nouns.txt 
Total words: 51301
Combination time: 47383.406ms
Max intersection: 13
Word 1: воспроизводитель
Word 2: производительность

Около минуты. По сравнению с С++ - долго.

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

import (
	"fmt"
	"log"
	"os"
	"time"
)

func toRunes(bs []byte) []rune {
	return []rune(string(bs))
}

func checkArgs() {
	if len(os.Args) != 2 {
		log.Fatalf(`Provide dictionary file name, like

%s <dictionary.txt>

`, os.Args[0])
	}
}

func getFile() (in []byte) {
	var err error
	if in, err = os.ReadFile(os.Args[1]); err != nil {
		log.Fatalf("opening file %s: %v", os.Args[1], err)
	}
	return
}

// a'k'a split file
func getWords(file []rune) (words [][]rune) {

	var buf []rune

	for _, r := range file {

		if r == '\n' || r == '\r' {
			if len(buf) > 0 {
				words = append(words, buf)
			}
			buf = nil // reset
			continue
		}

		buf = append(buf, r)
	}

	return
}

func getTailHeadIntersection(ar, br []rune) (hti string, i int) {

	for _, r := range ar {
		if i == len(br) {
			break
		}
		if r == br[i] {
			i += 1
			continue
		}
		i = 0
	}

	if i == 0 || i >= len(ar) || i >= len(br) {
		return "", 0
	}

	hti = string(ar[:len(ar)-i]) +
		"[" + string(ar[len(ar)-i:]) + "]" +
		string(br[i:])
	return
}

func main() {
	checkArgs()

	var (
		words = getWords(toRunes(getFile())) // [][]rune
		found string
		fln   int
	)

	// looking for an maximum head + tail intersection
	var tp = time.Now()
	for i, f := range words {
		for j, x := range words {
			if i == j {
				continue // skip the same
			}
			var hti, xln = getTailHeadIntersection(f, x)
			if xln <= fln {
				continue
			}
			found, fln = hti, xln
			// fmt.Printf("%s, %s => %s\n", string(f), string(x), hti)
		}
	}

	fmt.Printf("found: %d, %s, after %s\n", fln, found, time.Since(tp))
}
$ go run main.go russian_nouns.txt
found: 13, вос[производитель]ность, after 1m13.590062977s

Возможно gccgo даст другой результат. А может и нет. Конвертация из []byte в unicode code points вынесена за пределы измерения времени и сделана как подготовительная работа. Вероятно не будет работать корректно со словарём имеющим битые UTF-8-символы.

Кстати, что там за приз?

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

Можно конечно не заморачиваться с unicode code points как сделано у Вас в C++ примере. Но это не корректное решение. Решением быть не может.

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

Оптимизированная версия (патч)

diff --git a/main.go b/main.go
index f1673f9..d122ce6 100644
--- a/main.go
+++ b/main.go
@@ -50,7 +50,7 @@ func getWords(file []rune) (words [][]rune) {
        return
 }
 
-func getTailHeadIntersection(ar, br []rune) (hti string, i int) {
+func getTailHeadIntersection(ar, br []rune, fln int) (hti string, i int) {
 
        for _, r := range ar {
                if i == len(br) {
@@ -63,7 +63,8 @@ func getTailHeadIntersection(ar, br []rune) (hti string, i int) {
                i = 0
        }
 
-       if i == 0 || i >= len(ar) || i >= len(br) {
+       // avoid string creation to reduce GC-pressure
+       if i <= fln || i >= len(ar) || i >= len(br) {
                return "", 0
        }
 
@@ -89,8 +90,8 @@ func main() {
                        if i == j {
                                continue // skip the same
                        }
-                       var hti, xln = getTailHeadIntersection(f, x)
-                       if xln <= fln {
+                       var hti, xln = getTailHeadIntersection(f, x, fln)
+                       if xln == 0 {
                                continue
                        }
                        found, fln = hti, xln
go run main.go russian_nouns.txt
found: 13, вос[производитель]ность, after 47.591486151s
anonymous
()

И ещё вопрос. Какой теоретически оптимальный алгоритм? Перебор и всё?

anonymous
()
Ответ на: комментарий от anonymous
/(\w+) \1/

Для меня оптимально это. Но оно получается долго

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

50 сек это много.

Проверить не могу - нету у меня такого. И я как то вообще не рассматриваю этот язык

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

50 сек это много.

Если распараллелить, то 23 с. Да и железо другое ведь.

go run main.go russian_nouns.txt
found: 13, товаро[производитель]ность, after 22.964140253s, using 4 cores

Патч

diff --git a/main.go b/main.go
index d122ce6..b3c5a24 100644
--- a/main.go
+++ b/main.go
@@ -4,6 +4,8 @@ import (
 	"fmt"
 	"log"
 	"os"
+	"runtime"
+	"sync"
 	"time"
 )
 
@@ -74,18 +76,39 @@ func getTailHeadIntersection(ar, br []rune, fln int) (hti string, i int) {
 	return
 }
 
-func main() {
-	checkArgs()
+type Result struct {
+	Word   string
+	Length int
+}
+
+// get chunks
+func splitByChunks(words [][]rune, split int) (chunks [][][]rune) {
+
+	var chunkSize = (len(words) + split - 1) / split
+
+	chunks = make([][][]rune, 0, split)
+	for i := 0; i < len(words); i += chunkSize {
+		var end = i + chunkSize
+
+		if end > len(words) {
+			end = len(words)
+		}
+
+		chunks = append(chunks, words[i:end])
+	}
+	return
+}
+
+func getResult(wg *sync.WaitGroup, words [][]rune, chunk [][]rune,
+	results chan<- Result) {
+
+	defer wg.Done()
 
 	var (
-		words = getWords(toRunes(getFile())) // [][]rune
 		found string
 		fln   int
 	)
-
-	// looking for an maximum head + tail intersection
-	var tp = time.Now()
-	for i, f := range words {
+	for i, f := range chunk {
 		for j, x := range words {
 			if i == j {
 				continue // skip the same
@@ -99,5 +122,44 @@ func main() {
 		}
 	}
 
-	fmt.Printf("found: %d, %s, after %s\n", fln, found, time.Since(tp))
+	results <- Result{
+		Word:   found,
+		Length: fln,
+	}
+}
+
+func main() {
+	checkArgs()
+
+	var (
+		words = getWords(toRunes(getFile())) // [][]rune
+
+		concurrency = runtime.NumCPU()
+
+		found string
+		fln   int
+
+		chunks  = splitByChunks(words, concurrency)
+		results = make(chan Result, concurrency)
+		wg      sync.WaitGroup
+	)
+
+	// looking for an maximum head + tail intersection
+	var tp = time.Now()
+	wg.Add(concurrency)
+	for _, chunk := range chunks {
+		go getResult(&wg, words, chunk, results)
+	}
+	wg.Wait()
+
+	close(results)
+	for result := range results {
+		if result.Length <= fln {
+			continue
+		}
+		found, fln = result.Word, result.Length
+	}
+
+	fmt.Printf("found: %d, %s, after %s, using %d cores\n",
+		fln, found, time.Since(tp), concurrency)
 }

Проверить не могу - нету у меня такого. И я как то вообще не рассматриваю этот язык

sudo <package-manager> <install> go

Кстати, в параллель нашло товаро[производитель]ность.

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

Около минуты. По сравнению с С++ - долго.

А по сравнению с твоим любимым пердлом? Или не осилил весь набор из 51301 слова обработать?

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

А по сравнению с твоим любимым пердлом? Или не осилил весь набор из 51301 слова обработать?

Пердл не осилил. Сказано в начале.

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

Хотя очевидно, что Пёрдл тут не при чём. Как и любой язык программирования он делает то, что ему сказали (т.е. это не Пёрдл не осилил, а кое-кто другой).

Вообще довольно странный ТС. Тот же C++ на интрисиках даст прирост, если заморочиться. Но это же дерьмо тупое. И зачем вообще он этот тред поднял, если С++ будет очевидно быстрее. Сам по себе. Странный типчик. И ленивый. И нафига тогда прикладывал JS? Это просто нонсенс.

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

Ещё одна версия с параллельной обработкой даёт 21с.

package main

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"sync"
	"time"
)

func toRunes(bs []byte) []rune {
	return []rune(string(bs))
}

func checkArgs() {
	if len(os.Args) != 2 {
		log.Fatalf(`Provide dictionary file name, like

%s <dictionary.txt>

`, os.Args[0])
	}
}

func getFile() (in []byte) {
	var err error
	if in, err = os.ReadFile(os.Args[1]); err != nil {
		log.Fatalf("opening file %s: %v", os.Args[1], err)
	}
	return
}

// a'k'a split file
func getWords(file []rune) (words [][]rune) {

	var buf []rune

	for _, r := range file {

		if r == '\n' || r == '\r' {
			if len(buf) > 0 {
				words = append(words, buf)
			}
			buf = nil // reset
			continue
		}

		buf = append(buf, r)
	}

	return
}

func getTailHeadIntersection(ar, br []rune, fln int) (hti string, i int) {

	for _, r := range ar {
		if i == len(br) {
			break
		}
		if r == br[i] {
			i += 1
			continue
		}
		i = 0
	}

	// avoid string creation to reduce GC-pressure
	if i <= fln || i >= len(ar) || i >= len(br) {
		return "", 0
	}

	hti = string(ar[:len(ar)-i]) +
		"[" + string(ar[len(ar)-i:]) + "]" +
		string(br[i:])
	return
}

type Result struct {
	Word   string
	Length int
}

func getResult(wg *sync.WaitGroup, words [][]rune, input <-chan []rune,
	results chan<- Result) {

	defer wg.Done()

	var (
		found string
		fln   int
	)
	for f := range input {
		for _, x := range words {
			var hti, xln = getTailHeadIntersection(f, x, fln)
			if xln == 0 {
				continue
			}
			found, fln = hti, xln
			// fmt.Printf("%s, %s => %s\n", string(f), string(x), hti)
		}
	}

	results <- Result{
		Word:   found,
		Length: fln,
	}
}

func main() {
	checkArgs()

	var (
		words  = getWords(toRunes(getFile())) // [][]rune
		toFind = make(chan []rune, len(words))

		concurrency = runtime.NumCPU()

		found string
		fln   int

		results = make(chan Result, concurrency)
		wg      sync.WaitGroup
	)

	for _, word := range words {
		toFind <- word
	}
	close(toFind)

	// looking for an maximum head + tail intersection
	var tp = time.Now()
	wg.Add(concurrency)
	for i := 0; i < concurrency; i++ {
		go getResult(&wg, words, toFind, results)
	}
	wg.Wait()

	close(results)
	for result := range results {
		if result.Length <= fln {
			continue
		}
		found, fln = result.Word, result.Length
	}

	fmt.Printf("found: %d, %s, after %s, using %d cores\n",
		fln, found, time.Since(tp), concurrency)
}

И находит дело[производитель]ность на этот раз.

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

эх, столько бы усилий на решение каких-то реальных проблем в программах

Пожалуйста, определение реальности проблемы.

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

Ну и я добавляю маленькую оптимизацию и получаю 3-4с на 4 ядрах. С++ не может сосать так глубоко. Посему у него скорее всего неверный алгоритм. Лишённый логических оптимизаций.

package main

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"sync"
	"time"
)

func toRunes(bs []byte) []rune {
	return []rune(string(bs))
}

func checkArgs() {
	if len(os.Args) != 2 {
		log.Fatalf(`Provide dictionary file name, like

%s <dictionary.txt>

`, os.Args[0])
	}
}

func getFile() (in []byte) {
	var err error
	if in, err = os.ReadFile(os.Args[1]); err != nil {
		log.Fatalf("opening file %s: %v", os.Args[1], err)
	}
	return
}

// a'k'a split file
func getWords(file []rune) (words [][]rune) {

	var buf []rune

	for _, r := range file {

		if r == '\n' || r == '\r' {
			if len(buf) > 0 {
				words = append(words, buf)
			}
			buf = nil // reset
			continue
		}

		buf = append(buf, r)
	}

	return
}

func getTailHeadIntersection(ar, br []rune, fln int) (hti string, i int) {

	// it should be here, not in loop, but moved to the loop
	// to speed up it

	// // avoid the loop, if there is an already known intersection longer
	// // then a word of given
	// if fln > 0 && (len(ar) <= fln+1 || len(br) <= fln+1) {
	// 	return // "", 0
	// }

	for _, r := range ar {
		if i == len(br) {
			break
		}
		if r == br[i] {
			i += 1
			continue
		}
		i = 0
	}

	// avoid string creation to reduce GC-pressure
	if i <= fln || i >= len(ar) || i >= len(br) {
		return "", 0
	}

	hti = string(ar[:len(ar)-i]) +
		"[" + string(ar[len(ar)-i:]) + "]" +
		string(br[i:])
	return
}

type Result struct {
	Word   string
	Length int
}

func getResult(wg *sync.WaitGroup, words [][]rune, input <-chan []rune,
	results chan<- Result) {

	defer wg.Done()

	var (
		found string
		fln   int
	)
	for f := range input {
		for _, x := range words {
			// avoid the loop, if there is an already known intersection longer
			// then a word of given
			if fln > 0 && (len(f) <= fln+1 || len(x) <= fln+1) {
				continue
			}
			var hti, xln = getTailHeadIntersection(f, x, fln)
			if xln == 0 {
				continue
			}
			found, fln = hti, xln
			// fmt.Printf("%s, %s => %s\n", string(f), string(x), hti)
		}
	}

	results <- Result{
		Word:   found,
		Length: fln,
	}
}

func main() {
	checkArgs()

	var (
		words  = getWords(toRunes(getFile())) // [][]rune
		toFind = make(chan []rune, len(words))

		concurrency = runtime.NumCPU()

		found string
		fln   int

		results = make(chan Result, concurrency)
		wg      sync.WaitGroup
	)

	for _, word := range words {
		toFind <- word
	}
	close(toFind)

	// looking for a maximum head + tail intersection
	var tp = time.Now()
	wg.Add(concurrency)
	for i := 0; i < concurrency; i++ {
		go getResult(&wg, words, toFind, results)
	}
	wg.Wait()

	close(results)
	for result := range results {
		if result.Length <= fln {
			continue
		}
		found, fln = result.Word, result.Length
	}

	fmt.Printf("found: %d, %s, after %s, using %d cores\n",
		fln, found, time.Since(tp), concurrency)
}
go run main.go russian_nouns.txt 
found: 13, ледо[исследователь]ница, after 3.443023856s, using 4 cores
anonymous
()
Ответ на: комментарий от anonymous

$ node shlak.js russian_nouns.txt

JS выигрывает, потому что перебор и сравнении идёт не побайтно, а символами Unicode. Что ускоряет цикл для русского языка и др. Для русского цикл сокращается вдвое.

Можно оптимизировать ещё, заменив

if(wal > maxl)

и

if(wbl > maxl) {

на

if(wal > maxl+2)

и

if(wbl > maxl+2) {

соответственно. Потому что полные пересечения не нужны. Например

аб
ба
а[б]a

длина слов 2 и 2, длина пересечения 1. Любые слова длиной N и M дадут максимальное подходящее пересечение Imax = min(N, M) - 1. А если пересечение такой длины уже есть, то значит Imax должно быть Imax+1, т.е. min(N, M) - 1, т.е. слово минимальной длины д.б. длинней, чтобы получить большую длину. Т.е. +2.

И ещё первый символ первого слова можно смело пропускать. Он не участвует в игре в любом случае. Как и последний второго.

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

Я доработал так свою поделку и получил время в районе 3 с. 2.7-3.4 в среднем. Думаю что JS в один поток влезет в 6-7 с.

package main

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"sync"
	"time"
)

func toRunes(bs []byte) []rune {
	return []rune(string(bs))
}

func checkArgs() {
	if len(os.Args) != 2 {
		log.Fatalf(`Provide dictionary file name, like

%s <dictionary.txt>

`, os.Args[0])
	}
}

func getFile() (in []byte) {
	var err error
	if in, err = os.ReadFile(os.Args[1]); err != nil {
		log.Fatalf("opening file %s: %v", os.Args[1], err)
	}
	return
}

// a'k'a split file
func getWords(file []rune) (words [][]rune) {

	var buf []rune

	for _, r := range file {

		if r == '\n' || r == '\r' {
			if len(buf) > 0 {
				words = append(words, buf)
			}
			buf = nil // reset
			continue
		}

		buf = append(buf, r)
	}

	return
}

func getTailHeadIntersection(ar, br []rune, fln int) (hti string, i int) {

	// it should be here, not in loop, but moved to the loop
	// to speed up it

	// // avoid the loop, if there is an already known intersection longer
	// // then a word of given
	// if fln > 0 && (len(ar) <= fln+2 || len(br) <= fln+2) {
	// 	return // "", 0
	// }

	// skip the first symbol of the first word
	for k := 1; k < len(ar); k++ {
		// don't accept the last symbol of the word
		if i == len(br) {
			break
		}
		if ar[k] == br[i] {
			i += 1
			continue
		}
		i = 0
	}

	// avoid string creation to reduce GC-pressure
	if i <= fln || i >= len(ar) || i >= len(br) {
		return "", 0
	}

	hti = string(ar[:len(ar)-i]) +
		"[" + string(ar[len(ar)-i:]) + "]" +
		string(br[i:])
	return
}

type Result struct {
	Word   string
	Length int
}

func getResult(wg *sync.WaitGroup, words [][]rune, input <-chan []rune,
	results chan<- Result) {

	defer wg.Done()

	var (
		found string
		fln   int
	)
	for f := range input {
		for _, x := range words {
			// avoid the loop, if there is an already known intersection longer
			// then a word of given
			if fln > 0 && (len(f) <= fln+2 || len(x) <= fln+2) {
				continue
			}
			var hti, xln = getTailHeadIntersection(f, x, fln)
			if xln == 0 {
				continue
			}
			found, fln = hti, xln
			// fmt.Printf("%s, %s => %s\n", string(f), string(x), hti)
		}
	}

	results <- Result{
		Word:   found,
		Length: fln,
	}
}

func main() {
	checkArgs()

	var (
		words  = getWords(toRunes(getFile())) // [][]rune
		toFind = make(chan []rune, len(words))

		concurrency = runtime.NumCPU()

		found string
		fln   int

		results = make(chan Result, concurrency)
		wg      sync.WaitGroup
	)

	for _, word := range words {
		toFind <- word
	}
	close(toFind)

	// looking for a maximum head + tail intersection
	var tp = time.Now()
	wg.Add(concurrency)
	for i := 0; i < concurrency; i++ {
		go getResult(&wg, words, toFind, results)
	}
	wg.Wait()

	close(results)
	for result := range results {
		if result.Length <= fln {
			continue
		}
		found, fln = result.Word, result.Length
	}

	fmt.Printf("found: %d, %s, after %s, using %d cores\n",
		fln, found, time.Since(tp), concurrency)
}
go run main.go russian_nouns.txt
found: 13, не[доброжелатель]ница, after 2.785340352s, using 4 cores
anonymous
()
Ответ на: комментарий от anonymous

Вообще алгоритм неверный. Он только случайно отрабатывает верно. Это калька с предложенного С++ алгоритма с оптимизациями. И этот алгоритм неверный.

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

Для всех:

Попробовал простой перебор 2 массивов Словаря, один внутри другого. Вывод верхнего.

Перл - Больше минуты

PHP - Меньше минуты

JS - 6 секунд.

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

Для всех

абапелабапел
бапелбапелок

Давай натрави свои алгоритмы на этот словарь. Должно получиться

абапела[бапел]бапелок

Тестовое задание.

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

Мы когда-то уже закопаем этот тред о кончине перла?

Пёрл умер. Да здравствует Пёрл.

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

У меня вообще 2 секунды в 4 ядра. А на одном треде в районе 3.38с. Не могут плюсы выдавать меньше. Разумеется к дегенеративным подходам я не склонен и применил все оптимизации алгоритма.

anonymous
()

Лёгкость решения подобных никому не нужных задач говорит о языке скорее с отрицательной стороны.

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

Ну значит какой-то левый институт где занимаются ерундой. Мы например сразу на первом курсе векторный графический редактор делали.

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

Ну, кстати, с этими оптимизациями вообще вышло суб-2c:

$ node shlak.js russian_nouns.txt 
Total words: 51301
Combination time: 1.989s
Max intersection: 13
Word 1: воспроизводитель
Word 2: производительность

Но что должно доказать или опровергнуть это измерение сферических коней в вакууме, до сих пор непонятно. Что 17 нода лучше древнего перла? Это и без говнозадачек понятно было.

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

Это задание с института. Чувак искал исполнителя. За деньги. Пуфы - в первой части

Регулярные выражения в чем похожи на SQL в том плане, что для простых задач действительно все просто, в противном случае бывает неделями на форумах ноют КАК НАПИСАТЬ ЗАПРОС …

Вывод то прост

Молоток полезен лишь для определенной ниши задач ...
anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.