алгоритъм, позволяващ проследяване на дума, срещаща се две думи след дума с определен модел

Много ще бъда благодарен за помощ с този алгоритъм/псевдокод.

По принцип търся думи с определен модел (няма значение какъв). Имам специална функция за определянето му, която връща 1, ако думата отговаря на изискванията. Когато това стане, втората дума след това трябва да бъде пропусната и да не се записва в изхода. Нямах проблем с това, когато "избраните" думи са разделени от една "неизбрана" дума. Проблемът е - какво да правим, когато "избраните" се появяват един след друг?

Подготвих такъв псевдо код, за да изясня малко ситуацията. Но за съжаление не работи за всички комбинации от „избрано“ и „неизбрано“.

Въведох три брояча/променливи, които ми помагаха да открия позицията, на която се намирам в момента.

Следващият псевдо код не е в логичен ред!

if (counter == 2 || in_a_row >= 3) {
    erase = 1;
    counter--;
    yes = 0;
    if (!chosen) 
        counter = 0;
}
if (chosen) {
    counter++;
    yes = 1;
    in_a_row++;
} else {
    if (yes = 1) /* yes - is used when the preceeding word is chosen and the next is not chosen, in order to keep track of the counter */
        counter++;
}
if (in_a_row == 5)
    in_a_row = 4; /* just to make sure that counter doesn't go too high */
if (erase == 1)
    /*erasing procedure*/

Ако имате по-проста идея или видите грешка в нея, МОЛЯ, помогнете ми. Опитвайки се да отработя това в продължение на 8 часа...


person Peter Cerba    schedule 25.08.2012    source източник
comment
Не разбирам напълно всички условия, при които една дума трябва да бъде изтрита или не. Така че това е само обща забележка. Ако приемем, че имате целия списък с думи, преди да стартирате алгоритъма (т.е. не работите в реално време с въвеждане от клавиатурата например), моят опит с подобни проблеми е, че трябва да изтриете от задната към горната част на списъка . Идеята е (1) да поставите думите в списък, след това (2) да преминете през целия списък, (3) да маркирате елементите за изтриване, (4) да стартирате списъка назад, изтривайки елементите. Изтриването назад прави счетоводството по-лесно.   -  person rpsml    schedule 26.08.2012
comment
@rpsml Мога да продължа с обработката на файла без проблеми, единственият проблем е как да реша коя дума да пропусна.   -  person Peter Cerba    schedule 26.08.2012
comment
Всъщност не разбрах проблема, тъй като мислех, че е доста тривиален (вероятно пропускам нещо). Моето разбиране за алгоритъма в нулев ред е: ако задействащата дума е на позиция i, просто маркирайте позиция i+2, която трябва да бъде изтрита. И това е. Това би довело до случая, при който задействащите думи в i и i+1 ще изтрият думи в i+2 и i+3. Задействащите думи при i, i+1 и i+2 биха изтрили думите при i+2 (което само по себе си е задействаща дума), i+3 и i+4. Какво ми липсва тук?   -  person rpsml    schedule 26.08.2012


Отговори (4)


Извинете ме, че не използвах псевдокод, вместо това използвах действителен код. Надявам се, че вече разбирам проблема достатъчно добре, че убеждението ми, че не изглежда много сложно, е точно.

# include <stdio.h>
# include <ctype.h>
# include <string.h>


# define BUFF_SIZE       1024
# define WORD_DELIM     " "
# define MATCH_PATT     "barf"


int main(  int ac ,  char *av[]  )
{
    __u_char    false = ( 1 == 0 ) ;
    __u_char    true = ( 1 == 1 ) ;

    __u_char    match_1_back = false ;
    __u_char    match
barf   barf  barf   healthy     feeling     better   barf  barf barf uh oh sick again
barf   barf  healthy     feeling     better   barf  barf uh oh sick again
barf   healthy     barf   feeling     better     barf   uh   barf   oh sick again
barf   healthy     feeling     better   barf uh oh sick again
back = false ; char line_buff[ BUFF_SIZE ] ; char *buff_ptr ; char *word_ptr ; while ( fgets( line_buff , BUFF_SIZE , stdin ) ) { puts( "\nInput line was: " ) ; puts( line_buff ) ; puts( "Output line is: " ) ; buff_ptr = line_buff ; while ( ( word_ptr = strtok( buff_ptr , WORD_DELIM ) ) != NULL ) { buff_ptr = NULL ; if ( strcmp( word_ptr , MATCH_PATT ) == 0 ) { // Set these to what they should be for next iteration. match
barf   barf  barf   healthy     feeling     better   barf  barf barf uh oh sick again
barf   barf  healthy     feeling     better   barf  barf uh oh sick again
barf   healthy     barf   feeling     better     barf   uh   barf   oh sick again
barf   healthy     feeling     better   barf uh oh sick again
back = match_1_back ; match_1_back = true ; // Don't output matched token. } else { // Don't output token if a token matched 2 tokens back. if ( ! match
barf   barf  barf   healthy     feeling     better   barf  barf barf uh oh sick again
barf   barf  healthy     feeling     better   barf  barf uh oh sick again
barf   healthy     barf   feeling     better     barf   uh   barf   oh sick again
barf   healthy     feeling     better   barf uh oh sick again
back ) printf( "%s " , word_ptr ) ; // Set these to what they should be for next iteration. match
barf   barf  barf   healthy     feeling     better   barf  barf barf uh oh sick again
barf   barf  healthy     feeling     better   barf  barf uh oh sick again
barf   healthy     barf   feeling     better     barf   uh   barf   oh sick again
barf   healthy     feeling     better   barf uh oh sick again
back = match_1_back ; match_1_back = false ; } } printf( "\n" ) ; } }

С този вход:

barf   barf  barf   healthy     feeling     better   barf  barf barf uh oh sick again
barf   barf  healthy     feeling     better   barf  barf uh oh sick again
barf   healthy     barf   feeling     better     barf   uh   barf   oh sick again
barf   healthy     feeling     better   barf uh oh sick again

Получих този резултат:

Input line was:  
barf   barf  barf   healthy     feeling     better   barf  barf barf uh oh sick again

Output line is:  
better sick again


Input line was:  
barf   barf  healthy     feeling     better   barf  barf uh oh sick again

Output line is:  
better sick again


Input line was:  
barf   healthy     barf   feeling     better     barf   uh   barf   oh sick again

Output line is:  
healthy feeling uh oh again


Input line was:  
barf   healthy     feeling     better   barf uh oh sick again

Output line is:  
healthy better uh sick again

Просто използвах просто сравнение, а не действителни регулярни изрази. Исках само да илюстрирам алгоритъма. Резултатът отговаря ли на изискванията?

person toes_314    schedule 25.08.2012
comment
Благодаря ти! Използването на избраната дума кара да звучи така, сякаш думата е избрана за извеждане. - person toes_314; 26.08.2012
comment
Въпреки че вашето изпълнение леко се различава от това в задачата. Бих искал да кажа, че СЪМ ТОЛКОВА ЩАСТЛИВ, ЧЕ МИ ПОМОГНАХТЕ, въз основа на това създадох моя собствена програма, която сега РАБОТИ КАТО ШАРМ. Най-добри пожелания ! - person Peter Cerba; 26.08.2012

Звучи като класическа употреба на регулярни изрази. Не посочвате език, но много езици поддържат RegEx.

Следният сайт е добра отправна точка/справка за RegEx, ако не сте запознати с него. http://www.regular-expressions.info/quickstart.html

Ще използвате израз, съставен от три части. Синтаксисът по-долу е от паметта, така че ще трябва да го проверите отново:

  • (first) - Съвпада с думата "първо"
  • [\w]*{1,3} - Всяка дума, която се повтаря например между 1 и 3 пъти -
  • (second) - Съвпада с думата "втори"
person mbliss    schedule 25.08.2012
comment
Не знам кой е поставил +1 това, но това е просто реклама на софтуер. Не, благодаря, трябва да използвам обикновен C. - person Peter Cerba; 25.08.2012
comment
Здравей Питър, само за да поясня, че това не е реклама за софтуер. Регулярните изрази са вградена функция на много езици за програмиране. Сайтът, към който дадох връзка, не е такъв, с който съм свързан, но е такъв, който използвам като справка редовно. Както и да е, радвам се, че намерихте решение - person mbliss; 27.08.2012

Нещо като това?

for (i = 0; i<wordcount; i++)
{
    CurrentWord = Words[i]
    if (WordMatchesCritera(CurrentWord))
    {
        if (HavePrecedingWord)
        { 
             success !!!
        } 
        else
        {
            i ++;
            HavePrecedingWord = true
        }
    }
    else
    {
        HavePrecedingWord = false;
    }
}
person podiluska    schedule 25.08.2012
comment
Напълно не работи. Представете си последователност: избран избран не не. Според вашия алгоритъм first selected ще зададе Havepreceeding на 1, което ще изтрие selected2 вместо not1. Благодаря все пак - person Peter Cerba; 25.08.2012
comment
@peterkowalski не - i++ ще пропусне selected2 - person podiluska; 26.08.2012

Ще работи ли това?

    matchID = -1;
    eraseID = -1;


    for(i = 0; i < ... ; i++)
    {
         if( wordMatches ( word[i] ) )
         {                  
            matchID = i;     /* found the chosen one */
            eraseID = -1;         
         }
         else 
         {
            if( matchID != -1 ) /* chosen one was found ? */
            {
                 eraseID = i;   /* erase the next non-matching one */
                 break; /* ? done for now  ? */
            }

          }
    }
person shr    schedule 25.08.2012