Автор Тема: PoetryHaxor - програмка за търсене на рими  (Прочетена 11876 пъти)

PhrozenCrew

  • Напреднали
  • *****
  • Публикации: 51
    • Профил
Здравейте,

Написах програмка за търсене на рими. Програмата има версия за linux и Win. За Win я писах на C++, като използвах wxWidgets (IDE-wxDevC++). Много тромаво се получи, но кода е елементарен и който иска може да го промени и отимизира.
PoetryHaxor for Windows

За linux използвах perl, а за GUI използвах GTK2, че ми се стори най-лесно и бързо ;D. Пък и в тая комбинация би трябвало да върви на всички системи с инсталиран GTK2.:
PoetryHaxor for Linux


И двата архива са с приложен сорскод. Нямам лицензни условия, защото си нямам на идея как може да се лицензира такъв софтуер примерно под няква OpenSource форма.
Ако имате идеи свиркайте, особено за оптимизирането на C++-версията. Предварително благодаря!
Активен

b2l

  • Напреднали
  • *****
  • Публикации: 4786
  • Distribution: MCC Interim
  • Window Manager: - // - // -
  • ...sometimes I feel like screaming... || RTFM!
    • Профил
    • WWW
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #1 -: Dec 04, 2011, 20:14 »
Браво!
Активен

"Човекът е въже, опънато между звяра и свръхчовека, въже над пропаст. Човекът е нещо, което трябва да бъде превъзмогнато." - Фр. Ницше

laskov

  • Напреднали
  • *****
  • Публикации: 3166
    • Профил
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #2 -: Dec 05, 2011, 09:37 »
И на мен ми хареса :) ! Имам две незабележки :) първо - според мен, няма дума "вакумен". Има "вакуумен", но предполагам, че си взел наготово някой речник за проверка на грешки.
Другото е, че може като опция да се взима предвид мястото на ударението. Например в "умен" и "изумен" ударението е на различни места и римата се загубва.
Сега остава с един генератор на случайни числа да почне да пише стихове :)
Активен

Не си мислете, че понеже Вие мислите правилно, всички мислят като Вас! Затова, когато има избори, идете и гласувайте, за да не сте изненадани после от резултата, и за да не твърди всяка партия, че тя е спечелила, а Б.Б. (С.С., ...) е загубил, а трети да управлява.  Наздраве!  [_]3

laskov

  • Напреднали
  • *****
  • Публикации: 3166
    • Профил
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #3 -: Dec 23, 2011, 11:41 »
Слушайки Георги Минчев,
"... ... ... ... у дома си
.... запазените маси."
« Последна редакция: Dec 23, 2011, 11:46 от laskov »
Активен

Не си мислете, че понеже Вие мислите правилно, всички мислят като Вас! Затова, когато има избори, идете и гласувайте, за да не сте изненадани после от резултата, и за да не твърди всяка партия, че тя е спечелила, а Б.Б. (С.С., ...) е загубил, а трети да управлява.  Наздраве!  [_]3

bvbfan

  • Напреднали
  • *****
  • Публикации: 1056
  • Distribution: KaOS
  • Window Manager: Plasma 5
    • Профил
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #4 -: Dec 24, 2011, 10:24 »
Като гледам кода на С++ и Пърл е нормално на С++ да е по-бавен, цикълът на Пърл не борави със стрингове при всяка итерация, а именно:
Код
GeSHi (Perl):
  1. my $duma1 = substr $duma, -(length($duma))+1;
  2. my $duma2 = substr $duma, -(length($duma))+2;
  3. my $duma3 = substr $duma, -(length($duma))+3;
  4. my $duma4 = substr $duma, -(length($duma))+4;
  5. my $duma5 = substr $duma, -(length($duma))+5;
  6. my $duma6 = substr $duma, -(length($duma))+6;
  7. my $duma7 = substr $duma, -(length($duma))+7;
  8. my $duma8 = substr $duma, -(length($duma))+8;
  9. my $duma9 = substr $duma, -(length($duma))+9;
  10. my $duma10 = substr $duma, -(length($duma))+10;
  11. my $duma11 = substr $duma, -(length($duma))+11;
  12.  
  13.        open(MYFILE, "< :encoding(UTF-8)", "dic.txt");
  14. while(<MYFILE>){
  15. my($line) = $_;
  16.  
  17. chomp($line);
  18. if($duma){
  19. if($line =~ m/($duma)$/i){
  20. #$buffer->insert ($buffer->get_end_iter, "$line\n");
  21. $line1 .= "$line\n";
  22. }
  23. elsif(length($duma)-1>=2 && $line =~ m/($duma1)$/i){
  24. $line2 .= "$line\n";
  25. ...

докато С++ цикълът "пере" здраво за всеки ред и всяка отделна под-дума, което забавя драстично целият процес
Код
GeSHi (C++):
  1.  wxString filename = _T("dic.txt");
  2.    wxFileInputStream fsIn(filename);
  3.    if ( !fsIn.Ok() )
  4.    {
  5.        wxPuts(_T("ERROR: couldn't open file."));
  6.    }
  7.    else
  8.    {
  9.        wxTextInputStream tis(fsIn);
  10.  
  11.        for ( ;; )
  12.        {
  13.            const wxString s = tis.ReadLine();
  14.  
  15.            // line could be non empty if the last line of the file isn't
  16.            // terminated with EOL
  17.            if ( fsIn.Eof() && s.empty() )
  18.                break;
  19.  
  20.            if(duma){
  21. if(wxRegEx (duma+"$").Matches(s)){
  22. list1 += s+"\n";
  23. }
  24. else if((dsize-1 >= 2) && wxRegEx (duma.substr(1)+"$").Matches(s)){
  25. list2 += s+"\n";
  26. }
  27. else if((dsize-2 >= 2) && wxRegEx (duma.substr(2)+"$").Matches(s)){
  28. list3 += s+"\n";
  29. }
  30. ...

С++ дори много бързо извършва огромния ти цикъл, Пърл ще е съществено по-бавен при равноправни условия. Имам следните препоръки, кода си твой ти решаваш как ще изглежда, зареждай файла само веднъж в конструктора и използвай вектор от стрингове, като после само ще обикаляш вектора и ще "мачваш". В Project1Dlg.h
Код
GeSHi (C++):
  1. #include <vector>
  2. ...
  3. private:
  4. void OnClose(wxCloseEvent& event);
  5. void CreateGUIControls();
  6. std::vector<wxString>dict;
  7. };
после в конструктора го попълваш Project1Dlg.cpp
Код
GeSHi (C++):
  1. Project1Dlg::Project1Dlg(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
  2. : wxDialog(parent, id, title, position, size, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
  3. {
  4. CreateGUIControls();
  5. wxString filename = _T("dic.txt");
  6.    wxFileInputStream fsIn(filename);
  7.    if ( !fsIn.Ok() )
  8.    {
  9.        wxPuts(_T("ERROR: couldn't open file."));
  10.    }
  11.    else
  12.    {
  13.        wxTextInputStream tis(fsIn);
  14.  
  15.        for ( ;; )
  16.        {
  17.            const wxString s = tis.ReadLine();
  18.  
  19.            // line could be non empty if the last line of the file isn't
  20.            // terminated with EOL
  21.            if ( fsIn.Eof() && s.empty() )
  22.                break;
  23.    if(!s.empty())
  24. dict.push_back(s);
  25. }
  26.    }
  27. }
и при всяко натискане на бутон всичко ще става за по-малко от секунда, като обхождаш само вектора и търсиш за съвпадение
Код
GeSHi (C++):
  1.        std::vector<wxString>::iterator it;
  2.        for (it = dict.begin(); it != dict.end(); it++ )
  3.        {
  4.            const wxString s = (*it);
  5.  
  6.            if(duma){
  7. if(wxRegEx (duma+"$").Matches(s)){
  8. list1 += s+"\n";
  9. }
  10. else if((dsize-1 >= 2) && wxRegEx (duma.substr(1)+"$").Matches(s)){
  11. list2 += s+"\n";
  12. }
  13. ...
Активен

PhrozenCrew

  • Напреднали
  • *****
  • Публикации: 51
    • Профил
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #5 -: Dec 26, 2011, 14:59 »
bvbfan, много ти благодаря за добрите идеи!
Пробвах по начина, който си описал. Искрено се надявах да ускоря процеса. Но при мен не се получи. При тест с едни и същи думи се получава почти еднакво забавяне от 5-6 секунди. Т.е. дори и да има разлика е незабележима при WinXP SP3. Предполагам, че може би се дължи и на спецификата на операционната система.
Ето втората версия с предварително кеширане на речника: PoetryHaxor-v.02

Предполагам, че остава варианта за разделяне на процеси и динамично вадене на проверените думи. Обаче не съм толкова добър, за да напиша подобно нещо.
Активен

bvbfan

  • Напреднали
  • *****
  • Публикации: 1056
  • Distribution: KaOS
  • Window Manager: Plasma 5
    • Профил
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #6 -: Dec 26, 2011, 20:36 »
Аз не съм ползвам wxDevC++ нито wxWidgets и реших да видя какво е положението и защо се изпълнява бавно и наистина проблема е непрекъснатото извикване на substr. И едното решение е да реализираш точно както на perl
Код
GeSHi (C++):
  1. void Project1Dlg::WxButton1Click(wxCommandEvent& event)
  2. {
  3. WxEdit1->Clear();
  4. wxString duma = WxEdit2->GetValue();
  5. int dsize = duma.length();
  6. if(dsize < 2) return;
  7.  
  8. wxRegEx Duma(duma+wxT("$"));
  9. wxRegEx subDuma1(duma.substr(1)+wxT("$"));
  10. wxRegEx subDuma2(duma.substr(2)+wxT("$"));
  11. wxRegEx subDuma3(duma.substr(3)+wxT("$"));
  12. wxRegEx subDuma4(duma.substr(4)+wxT("$"));
  13. wxRegEx subDuma5(duma.substr(5)+wxT("$"));
  14. wxRegEx subDuma6(duma.substr(6)+wxT("$"));
  15. wxRegEx subDuma7(duma.substr(7)+wxT("$"));
  16. wxRegEx subDuma8(duma.substr(8)+wxT("$"));
  17. wxRegEx subDuma9(duma.substr(9)+wxT("$"));
  18. wxRegEx subDuma10(duma.substr(10)+wxT("$"));
  19. wxRegEx subDuma11(duma.substr(11)+wxT("$"));
  20.  
  21. wxString result;
  22.  
  23. wxPuts(_T("\n*** wxTextInputStream test ***"));
  24.  
  25. std::vector<wxString>::iterator it;
  26. for (it = dict.begin(); it != dict.end(); it++ )
  27. {
  28.                bool find = false;
  29. const wxString s = (*it);
  30.  
  31. if(Duma.Matches(s)){
  32. find = true;
  33. }
  34.                else if((dsize-1 >= 2) && subDuma1.Matches(s)){
  35. find = true;
  36. }
  37. else if((dsize-2 >= 2) && subDuma2.Matches(s)){
  38. find = true;
  39. }
  40. else if((dsize-3 >= 2) && subDuma3.Matches(s)){
  41. find = true;
  42. }
  43. else if((dsize-4 >= 2) && subDuma4.Matches(s)){
  44. find = true;
  45. }
  46. else if((dsize-5 >= 2) && subDuma5.Matches(s)){
  47. find = true;
  48. }
  49. else if((dsize-6 >= 2) && subDuma6.Matches(s)){
  50. find = true;
  51. }
  52. else if((dsize-7 >= 2) && subDuma7.Matches(s)){
  53. find = true;
  54. }
  55. else if((dsize-8 >= 2) && subDuma8.Matches(s)){
  56. find = true;
  57. }
  58. else if((dsize-9 >= 2) && subDuma9.Matches(s)){
  59. find = true;
  60. }
  61. else if((dsize-10 >= 2) && subDuma10.Matches(s)){
  62. find = true;
  63. }
  64. if(find) {
  65.                     result += s+wxT("\n");
  66.                }
  67. }
  68. WxEdit1->AppendText(result);
  69. WxEdit1->SetInsertionPoint(0); // Set cursor to first line
  70.  
Тествах и се изпълнява за по-малко от секунда  ;) , имам и мой вариант, който зависи от дължината на търсената дума и възможно да отнеме повече време при по-дълги думи, но може да се подобри, стига да има желание. Премахвам всички суб-думи и с един цикъл решавам за съпадения
Код
GeSHi (C++):
  1.       if(Duma.Matches(s)){
  2.    find = true;
  3.       }
  4.       else
  5.       {
  6.            int start = 0;
  7.            size_t ssize = s.size();
  8.            if(dsize > (int)ssize)
  9.                start = dsize-ssize;
  10.            for(int i = start+1; i < dsize-2; i++)
  11.            {
  12.                if(wxRegEx(duma.substr(i)+wxT("$")).Matches(s))
  13.                {
  14.                    find = true;
  15.                    break;
  16.                }
  17.            }
  18.        }
  19.  
Активен

PhrozenCrew

  • Напреднали
  • *****
  • Публикации: 51
    • Профил
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #7 -: Dec 26, 2011, 23:51 »
bvbfan, ценя високо желанието ти да ми помогнеш! Благодаря ти за интересните кодове! Научавам страшно много неща!
Наистина програмата така работи по-бързо. В един първоначален вариант бях направил нещо подобно, но се губи идеята. Целта ми е да изкарам първо думите с най-дълго съвпадение, а не просто всички думи, които съвпадат с шаблоните.
Отново ти благодаря за ценния код, а още повече за желанието ти да съдействаш!
Активен

bvbfan

  • Напреднали
  • *****
  • Публикации: 1056
  • Distribution: KaOS
  • Window Manager: Plasma 5
    • Профил
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #8 -: Dec 27, 2011, 13:40 »
В един първоначален вариант бях направил нещо подобно, но се губи идеята. Целта ми е да изкарам първо думите с най-дълго съвпадение, а не просто всички думи, които съвпадат с шаблоните.
Идеята не се губи и 2-та варианта целта е да се намери най-дългото възможно съвпадение, освен това ги проверих, че дават един и същ резултат. Защо си помисли, че се сменя идеята  ???
Активен

PhrozenCrew

  • Напреднали
  • *****
  • Публикации: 51
    • Профил
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #9 -: Dec 27, 2011, 23:14 »
Възможно е нещо да съм объркал кода от последния ти пост, но след компиране, при тест с една и съща дума се получава следния резултат:

Десният вариант е програмата от първия ми пост, левият е копилацията от кода по-горе. Надявам се да е ясно какво искам да постигна. Първи да излизат думите с максимално дълго съвпадение.
Активен

bvbfan

  • Напреднали
  • *****
  • Публикации: 1056
  • Distribution: KaOS
  • Window Manager: Plasma 5
    • Профил
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #10 -: Dec 28, 2011, 17:09 »
Просто са подредени както във файла, а не по най-дълго съвпадение, махни флага find и си върни пак стринг променливите, 1:1 с Пърл-а и става много бързо и точно както искаш find = true; ->  line1 += s+wxT("\n"); и така пак 11 и пак поотделно ги слагаш на прозореца.
Активен

Oxy

  • Напреднали
  • *****
  • Публикации: 253
  • Distribution: Fedora / Gentoo / Debian
  • Window Manager: KDE (4.2/ 3.5)
    • Профил
    • WWW
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #11 -: Dec 28, 2011, 21:29 »
Понеже нямам време да чета кодове в момента искам да попитам дали сте си играли да правите някакво организиране на информацията и да я кодирате, така че търсенето да става много бързо или просто правите някакъв цикъл в масива от думи и върху всяка дума извършвате операции с регулярни изрази? Имам интересна идея за реализирането на въпросната програма, просто ще трябва да си поиграя малко с числа преди да пиша... :)

Oxy

  • Напреднали
  • *****
  • Публикации: 253
  • Distribution: Fedora / Gentoo / Debian
  • Window Manager: KDE (4.2/ 3.5)
    • Профил
    • WWW
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #12 -: Dec 28, 2011, 21:43 »
ОК сега. Идеята ми е следната. Да вземем дума "оксиморон", Която е от 9 символа.
и я представвяме по следния начин: нором последните 5 байта(макар че това символ = байт май е само в аски.) все тая правим "нором" = м*100000000 + 0* 1000000 + р*10000 + о*100 + н
като всяки символ отговаря на някакво число от 1 до 34
после всичко после примерно търсим рима на газпром думата се кодира по същия начин с последните 5 символа и обчият стринг ром ще се открие доста бързо. Тъй като най-важни са последните букви, колкото е голяма "приликата" толкова повече функциите от думате ще дават по-близък резултат. Като сложност на алгоритъма имаме комплекситет в О(log n) ако предварително си си сметнал думите в масива:)

Поздрави,
Тодор

Oxy

  • Напреднали
  • *****
  • Публикации: 253
  • Distribution: Fedora / Gentoo / Debian
  • Window Manager: KDE (4.2/ 3.5)
    • Профил
    • WWW
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #13 -: Dec 28, 2011, 21:55 »
В Българския тълковен речник (изд. 1994) пише, че в него има около 60'000
при комплекситет log(n) като базиса ти е 2 смятай колко пъти ще правиш сондиране :) 16 :) отделно веднъж, ще трявба да ги подредиш в някаква структора като ги кодираш, което с един мърджсорт би трябвало да ти излезе с граница до 60 000 * 16. Ако ти се занимава може да постигнеш по-добра сложност с някакъв рандомизиран куиксорт, ама не си струва да си го пишеш това, след като веднъж ще кодираш и сортираш. Също може да ползваш инсърт сорт кодирай, сортирай, кодирай, сортирай и тн... не знам колко си струва упражнението като не сортираш някакъв обем от 2^200 обекта примерно :) [_]3

bvbfan

  • Напреднали
  • *****
  • Публикации: 1056
  • Distribution: KaOS
  • Window Manager: Plasma 5
    • Профил
Re: PoetryHaxor - програмка за търсене на рими
« Отговор #14 -: Dec 28, 2011, 22:20 »
Добавих Уникод и направих ново търсене
http://www.multiupload.com/ATZ824YUWP
Активен