Linux за българи: Форуми

Програмиране => Общ форум => Темата е започната от: PhrozenCrew в Dec 04, 2011, 18:48



Титла: PoetryHaxor - програмка за търсене на рими
Публикувано от: PhrozenCrew в Dec 04, 2011, 18:48
Здравейте,

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

За linux използвах perl, а за GUI използвах GTK2, че ми се стори най-лесно и бързо ;D. Пък и в тая комбинация би трябвало да върви на всички системи с инсталиран GTK2.:
PoetryHaxor for Linux ($2)
(http://blog.nediko.info/examples/poetryhaxor/PoetryHaxor_for_Linux.png)

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


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: b2l в Dec 04, 2011, 20:14
Браво!


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: laskov в Dec 05, 2011, 09:37
И на мен ми хареса :) ! Имам две незабележки :) първо - според мен, няма дума "вакумен". Има "вакуумен", но предполагам, че си взел наготово някой речник за проверка на грешки.
Другото е, че може като опция да се взима предвид мястото на ударението. Например в "умен" и "изумен" ударението е на различни места и римата се загубва.
Сега остава с един генератор на случайни числа да почне да пише стихове :)


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: laskov в Dec 23, 2011, 11:41
Слушайки Георги Минчев,
"... ... ... ... у дома си
.... запазените маси."


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: bvbfan в 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. ...


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

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


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: bvbfan в 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.  


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


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: bvbfan в Dec 27, 2011, 13:40
В един първоначален вариант бях направил нещо подобно, но се губи идеята. Целта ми е да изкарам първо думите с най-дълго съвпадение, а не просто всички думи, които съвпадат с шаблоните.
Идеята не се губи и 2-та варианта целта е да се намери най-дългото възможно съвпадение, освен това ги проверих, че дават един и същ резултат. Защо си помисли, че се сменя идеята  ???


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: PhrozenCrew в Dec 27, 2011, 23:14
Възможно е нещо да съм объркал кода от последния ти пост, но след компиране, при тест с една и съща дума се получава следния резултат:
(http://i43.tinypic.com/qso51z.png)
Десният вариант е програмата от първия ми пост, левият е копилацията от кода по-горе. Надявам се да е ясно какво искам да постигна. Първи да излизат думите с максимално дълго съвпадение.


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: bvbfan в Dec 28, 2011, 17:09
Просто са подредени както във файла, а не по най-дълго съвпадение, махни флага find и си върни пак стринг променливите, 1:1 с Пърл-а и става много бързо и точно както искаш find = true; ->  line1 += s+wxT("\n"); и така пак 11 и пак поотделно ги слагаш на прозореца.


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: Oxy в Dec 28, 2011, 21:29
Понеже нямам време да чета кодове в момента искам да попитам дали сте си играли да правите някакво организиране на информацията и да я кодирате, така че търсенето да става много бързо или просто правите някакъв цикъл в масива от думи и върху всяка дума извършвате операции с регулярни изрази? Имам интересна идея за реализирането на въпросната програма, просто ще трябва да си поиграя малко с числа преди да пиша... :)


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: Oxy в Dec 28, 2011, 21:43
ОК сега. Идеята ми е следната. Да вземем дума "оксиморон", Която е от 9 символа.
и я представвяме по следния начин: нором последните 5 байта(макар че това символ = байт май е само в аски.) все тая правим "нором" = м*100000000 + 0* 1000000 + р*10000 + о*100 + н
като всяки символ отговаря на някакво число от 1 до 34
после всичко после примерно търсим рима на газпром думата се кодира по същия начин с последните 5 символа и обчият стринг ром ще се открие доста бързо. Тъй като най-важни са последните букви, колкото е голяма "приликата" толкова повече функциите от думате ще дават по-близък резултат. Като сложност на алгоритъма имаме комплекситет в О(log n) ако предварително си си сметнал думите в масива:)

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


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: Oxy в Dec 28, 2011, 21:55
В Българския тълковен речник (изд. 1994) пише, че в него има около 60'000
при комплекситет log(n) като базиса ти е 2 смятай колко пъти ще правиш сондиране :) 16 :) отделно веднъж, ще трявба да ги подредиш в някаква структора като ги кодираш, което с един мърджсорт би трябвало да ти излезе с граница до 60 000 * 16. Ако ти се занимава може да постигнеш по-добра сложност с някакъв рандомизиран куиксорт, ама не си струва да си го пишеш това, след като веднъж ще кодираш и сортираш. Също може да ползваш инсърт сорт кодирай, сортирай, кодирай, сортирай и тн... не знам колко си струва упражнението като не сортираш някакъв обем от 2^200 обекта примерно :) [_]3


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: bvbfan в Dec 28, 2011, 22:20
Добавих Уникод и направих ново търсене
http://www.multiupload.com/ATZ824YUWP


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: niakoi в Dec 29, 2011, 10:58
само 1 предложение, виж какво е DAWG и как можеш да го използваш, за да забързаш програмата си

поздрави
нас


Титла: Re: PoetryHaxor - програмка за търсене на рими
Публикувано от: Oxy в Dec 31, 2011, 03:59
Предложението с ДАЛГ е интересно... ако инвертира всяка дука и после разглежда всеки символ като обект от  символ и 28 възможни поинтъра към следващия убект, много лесто може да свива търсенето. Аз до сега не съм реализирал подобно дърво до сега, но би ми било интересно да го видя в практиката... Ако за корен са сложи един епсилон а.к.а. празната дума/символ ще се получи интересно... ако има някой да му се занимава, ще е интересно...