Kekemeli sözlerimi düzelt


12

Kekemelik , çoğumuzun deneyimlediği veya en azından gördüğü bir sorundur. Ünlü konuşma tanıma yazılımlarının çoğunun kekemeli konuşma ile ilgili ciddi sorunları olsa da, kekemeliği anlayan, ancak bunları düzeltemeyen ve sadece olduğu gibi yazan bir yazılım düşünelim.

Böyle bir yazılım tarafından yazılmış bir örnek şöyle olabilir: "lütfen dikkatli olun" . Bu örnekte "dikkatli" orijinal kelime ve "ca ca" ise kekemeli kelimelerdir.

Meydan okuma

Orijinal kelimeleri korurken kekemeli kelimeleri girişten kaldırarak düzelten bir program veya işlev yazın. Örneği sabit sürümü için "lütfen dikkatli olun ca ca" olacağını "lütfen dikkatli olun" .

Bu , her dilde en kısa cevap kazanır!

Kekemeli kelimeler nedir?

Kekemeliğin birçok farklı varyasyonu vardır. Ancak bu zorluğun basitliği için, bunu aşağıdaki kurallarla sınırlayacağız:

  • Kekemeli kelimeler orijinal kelimenin tamamlanmamış bir parçası veya tamamı olabilir. "Tamamlanmamış kısım" ile, orijinal kelimenin tam olarak kekemeli kelimeyle başlaması gerektiği anlamına gelir. Örneğin "ope" ve "açık" hem duraksamalı kelimesine olabilir "açık" , ama "kalem" beri bir olamaz "açık" ile başlamıyor "kalem" .
  • Kekemelik kelimeler "aeiou" sesli harflerinden en az birini içermelidir . Örneğin "yıldız" , "a" içerdiğinden "başlangıç" için kesikli bir kelime olabilir , ancak "st" , belirtilen sesli harfleri içermediği için kekemeli bir kelime olamaz.
  • Kekemeli kelimeler sadece orijinal sözcükten önce görünebilir ve geçerli olmak için en az iki kez tekrarlanmalıdır (orijinal kelime tekrarlarda sayılmaz). Örneğin "oo open" sözcükleri kesik kesiktir, ancak "o open o" söz konusu değildir, çünkü orijinal sözcükten sonraki "o" sayılmaz ve orijinal sözcükten önceki "o" en az iki kez tekrarlanmaz. "git git git git git" orijinal kelimeden önce kekemeli kelimelerin beş tekrarına sahiptir ve geçerlidir.
  • Tekrarlanan kekemeli kelimelerin tek bir kümesi karışık formlar içeremez ve kelimeler birbirleri gibi olmalıdır. Örneğin, "op o op open" kekemelik kelimeler olarak sayılmaz. Öte yandan, "o op op open" sözcükleri kekemeli çünkü ilk "o" burada tamamen farklı bir kelime olarak görülüyor ve iki "op" , "açık" kekemeli kelimeleri olarak sayılıyor .
  • Birbirinden hemen sonra tekrarlanan kekemeli kelimelerin birden fazla geçerli kümesinde sadece son orijinal sözcük kalır. Örneğin, "ooo op op op open" da , "oo o" kısmı ilk "op" kelimesinin düzensiz kelimeleri olarak görülür , bu yüzden kaldırılmaları ve daha sonra "op op op" ifadesinin "open" düzensiz kelimeleri olarak görülmesi " ve bunlar da kaldırılmalıdır, bu nedenle kekemeli kelimelerin kaldırılmasından sonra yalnızca " açık " bırakılacaktır. Çok sabitleme, sadece soldan sağa başına gelen tekrarlanan stuttered kelimelerin birden fazla geçerli setleri varsayabiliriz "op op ooo açık" olmasına neden olur "açık op op" aka (

Giriş

  • Giriş yalnızca ASCII İngilizce harfler (az), rakamlar (0-9) ve boşluk karakterlerini içeren tek satırlık bir dizedir. Harf muhafazası önemli değildir ve küçük veya büyük harf veya her ikisini birden kabul etmeye karar verebilirsiniz, ancak kasa aynı kalmalıdır ve çıktıda değiştiremezsiniz.
  • ["l","i","s","t"," ","o","f"," ","l","e","t","t","e","r","s"]Dize yerine bir harf listesi (gibi ) kullanabilirsiniz, ancak sözcük listesini kullanamazsınız. Dilinizin farklı bir giriş yapısı varsa, onu kullanın. Mesele, girdinin kelimelerle ayrılmaması gerektiğidir, bu nedenle bazı dillerde kelimeleri ayırmanın maliyeti aslında diğer yaratıcı çözümleri tetikleyebilir.
  • Giriş, içinde hiç, bir veya birden fazla kekemeli kelime içerebilir.
  • Kelimeler ve / veya sayılar tek bir boşlukla ayrılır ve girdi yan yana iki boşluk içermez.

Çıktı

  • Bir dize veya bir harf listesi ya da girdideki tüm kesilmiş sözcüklerin kaldırıldığı dilinizdeki uygun yapı.
  • Çıktı sözcükleri tam olarak bir boşlukla (girdi ile aynı) ayrılmalıdır.
  • Tek satır başı ve sondaki satır başı veya boşluk kullanılabilir.

Standart boşluklar yasaktır.

Test senaryoları

Kekemelik kelime yok:

"hello world" => "hello world"

Tekrarlanan kekemeli kelimelerin tek bir örneği:

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

Tekrarlanan kekemeli kelimelerin birden fazla örneği:

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

Kekemeli kelimeler yok, yeterince tekrarlanmadı:

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

Kekemelik kelimeler yok, sözü edilen sesli harflerden hiçbirine sahip değilsiniz:

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

Sayılar kekemelik kelimeler değil, sözü edilen sesli harflerden hiçbirine sahip değiller:

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

Ancak hem sesli harflere hem de sayılara sahip bir kelimede kekeme sözleri olabilir:

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

Aynı tekrar grubundaki kekemeli kelimelerin farklı biçimleri sayılmaz:

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

Birbiri ardına sürekli kekemeli kelime grupları için sadece son orijinal kelimeyi sakla:

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

Bu, birbiri ardına çok sayıda sürekli kekemeli kelime kümesi değildir:

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

Boş giriş:

"" => ""

Yorumlardan daha fazla vaka:

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

Yukarıdaki test senaryolarının kopyalanması kolay bir listesi:

"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"kuralın tekrar tekrar uygulanması gerektiği gibi görünüyor, böylece bu "içecek su" olur
Jonah

2
@Jonah Eğer kekemelik kelimeler nedir? Bu konuyu açıkladım. "wat wat" "wa" için kekemeli kelimeler değildir ve sadece bir kez düzeltiriz, bu yüzden "wat wat su içtikten sonra" yeni oluşan kekemeli kelimeleri kaldırmak için tekrar düzeltmeyiz. Ama "wa wa wat wat su" gibi bir ters durumda sonuç "su" olacaktır, çünkü "wa wa" ilk "wat" ve "wat wat" için kekemeli sözcükler de "su" kekemeli kelimelerdir.
night2

Tamam yeterince adil, daha fazla yapamayana kadar düzeltmeye devam etmenin mantıklı olacağını söylüyordum, ama tek bir yinelemeye odaklanma argümanını da görebiliyorum.
Jonah

Yanıtlar:


6

C (GCC), 183 , 180 178 bayt

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

Çevrimiçi deneyin!

C kesinlikle normal ifadenin kısalığı ile rekabet edemez ...

Bunu okumak özellikle zor çünkü tüm işlevi tek bir iç içe çift fordöngüye (bedensiz!) Daralttım. Bu değerlendirme sırasını tamamen sakat yapar - başlangıca yakın kod aslında sonuncuyu yürütür.

Buradaki favori numaram strpbrk(u,"aeiou")-1<s. Bu, tekrarlanan sözcüğün sesli harf içerip içermediğini kontrol etmek için kullanılır. utekrarlanan kelimenin başlangıcını gösterir ve kelimenin sikinci tekrarını gösterir; Örneğin:

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

strpbrksonra içinde "aeiou"görünen ilk karakteri bulur u. (Bu durumda, 'u'hemen sonra gelir.) Sonra s, kelimenin bir sesli harf içerdiğini doğrulamak için bunun daha önce gelip gelmediğini kontrol edebiliriz . Ancak küçük bir sorun var - dizenin tamamında sesli harf yoksa strpbrkdöner NULL(yani 0). Bunu düzeltmek için, ben sadece döner, hangi 1 çıkarma 0içine 0xffffffffffffffffnedeniyle taşması (benim makinede). Bir işaretçinin maksimum değeri olduğundan, bu kesinlikle daha büyüktür sve denetimin başarısız olmasına neden olur.

İşte biraz daha eski bir sürüm (kontrol akışını karıştıran dönüşümden önce) yorumlarla:

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

Sayesinde @ user1475369 3 byte ve için @ceilingcat 2 byte için.


-3 değiştirerek bayt T>1&&strpbrkile T>1&strpbrk, r&&!strncmpile r&!strncmp, ve &&t[-1]ile &t[-1].
girobuz


@ ceilingcat Bağlantınız bazı test senaryolarında başarısız oluyor, ancak bu 3 optimizasyondan 2'si çalışıyor; Teşekkürler!
Kapı tokmağı

Öner bcmp()yerinememcmp()
ceilingcat

4

Perl 5 (-p), 34 bayt

Arnauld'un silinen cevabına dayanarak.

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

Çevrimiçi deneyin!


Bu "za a ab" için "zab" üretir. Bu girdide bir kekemelik olması gerektiğini düşünmüyorum.
özyinelemeli

@ recursive teşekkürler, sabit.
Grimmy

2
Test örneklerine baktım ve sadece burada bulmak için bir regex tasarladım. Doğal olarak bu önemsiz Retina portunun 30 bayt olduğu anlamına gelir.
Neil

3

05AB1E , 30 29 28 bayt

Kevin Cruijssen sayesinde -1 bayt

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

Çevrimiçi deneyin!

05AB1E, normal ifadeleri olmadan, kesinlikle bu görev için en iyi araç gibi görünmüyor. Yine de, bir şekilde Retina'yı zar zor yenmeyi başarıyor.

#                     # 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
'Den gönce kaldırabilirsiniz Ā. Python tarzı truthify zaten 0boş dizeler ve 1boş olmayan dizeler için sonuçlanacaktır .
Kevin Cruijssen

@KevinCruijssen güzel bulmak!
Grimmy



1

Temiz , 184 bayt

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

Çevrimiçi deneyin!

Tanımlar $ :: [Char] -> [Char]boşluklar ve gruplar daha sonra yardımcı göre daraltılır aynı elemanları giriş dize böler, f :: [[[Char]]] -> [[Char]]dönmeden önce birleştirme.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.