Napraw moje jąkane słowa

12

Jąkanie jest problemem, którego wielu z nas mogło doświadczyć lub przynajmniej go zobaczyć. Chociaż większość znanych programów do rozpoznawania mowy ma poważne problemy z jąkaniem się, wyobraźmy sobie oprogramowanie, które rozumie jąkanie, ale nie może ich naprawić i zapisuje je tylko w obecnej postaci.

Przykładowy tekst napisany przez takie oprogramowanie może wyglądać tak: „bądź ostrożny” . W tym przykładzie „ostrożne” to oryginalne słowo, a „ca ca” to jąkane słowa.

Wyzwanie

Napisz program lub funkcję, która naprawia jąkane słowa, usuwając je z wejścia, zachowując oryginalne słowa. Na przykład poprawiona wersja „proszę uważać” to „proszę uważać” .

To jest , wygrywa najkrótsza odpowiedź w każdym języku!

Jakie są jąkane słowa?

Jąkanie ma wiele różnych odmian. Ale dla uproszczenia tego wyzwania ograniczymy go do następujących zasad:

  • Jąkane słowa mogą być niekompletną częścią lub całością oryginalnego słowa. Przez „część nieukończoną” rozumiem, że oryginalne słowo powinno zaczynać się dokładnie od słowa jąkanego. Na przykład „ope” i „open” oba mogą być jąkanym słowem „open” , ale „pen” nie może być jednym, ponieważ „open” nie zaczyna się od „pen” .
  • Jąkane słowa muszą zawierać co najmniej jedną z samogłosek „aeiou” . Na przykład „gwiazda” może być jąkanym słowem dla „start”, ponieważ zawiera „a” , ale „st” nie może być jąkanym słowem, ponieważ nie zawiera żadnej z wymienionych samogłosek.
  • Jąkane słowa mogą pojawić się tylko przed oryginalnym słowem i powinny być powtórzone co najmniej dwa razy, aby były poprawne (oryginalne słowo nie liczy się w powtórzeniach). Na przykład „oo open” ma jąkane słowa, ale „o open o” nie, ponieważ „o” po oryginalnym słowie się nie liczy, a „o” przed oryginalnym słowem nie jest powtarzane co najmniej dwa razy. „go go go go go go go” ma pięć powtórzeń jąkanych słów przed oryginalnym słowem i jest ważne.
  • Pojedynczy zestaw powtarzanych jąkanych słów nie może zawierać mieszanych form, a słowa powinny być dokładnie takie same. Na przykład „op o op open” nie liczy się jako jąkane słowa. Z drugiej strony „o op op open” ma jąkane słowa, ponieważ pierwsze „o” jest tutaj postrzegane jako zupełnie inne słowo, a dwa „op” są liczone jako jąkane słowa „open” .
  • W przypadku wielu prawidłowych zestawów powtarzających się jąkanych słów bezpośrednio po sobie, pozostaje tylko ostatnie oryginalne słowo. Na przykład w „ooo op op op open” część „oo o” jest postrzegana jako jąkane słowa pierwszego „op” , więc należy je usunąć, a następnie „op op op” jest postrzegana jako jąkane słowo „otwarte ” i należy je również usunąć, aby po usunięciu jąkanych słów pozostało tylko „ otwarte ” . Możesz założyć, że wiele prawidłowych zestawów powtarzających się jąkanych słów występuje tylko od lewej do prawej, więc ustalenie „op op ooo open” spowoduje „op op open” (aka

Wejście

  • Dane wejściowe to pojedynczy wiersz zawierający tylko angielskie litery ASCII (az), cyfry (0-9) i znaki spacji. Obudowa na litery nie jest ważna i możesz zdecydować o przyjęciu małych lub wielkich liter lub obu, ale obudowa powinna pozostać taka sama i nie możesz jej zmienić w wydruku.
  • Możesz użyć listy liter (jak ["l","i","s","t"," ","o","f"," ","l","e","t","t","e","r","s"]) zamiast ciągu, ale nie możesz użyć listy słów. Jeśli twój język ma inną strukturę wprowadzania, użyj go. Chodzi o to, że dane wejściowe nie powinny być oddzielane słowami, więc koszt oddzielenia słów w niektórych językach może faktycznie wywołać inne kreatywne rozwiązania.
  • Dane wejściowe mogą nie zawierać żadnego, jednego lub wielu jąkanych słów.
  • Słowa i / lub liczby są oddzielone pojedynczą spacją, a dane wejściowe nie będą zawierać podwójnych spacji obok siebie.

Wynik

  • Ciąg znaków lub lista liter lub odpowiednia struktura w Twoim języku z usuniętymi wszystkimi wprowadzonymi słowami.
  • Wyrazy wyjściowe powinny być oddzielone dokładnie jedną spacją (to samo co wejście).
  • Dozwolone są pojedyncze wiodące i końcowe znaki nowej linii lub spacja.

Standardowe luki są zabronione.

Przypadki testowe

Brak jąkanych słów:

"hello world" => "hello world"

Pojedynczy przykład powtarzających się jąkanych słów:

"ope ope ope ope open the window" => "open the window"

Wiele wystąpień powtarzanych jąkanych słów:

"there is is is is something un un under the the the table" => "there is something under the table"

Brak słów jąkanych, niewystarczająco powtarzanych:

"give me the the book" => "give me the the book"

Bez zacinających się słów, nie ma żadnej z wymienionych samogłosek:

"h h help m m m me" => "h h help m m m me"

Liczby nie są jąkanymi słowami, nie mają żadnej z wymienionych samogłosek:

"my nu nu number is 9 9 9 9876" => "my number is 9 9 9 9876"

Ale słowo zawierające zarówno samogłoski, jak i liczby może mieć jąkane słowa:

"my wi wi windows10 is slow" => "my windows10 is slow"

Różne formy jąkanych słów w tej samej grupie powtórzeń nie są liczone:

"this is an ant antarctica does not have" => "this is an ant antarctica does not have"

W przypadku wielu ciągłych zestawów jąkanych słów bezpośrednio po sobie zachowaj tylko ostatnie oryginalne słowo:

"what a be be be beauti beauti beautiful flower" => "what a beautiful flower"

To nie jest przypadek wielu ciągłych zestawów jąkanych słów zaraz po sobie:

"drink wat wat wa wa water" => "drink wat wat water"

Puste wejście:

"" => ""

Więcej przypadków z komentarzy:

"a ab abc" => "a ab abc"
"a ab ab abc" => "a abc"
"ab ab abc abcd" => "abc abcd"
"a a ab a able" => "ab a able"
"i have ave ave average" => "i have average"
"my wi wi windows 10 is cra cra crap" => "my windows 10 is crap"

Łatwa do skopiowania lista powyższych przypadków testowych:

"hello world",
"ope ope ope ope open the window",
"there is is is is something un un under the the the table",
"give me the the book",
"h h help m m m me",
"my nu nu number is 9 9 9 9876",
"my wi wi windows10 is slow",
"this is an ant antarctica does not have",
"what a be be be beauti beauti beautiful flower",
"drink wat wat wa wa water",
"",
"a ab abc",
"a ab ab abc",
"ab ab abc abcd",
"a a ab a able",
"i have ave ave average",
"my wi wi windows 10 is cra cra crap"
Noc 2
źródło
2
"drink wat wat wa wa water" => "drink wat wat water"wydaje się, że reguła powinna mieć zastosowanie rekurencyjnie, aby stała się „pić wodę”
Jonah
2
@Jonah, jeśli czytasz ostatni element w części Jakie są jąkane słowa? Wyjaśniłem tę sprawę. „wat wat” nie są jąkanymi słowami dla „wa” i naprawiamy je tylko raz, więc kiedy otrzymujemy „pij wat wat wodę”, nie naprawiamy ponownie, aby usunąć nowo utworzone słowa jąkające. Ale w odwrotnym przypadku, np. „Wa wa wat wat water”, wynikiem będzie „woda”, ponieważ „wa wa” to słowa jąkane dla pierwszego „wat”, a „wat wat” to również jąkane słowa „woda”.
Noc 2
Ok, w porządku, mówiłem tylko, że sensowne będzie kontynuowanie napraw, dopóki nie będzie już można, ale widzę argument za skupieniem się na jednej iteracji.
Jonasz

Odpowiedzi:

6

C (gcc), 183 180 178 bajtów

f(s,t,u,T,e,r)char*s,*t,*u,*r;{for(;s=index(u=s,32);T>1&strpbrk(u,"aeiou")-1<s&&memmove(s=u,t-e,r-t-~e))for(e=++s-u,r=u+strlen(t=u),T=0;(t+=e)<r&!memcmp(u,t,e-1)&t[-1]==32;++T);}

Wypróbuj online!

C z pewnością nie może konkurować ze zwięzłością wyrażenia regularnego ...

Ten jest szczególnie trudny do odczytania, ponieważ ostatecznie zrzuciłem całą funkcję w jedną zagnieżdżoną parę forpętli (bez ciała!). To sprawia, że ​​kolejność oceny jest nieprecyzyjna - kod na początku jest faktycznie wykonywany jako ostatni.

Moja ulubiona sztuczka to strpbrk(u,"aeiou")-1<s. Służy to do sprawdzenia, czy powtarzane słowo zawiera samogłoski. uwskazuje początek powtarzanego słowa i swskazuje na drugie powtórzenie tego słowa; na przykład:

"my nu nu number is 9 9 9 9876"
    ^  ^
    u  s

strpbrknastępnie znajduje pierwszy znak, "aeiou"który pojawia się po u. (W tym przypadku jest to 'u'zaraz po.) Następnie możemy sprawdzić, czy to nastąpi wcześniej, saby sprawdzić, czy słowo zawiera samogłoskę. Ale jest niewielki problem - strpbrkzwraca NULL(tj. 0), Jeśli nie ma samogłoski w całym ciągu. Aby to naprawić, po prostu odejmuję 1, który zmienia się 0w 0xffffffffffffffff(na moim komputerze) z powodu przepełnienia. Jest to maksymalna wartość wskaźnika, która jest zdecydowanie większa niż s, co powoduje niepowodzenie sprawdzania.

Oto nieco starsza wersja (przed transformacją, która zmąciła kontrolę) z komentarzami:

f(s,t,u,c,n,e)char*s,*t,*u,*e;{
    // set s to the position of the *next* check; u is the old position
    for(;s=index(u=s,32);) {
        // count the length of this word (incl. space); also fix s
        n=++s-u;
        // find the end of the string; assign temp pointer to start
        e=u+strlen(t=u);
        // count repetitions of the word
        for(c=0;                // number of repetitions
            (t+=n)              // advance temp pointer by length of word
            <e&&                // check that we haven't hit the end...
            !strncmp(u,t,n-1)&& // ...and the word matches...
            t[-1]==32;          // ...and the previous character was space
            ++c);               // if so, increment count
        // decide whether to remove stuttering
        c>1&&                    // count must be at least 2
        strpbrk(u,"aeiou")-1<s&& // word must contain a vowel
        // if so, move everything after the last occurrence back to the
        // beginning, and also reset s to u to start scanning from here again
        memmove(s=u,t-n,e-t+n+1);
    }
}

Dzięki @ user1475369 za 3 bajty i @ceilingcat za 2 bajty.

Klamka
źródło
-3 bajtów zastępując T>1&&strpbrkz T>1&strpbrk, r&&!strncmpz r&!strncmp, a &&t[-1]z &t[-1].
girobuz
@ceilingcat Twój link nie spełnia niektórych warunków testowych, ale 2 z 3 optymalizacji działają; dzięki!
Klamka
Zaproponuj bcmp()zamiastmemcmp()
ceilingcat 30.09.19
4

Perl 5 (-p), 34 bajty

Na podstawie usuniętej odpowiedzi Arnaulda.

s/(\b(\w*[aeiou]\w*) )\1+(?=\2)//g

Wypróbuj online!

Ponury
źródło
To produkuje „zab” dla „za a ab”. Nie sądzę, aby na tym wejściu wykryto zacięcie.
rekurencyjny
Naprawiono dzięki @recursive.
Grimmy,
2
Przejrzałem przypadki testowe i opracowałem wyrażenie regularne, ale znalazłem je już tutaj. Oczywiście oznacza to, że trywialny port Retina ma 30 bajtów.
Neil,
3

05AB1E , 30 29 28 bajtów

-1 bajt dzięki Kevin Cruijssen

#Rγε®y¬©žMÃĀiнkĀDygαΘ+∍]R˜ðý

Wypróbuj online!

05AB1E, bez wyrażeń regularnych, zdecydowanie nie wygląda na najlepsze narzędzie do tego zadania. Mimo to jakoś udało się ledwo pokonać Retinę.

#                     # split on spaces
 R                    # reverse the list of words
  γ                   # group consecutive identical words together

ε                   ] # for each group of words y:
 ®                    #  push the previous word on the stack (initially -1)
  y                   #  push another copy of y
   ¬                  #  push the first element without popping
    ©                 #  save the current word for the next loop
     žM               #  built-in constant aeiou
       ÃĀi          ] #  if the length of the intersection is non-zero:
           н          #   take the first element of y
            kĀ        #   0 if the previous word starts with this word, 1 otherwise
              D       #   duplicate
               yg     #   length of y (the number of consecutive identical words)
                 α    #   subtract the result of the startsWith check
                  Θ   #   05AB1E truthify (1 -> 1, anything else -> 0)
                   +  #   add the result of the startsWith check
                    ∍ #   set the length of y to that value
                      #  otherwise leave y unchanged

˜                     # flatten the modified list of groups of words
 R                    # reverse the list of words
  ðý                  # join with spaces
Ponury
źródło
1
Możesz usunąć gprzed Ā. Prawda w stylu Pythona spowoduje już powstanie 0pustych ciągów i 1niepustych ciągów.
Kevin Cruijssen
@KevinCruijssen nice find!
Grimmy,
1

Perl 6 , 45 bajtów

{S:g/<|w>(\S*<[aeiou]>\S*)\s$0+%%\s{}<?$0>//}

Wypróbuj online!

Prosta odpowiedź wyrażenia regularnego, która zastępuje wszystkie dopasowania jąkania pustym łańcuchem.

Jo King
źródło
1

Stax , 26 bajtów

å╬↓<▀.₧▀"╦n▐∞↨vß%ù:Qa3@=↔_

Uruchom i debuguj

Bezpośredni port z odpowiedzi perla @ Grimy'ego. Stax jest w stanie zmniejszyć dosłowny wzór wyrażenia regularnego i ma stałą samogłosek, która może się zmniejszyć [aeiou].

rekurencyjny
źródło
1

Czysty , 184 bajty

import StdEnv,Data.List,Text
$s=join[' '](f(group(split[' ']s)))
f[[a]:t]=[a:f t]
f[h=:[a:_]:t=:[[b:_]:_]]|intersect['aeiou']a==[]=h++f t|isPrefixOf a b=f t=if(h>[a,a])[a]h++f t
f[]=[]

Wypróbuj online!

Definiuje $ :: [Char] -> [Char], który dzieli ciąg wejściowy na spacje i grupuje identyczne elementy, które są następnie składane przez pomocnika f :: [[[Char]]] -> [[Char]], łącząc się przed powrotem.

Obrzydliwe
źródło