Виправити мої заїкані слова


12

Заїкання - це проблема, яку багато хто з нас, можливо, відчували або принаймні бачили. Хоча більшість відомих програмного забезпечення для розпізнавання мови мають серйозні проблеми із заїканням мови, давайте уявимо програмне забезпечення, яке розуміє заїкання, але не може їх виправити, а записує їх лише як є.

Приклад написаного текстом такого програмного забезпечення може бути таким: "будьте обережні" . У цьому прикладі "обережно" є початкове слово, а "ca ca" - заїкані слова.

Виклик

Напишіть програму або функцію, яка фіксує заїкані слова, видаляючи їх із введення, зберігаючи вихідні слова. Наприклад, виправлена ​​версія "будь ласка, будьте обережні", це "будь ласка, будьте обережні" .

Це , найкоротша відповідь на всіх мовах виграє!

Що таке заїкані слова?

Заїкання має багато різних варіацій. Але для простоти цього завдання ми обмежимось такими правилами:

  • Заїкані слова можуть бути незавершеною частиною або цілим початковим словом. Під "незавершеною частиною" я маю на увазі, що початкове слово має починатися саме з заїканого слова. Наприклад, "ope" і "open" обидва можуть бути заїканим словом для "open" , але "pen" не може бути одним, оскільки "open" не починається з "pen" .
  • Заїкані слова повинні містити принаймні один з голосних "aeiou" . Наприклад, "зірка" може бути заїканим словом для "почати", оскільки воно містить "а" , але "st" не може бути заїканим словом, оскільки воно не містить жодного із згаданих голосних.
  • Заїкані слова можуть з’являтися лише перед початковим словом і повинні бути повторені принаймні два рази, щоб бути дійсними (оригінальне слово не враховується у повторах). Наприклад, "oo open" має заїкані слова, але "o open o" не робить, тому що "o" після початкового слова не рахується, а "o" перед початковим словом не повторюється принаймні два рази. "go go go go go go" має п'ять повторів заїканих слів перед початковим словом і є дійсним.
  • Один набір повторних заїканих слів не може містити змішаних форм, і слова повинні бути абсолютно однаковими. Наприклад, "op o op open" не вважається заїканими словами. З іншого боку, "o op op open" має заїкані слова, тому що перше "o" тут розглядається як зовсім інше слово, а два "op" s зараховуються як заїкані слова "open" .
  • У випадку кількох дійсних наборів повторних заїканих слів відразу один за одним залишається лише останнє оригінальне слово. Наприклад, в «ооо оп оп оп відкритим» , то «оо о» частини розглядається як заїкався слова першого «оп» , тому вони повинні бути видалені , а потім «оп оп оп» розглядається як заїкався слова «відкрита ", і їх також слід видалити, тому після видалення заїканих слів залишиться лише " відкритий " . Можна припустити, що кілька дійсних наборів повторних заїканих слів трапляються лише зліва направо, тому фіксація "op op ooo open" призведе до "op op open" (ака

Вхідні дані

  • Введення - це рядковий рядок, що містить лише англійські літери ASCII (az), цифри (0-9) та пробіли. Обкладинка букви не важлива, і ви можете вирішити прийняти малі або великі літери або обидва з них, але корпус повинен залишатися таким же, і ви не можете змінити його у висновку.
  • Ви можете використовувати список букв (як ["l","i","s","t"," ","o","f"," ","l","e","t","t","e","r","s"]) замість рядка, але ви не можете використовувати список слів. Якщо ваша мова має іншу структуру введення, використовуйте її. Справа в тому, що введення не слід розділяти словами, тому вартість розділення слів на деяких мовах може насправді викликати інші творчі рішення.
  • Вхід може містити в собі жодне, одне або кілька заїканих слів.
  • Слова та чи числа розділені одним пробілом, і вхід не буде містити подвійних пробілів поруч.

Вихідні дані

  • Рядок або список букв або відповідна структура вашої мови з усіма заїканими словами, видаленими з введення.
  • Вихідні слова повинні бути розділені рівно одним пробілом (таким же, як і введення).
  • Допускається одинарний провідний та кінцевий новий рядок або пробіл.

Стандартні лазівки заборонені.

Тестові справи

Немає заїканих слів:

"hello world" => "hello world"

Один екземпляр повторних заїканих слів:

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

Кілька випадків повторного заїкання слів:

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

Без заїканих слів, недостатньо повторених:

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

Немає заїканих слів, не має жодного згаданих голосних:

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

Числа - це не заїкані слова, вони не мають жодного із згаданих голосних:

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

Але слово з голосними чи числами може мати заїкані слова:

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

Різні форми заїканих слів у одній групі повторень не зараховуються:

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

Для декількох безперервних наборів заїканих слів відразу один за одним зберігайте лише останнє початкове слово:

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

Це не випадок безлічі безперервних наборів заїканих слів відразу один за одним:

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

Порожній вхід:

"" => ""

Більше випадків від коментарів:

"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"

Легкий для копіювання список вищевказаних тестів:

"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"

2
"drink wat wat wa wa water" => "drink wat wat water"Насправді здається, що правило повинно застосовуватися рекурсивно, так що це стає "пити воду"
Йона,

2
@Jonah, якщо ви прочитали останній пункт у розділі Що таке заїкані слова? Я пояснив це питання. "Ват Ват" не є заїканими словами для "ва", і ми фіксуємо лише один раз, тому, як тільки ми отримаємо "пити ват Ват води", ми не будемо фіксувати знову, щоб видалити новоутворені заїкані слова. Але у зворотному випадку, наприклад, "wa wa wat wat water" результат буде "water", оскільки "wa wa" є заїканими словами для першого "wat", а "wat wat" - це також заїкані слова "water".
Ніч2,

Добре справедливо, я просто говорив, що було б сенс продовжувати фіксувати, поки ви більше не зможете, але я також бачу аргумент для фокусування на одній ітерації.
Іона

Відповіді:


6

C (gcc), 183 180 178 байт

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);}

Спробуйте в Інтернеті!

Ну, C, звичайно, не може конкурувати зі стислістю регулярних виразів ...

Цього особливо важко читати, оскільки я закінчив згортання всієї функції в одну вкладену пару forциклів (без тіла!). Це робить замовлення на оцінку все вибагливим - код на початку справді виконується останнім.

Мій улюблений трюк тут strpbrk(u,"aeiou")-1<s. Це використовується для перевірки, чи містить повторне слово голосні. uвказує на початок повторного слова і sвказує на друге повторення слова; наприклад:

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

strpbrkпотім знаходить перший символ у "aeiou"тому, що з’являється після u. (У цьому випадку це 'u'відразу після.) Тоді ми можемо перевірити, що це відбувається раніше, sщоб перевірити, чи слово містить голосну. Але є невелика проблема - strpbrkповертається NULL(тобто 0), якщо в усьому рядку немає голосної. Щоб виправити це, я просто віднімаю 1, який перетворюється 0на 0xffffffffffffffff(на моїй машині) через переповнення. Будучи максимальним значенням вказівника, це, очевидно, більше, ніж sвикликає збій чека.

Ось трохи старша версія (до трансформації, яка заплутала контрольний потік) з коментарями:

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);
    }
}

Завдяки @ user1475369 за 3 байти та @ceilingcat за 2 байти.


-3 байти шляхом заміни T>1&&strpbrkна T>1&strpbrk, r&&!strncmpз r&!strncmpі &&t[-1]на &t[-1].
girobuz


@ceilingcat Ваше посилання не працює в деяких тестових випадках, але 2 з цих 3 оптимізації працюють; Дякую!
Дверна ручка

Запропонувати bcmp()замістьmemcmp()
roofcat

4

Perl 5 (-p), 34 байти

На основі видаленої відповіді Арнольда.

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

Спробуйте в Інтернеті!


Це виробляє "zab" для "za a ab". Я не думаю, що в цьому вході має бути виявлено заїкання.
рекурсивна

@ рекурсивна подяка, виправлено.
Grimmy

2
Я переглянув тестові приклади і створив регекс, тільки щоб знайти його вже тут. Природно, це означає, що тривіальний порт сітківки становить 30 байт.
Ніл

3

05AB1E , 30 29 28 байт

-1 байт завдяки Kevin Cruijssen

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

Спробуйте в Інтернеті!

05AB1E, не маючи регулярних виразів, точно не виглядає як найкращий інструмент для виконання цього завдання. І все-таки йому якось вдається лише ледь бити Ретіну.

#                     # 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

1
Ви можете видалити gдо Ā. Програма truthify в стилі Python вже призведе 0до порожніх рядків і 1для не порожніх рядків.
Кевін Кройсейсен

@KevinCruijssen приємна знахідка!
Grimmy



1

Чисто , 184 байти

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[]=[]

Спробуйте в Інтернеті!

Визначає $ :: [Char] -> [Char], який розбиває вхідний рядок на пробіли та групує однакові елементи, які згортаються помічником f :: [[[Char]]] -> [[Char]], приєднуючись до повернення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.