말더듬을 수정


12

말더듬 은 많은 사람들이 경험했거나 적어도 본 적이있는 문제입니다. 유명한 음성 인식 소프트웨어의 대부분은 말더듬에 심각한 문제가 있지만 말더듬을 이해하지만 수정할 수는없고 그대로 쓰는 소프트웨어를 상상해 봅시다.

이러한 소프트웨어에 의해 작성된 텍스트의 예는 다음과 같습니다. "주의하십시오" . 이 예에서 "주의" 는 원래 단어이고 "ca ca" 는 말더듬입니다.

도전

끊어진 단어를 원래 단어는 그대로 유지하면서 입력에서 제거하여 수정하는 프로그램이나 함수를 작성하십시오. 예를 고정 버전 "주의하시기 바랍니다 캘리포니아 캘리포니아" 가 될 것입니다 "주의 해주십시오" .

이것은 모든 언어 승리에서 가장 짧은 !

말 더미 란 무엇입니까?

말더듬에는 여러 가지 변형이 있습니다. 그러나이 과제를 간단하게하기 위해 다음 규칙으로 제한합니다.

  • 말더듬은 단어는 원래 단어의 일부 또는 전체가 될 수 없습니다. "완료되지 않은 부분"이란 말은 원래 단어가 말 더미로 정확하게 시작해야한다는 것을 의미합니다. 예를 들어 "OPE""개방" 모두는 말더듬이에 대한 단어 일 수있다 "열기" ,하지만 "펜" 이후 하나가 될 수 없다 "열기" 로 시작하지 않는 "펜" .
  • 말더듬 된 단어는 "aeiou" 모음 중 하나 이상을 포함해야합니다 . 예를 들어, "star""a"를 포함하고 있기 때문에 "start"에 대해 말더듬 된 단어 수 있지만 "st" 는 언급 된 모음을 포함하지 않으므로 말더듬 된 단어 수 없습니다.
  • 말더듬 단어는 원래 단어 앞에만 나타날 수 있으며 유효하려면 두 번 이상 반복해야합니다 (원래 단어는 반복에 포함되지 않음). 예를 들어 "oo open" 은 단어를 더듬었지만 "o open o" 는 그렇지 않습니다 . 원래 단어 뒤의 "o" 는 계산되지 않으며 원래 단어 앞의 "o" 는 두 번 이상 반복되지 않기 때문입니다. "go go go go go go go" 는 원래 단어 앞에 5 번의 말더듬 단어가 있으며 유효합니다.
  • 반복되는 말더듬 단어 하나가 혼합 된 형태를 포함 할 수 없으며 단어는 서로 정확히 같아야합니다. 예를 들어 "op o op open" 은 말더듬으로 계산되지 않습니다. 반면에 "o op op open" 은 첫 번째 "o" 가 여기에서 완전히 다른 단어로 표시되고 두 "op""open" 의 더듬 거리는 단어로 간주되기 때문에 단어가 더듬어 졌습니다.
  • 여러 번의 반복되는 말더듬 단어가 서로 바로 유효한 경우에는 마지막 원래 단어 만 남습니다. 예를 들어, "ooo op op op open" 에서 "oo o" 부분은 첫 번째 "op" 의 말더듬 단어로 표시 되므로 제거해야합니다. 그런 다음 "op op op""open" 말더듬 단어로 표시됩니다 " 도 제거해야하므로 말이 끊긴 단어를 제거한 후에는 "열기 " 만 남습니다. 당신은 너무 고정 만에서 왼쪽에서 오른쪽으로 일어날 반복 더듬 단어의 여러 유효한 세트를 가정 할 수있다 "영업 이익은 OOO 개방" 을 초래할 것 "오픈 연산 연산" 일명 (

입력

  • 입력은 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"규칙이 재귀 적으로 적용되어 이것이 "음용수"가되도록하는 것 같습니다.
Jonah

2
@Jonah 마지막 단어 를 읽는다면 말더듬이 란 무엇입니까? 나는이 문제를 설명했다. "wat wat"는 "wa"에 대한 말을 더듬 지 않으며 한 번만 수정하므로 "Wat wat wat water"를 얻은 후에는 새로 작성된 말을 더듬기 위해 다시 수정하지 않습니다. 그러나 "wa wa wat wat water"와 같은 반대의 경우에는 "wa wa"가 말을 더듬고 "wat wat"도 "물"을 더듬기 때문에 "물"이됩니다.
Night2

충분히 공평합니다. 더 이상 할 수 없을 때까지 계속 고치는 것이 합리적이라고 말했지만 단일 반복에 중점을 둔 주장도 볼 수 있습니다.
요나

답변:


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). 이 문제를 해결하려면 단순히 전환하는 일을 빼기 00xffffffffffffffff인한 오버 플로우 (내 컴퓨터에서). 포인터의 최대 값이므로이 값이 결정보다 큰 것으로 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 바이트.


, with 및 로 교체 T>1&&strpbrk하여 -3 바이트 . T>1&strpbrkr&&!strncmpr&!strncmp&&t[-1]&t[-1]
girobuz


@ceilingcat 링크가 테스트 사례 중 일부에 실패하지만이 3 가지 최적화 중 2 개가 작동합니다. 감사!
Doorknob

bcmp()대신 추천memcmp()
천장 고양이

4

Perl 5 (-p), 34 바이트

Arnauld의 삭제 된 답변을 기반으로합니다.

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

온라인으로 사용해보십시오!


"za a ab"에 대해 "zab"가 생성됩니다. 그 입력에서 더듬기가 감지되어야한다고 생각하지 않습니다.
재귀

@ 재귀 감사합니다.
Grimmy

2
나는 테스트 사례를보고 정규식을 고안했다. 당연히 이것은 사소한 Retina 포트가 30 바이트라는 것을 의미합니다.

3

05AB1E , 30 29 28 바이트

Kevin Cruijssen 덕분에 -1 바이트

#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전과 Ā. 파이썬 스타일의 진리는 이미 0빈 문자열과 비어 있지 않은 문자열을 초래 1합니다.
Kevin Cruijssen

@KevinCruijssen 좋은 발견!
Grimmy


1

Stax , 26 바이트

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

실행 및 디버깅

@Grimy의 펄 답변에서 직접 포트. Stax는 정규식 패턴 리터럴을 축소 할 수 있으며 모음 상수가있어 축소 할 수 [aeiou]있습니다.


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]]리턴하기 전에 결합이.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.