途切れた言葉を修正する


12

St音は、私たちの多くが経験したか、少なくとも見たことがある問題です。有名な音声認識ソフトウェアのほとんどは、speaking音の話に関して深刻な問題を抱えていますが、st音は理解できますが、修正することはできず、そのまま書くだけのソフトウェアを想像してみましょう。

そのようなソフトウェアによって書かれたテキストの例は、次のようになります:「注意してください」。この例では、「注意」が元の単語であり、「ca ca」がthe音の単語です。

チャレンジ

元の単語を保持したまま、入力から単語を削除することにより、st音の単語を修正するプログラムまたは関数を作成します。たとえば、「注意してください」の修正バージョンは注意してくださいとなります。

これは、すべての言語で最短の答えが得られます!

どもり言葉とは何ですか?

St音にはさまざまなバリエーションがあります。ただし、この課題を簡単にするために、次のルールに制限します。

  • St音の単語は、元の単語の未完成の部分または全体である場合があります。「未完成の部分」とは、元の単語がst音の単語から正確に始まることを意味します。たとえば、「OPE」「オープン」の両方がどもっための単語ことができ、「オープン」が、「ペン」以来の1にすることはできません「オープン」で始まらない「ペン」
  • St音の単語には、少なくとも1つのあいうえお母音が含まれている必要があります。たとえば、「star」「a」を含むため「start 」のst音の単語になりますが、「st」は上記の母音が含まれないためst音の単語にはなりません。
  • St音の単語は元の単語の前にのみ表示され、有効になるには少なくとも2回繰り返される必要があります(元の単語は繰り返しにはカウントされません)。たとえば、「oo open」は単語が途切れますが、「o open o」はそうではありません。元の単語の後の「o」はカウントされず、元の単語の前の「o」は少なくとも2回繰り返されないためです。ゴーゴーゴーゴーゴーゴーは、元の単語の前にst音の単語が5回繰り返されており、有効です。
  • 繰り返しst音の単語の単一のセットに混合形式を含めることはできず、単語は互いに正確に一致する必要があります。たとえば、「op o op open」は、単語がcount音としてカウントされません。一方、「o op op open」は、最初の「o」がここではまったく異なる単語と見なされ、2つの「op」「open」の st音単語としてカウントされるため、単語をst音にしています。
  • 複数の有効な繰り返し単語が連続して繰り返される場合、最後の元の単語のみが残ります。たとえば、「ooo op op op open」では、「oo o」の部分が最初の「op」の st音の単語と見なされるため、削除してから「op op op」「open」のopen音の単語と見なします彼らは、あまりにも除去しなければならないので、唯一の『オープン』どもっ言葉を除去した後に残されます。繰り返しst音単語の複数の有効なセットが左から右にのみ発生すると想定できるため、「op op ooo open」を修正すると「op op open」(別名

入力

  • 入力は、ASCII英語文字(az)、数字(0-9)、およびスペース文字のみを含む1行の文字列です。文字の大文字小文字は重要ではなく、小文字、大文字、またはその両方を受け入れることができますが、大文字小文字は同じままにして、出力で変更することはできません。
  • ["l","i","s","t"," ","o","f"," ","l","e","t","t","e","r","s"]文字列の代わりに文字のリスト(など)を使用できますが、単語のリストは使用できません。言語の入力構造が異なる場合は、それを使用します。重要なのは、入力を単語で区切るべきではないため、一部の言語で単語を区切るコストが実際に他の創造的なソリューションを引き起こす可能性があるということです。
  • 入力には、何も含まれないか、1つまたは複数のst音が含まれる場合があります。
  • 単語や数字は単一のスペースで区切られ、入力には隣同士に二重のスペースは含まれません。

出力

  • 文字列、文字のリスト、または言語内の適切な構造で、st音の単語はすべて入力から削除されます。
  • 出力ワードは、正確に1つのスペースで区切る必要があります(入力と同じ)。
  • 単一の先頭と末尾の改行またはスペースが許可されます。

標準的な抜け穴は禁止されています。

テストケース

st音のない言葉:

"hello world" => "hello world"

繰り返されるutter音単語の単一インスタンス:

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

st音の言葉はありません。言及された母音はありません。

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

同じリピートグループ内の異なる形式のst音単語はカウントされません。

"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は、「どもり言葉とは」の下の最後の項目を読んだ場合 この問題について説明しました。「wat wat」は「wa」のst音語ではないため、一度修正するだけなので、「wat wat wat water」を取得したら、新たに形成されたst音語を削除するために再度修正することはありません。しかし、「wa wa」は最初の「wat」であり、「wat wat」は「water」のwater音語でもあるため、「wa wa wat wat water」のような逆の場合、結果は「water」になります。
Night2

結構です、もう修正できなくなるまで修正を続けるのは理にかなっていると言っていましたが、1回の繰り返しにも焦点を当てるという議論を見ることができます。
ジョナ

回答:


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は確かに正規表現の簡潔さと競合することはできません...

これは特に読みにくいです。なぜなら、関数全体を1つのネストされたforループのペアに折りたたんだからです(本体はありません!)。これにより、評価順序がすべて不安定になります。最初に近いコードが実際に最後に実行されます。

ここで私のお気に入りのトリックはstrpbrk(u,"aeiou")-1<s。これは、繰り返される単語に母音が含まれているかどうかを確認するために使用されます。u繰り返される単語の先頭をs指し、単語の2番目の繰り返しを指します。例えば:

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

strpbrk次に、の"aeiou"後に現れる最初の文字を見つけuます。(この場合は、'u'直後です。)次に、これが前sにあることを確認して、単語に母音が含まれていることを確認します。しかし、わずかな問題がありstrpbrkます- 文字列全体に母音がない場合に返されるNULL(つまり0)。この問題を解決するために、私は単純に回動する、1を減算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バイトのために。


-3置き換えることによってバイトT>1&&strpbrkT>1&strpbrkr&&!strncmpr&!strncmp、と&&t[-1]を有します&t[-1]
ギロブズ


@ceilingcatリンクはテストケースの一部に失敗しますが、これら3つの最適化のうち2つが機能します。ありがとう!
ドアノブ

提案するbcmp()代わりにmemcmp()
ceilingcat

4

Perl 5(-p)、34バイト

Arnauldの削除された回答に基づきます。

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

オンラインでお試しください!


これにより、「za a ab」に対して「zab」が生成されます。その入力にスタッターが検出されるとは思わない。
再帰的

@再帰的な感謝、修正。
グリムミー

2
私はテストケースを見て正規表現を考案しましたが、ここでそれを見つけるだけです。当然、これは簡単なRetinaポートが30バイトであることを意味します。
ニール

3

05AB1E30 29 28バイト

-1バイト、Kevin Cruijssenに感謝

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

オンラインでお試しください!

05AB1Eには正規表現がないため、このタスクに最適なツールとは思えません。それでも、どういうわけかRetinaをかろうじて倒すことができます。

#                     # 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前に削除できĀます。PythonスタイルのTruthifyは、すでに0空の文字列と空でない文字列の結果に1なります。
ケビンCruijssen

@KevinCruijssen素敵な発見!
グリムミー



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

オンラインでお試しください!

Defines $ :: [Char] -> [Char]は、入力文字列をスペースで分割し、同一の要素をグループ化します。これらの要素は、ヘルパーによって折りたたまれてf :: [[[Char]]] -> [[Char]]から戻ります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.