แก้ไขคำพูดติดอ่างของฉัน


12

การพูดติดอ่างเป็นปัญหาที่พวกเราหลายคนอาจเคยมีประสบการณ์หรืออย่างน้อยก็เห็นมัน แม้ว่าซอฟต์แวร์จดจำคำพูดที่โด่งดังส่วนใหญ่มีปัญหาร้ายแรงเกี่ยวกับการพูดติดอ่างลองนึกภาพซอฟต์แวร์ที่เข้าใจการพูดติดอ่าง แต่ไม่สามารถแก้ไขได้และเขียนเฉพาะตามที่เป็น

ตัวอย่างข้อความที่เขียนโดยซอฟต์แวร์ดังกล่าวสามารถเป็นเช่นนี้"โปรด CA CA ระมัดระวัง" ในตัวอย่างนี้"ระวัง"คือคำเดิมและ"ca ca"เป็นคำพูดติดอ่าง

ท้าทาย

เขียนโปรแกรมหรือฟังก์ชั่นที่แก้ไขคำพูดติดอ่างโดยการลบคำเหล่านั้นออกจากอินพุตขณะที่รักษาคำเดิมไว้ ยกตัวอย่างเช่นการแก้ไขรุ่นของ"โปรด CA CA ระวัง"จะเป็น"โปรดระวัง"

นี่คือคำตอบที่สั้นที่สุดในทุกภาษาชนะ!

คำพูดติดอ่างอะไร

การพูดติดอ่างมีหลายรูปแบบที่แตกต่างกัน แต่เพื่อความเรียบง่ายของความท้าทายนี้เราจะ จำกัด ให้เป็นกฎต่อไปนี้:

  • คำพูดติดอ่างอาจเป็นส่วนที่ไม่สมบูรณ์หรือเป็นคำเดิมทั้งหมด โดย "ส่วนที่ไม่สมบูรณ์" ฉันหมายความว่าคำดั้งเดิมควรเริ่มต้นด้วยคำที่พูดติดอ่าง ยกตัวอย่างเช่น"ope"และ"เปิด"ทั้งสองสามารถจะเป็นคำพูดติดอ่าง"เปิด"แต่"ปากกา"ไม่สามารถเป็นหนึ่งตั้งแต่"เปิด"ไม่ได้เริ่มต้นด้วย"ปากกา"
  • คำพูดติดอ่างต้องมีสระ"aeiou"อย่างน้อยหนึ่งแห่ง ตัวอย่างเช่น"ดาว"อาจเป็นคำพูดติดอ่างของคำว่า"เริ่มต้น"เนื่องจากมี"a"แต่"st"ไม่สามารถเป็นคำพูดติดอ่างได้เนื่องจากไม่มีสระใด ๆ ที่กล่าวถึง
  • คำพูดติดอ่างสามารถปรากฏต่อหน้าคำเดิมและควรทำซ้ำอย่างน้อยสองครั้งเพื่อให้ถูกต้อง (คำเดิมไม่นับในการทำซ้ำ) ตัวอย่างเช่น"oo open"มีคำพูดติดอ่าง แต่"o open o"ไม่ได้เพราะ"o"หลังจากคำดั้งเดิมไม่ได้นับและ"o"ก่อนคำเดิมไม่ซ้ำอย่างน้อยสองครั้ง "go go go go go go"มีคำพูดติดอ่างห้าคำต่อหน้าคำเดิมและถูกต้อง
  • คำที่พูดติดอ่างเพียงชุดเดียวไม่สามารถมีรูปแบบผสมได้และคำนั้นควรเหมือนกัน ตัวอย่างเช่น"op o op open"จะไม่นับเป็นคำพูดติดอ่าง บนมืออื่น ๆ"o op op เปิด"ได้พูดติดอ่างคำเพราะเป็นครั้งแรกที่"o" ที่ถูกมองว่าเป็นคำที่แตกต่างกันทั้งที่นี่และทั้งสอง"สหกรณ์" sจะถูกนับเป็นคำ stuttered ของ"เปิด"
  • ในกรณีที่ชุดคำพูดติดอ่างที่ถูกต้องหลายชุดติดกันแล้วจะมี แต่คำเดิมเท่านั้นที่เหลืออยู่ ตัวอย่างเช่นใน"ooo op op op open"ส่วน"oo o"ถูกมองว่าเป็นคำพูดติดอ่างของคำว่า"op"แรกดังนั้นพวกเขาจึงควรลบออกและจากนั้น"op op op"ถูกมองว่าเป็นคำพูดติดอ่างของ"open "และควรลบเช่นกันดังนั้นเฉพาะ" open "เท่านั้นที่จะถูกทิ้งหลังจากลบคำที่พูดติดอ่าง คุณสามารถสมมติว่าคำพูดติดอ่างที่ถูกต้องหลายชุดเกิดขึ้นจากซ้ายไปขวาเท่านั้นดังนั้นการแก้ไข"op op ooo open"จะส่งผลให้"op op open" (aka

อินพุต

  • อินพุตเป็นสตริงบรรทัดเดียวที่มีตัวอักษรภาษาอังกฤษ 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 ถ้าคุณอ่านรายการสุดท้ายภายใต้คำพูดติดอ่างอะไร ฉันได้อธิบายเรื่องนี้แล้ว "วัดวัด" ไม่ใช่คำพูดติดอ่างสำหรับ "วา" และเราแก้ไขเพียงครั้งเดียวดังนั้นเมื่อเราได้รับ "ดื่มวัดน้ำ" เราไม่แก้ไขอีกครั้งเพื่อลบคำพูดติดอ่างที่เกิดขึ้นใหม่ แต่ในกรณีตรงกันข้ามเช่น "wa wa wat wat water" ผลลัพธ์จะเป็น "water" เพราะ "wa wa" เป็นคำที่พูดติดอ่างในคำว่า "wat" และ "wat wat" เป็นคำที่พูดติดอ่างของ "water"
กลางคืน 2

โอเคพอแล้วฉันแค่บอกว่ามันจะสมเหตุสมผลที่จะแก้ไขจนกว่าคุณจะทำไม่ได้อีกต่อไป แต่ฉันสามารถเห็นการโต้เถียงสำหรับการมุ่งเน้นไปที่การทำซ้ำครั้งเดียวเช่นกัน
Jonah

คำตอบ:


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 แน่นอนไม่สามารถแข่งขันกับความกะทัดรัดของ regex ...

คนนี้อ่านยากเป็นพิเศษเพราะฉันสิ้นสุดการยุบฟังก์ชั่นทั้งหมดไปเป็น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()
ceilingcat

4

Perl 5 (-p), 34 ไบต์

ตามคำตอบที่ถูกลบของ Arnauld

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

ลองออนไลน์!


สิ่งนี้จะสร้าง "zab" สำหรับ "za a ab" ฉันไม่คิดว่าควรตรวจพบการพูดติดอ่างในอินพุตนั้น
เรียกซ้ำ

@ ขอบคุณขอบคุณถาวร
Grimmy

2
ฉันดูกรณีทดสอบและคิดค้น regex เพื่อค้นหามันที่นี่เท่านั้น ตามปกติแล้วนี่หมายความว่าพอร์ต Retina ขนาดเล็กคือ 30 ไบต์
Neil

3

05AB1E , 30 29 28 ไบต์

-1 ไบต์ต้องขอบคุณ Kevin Cruijssen

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

ลองออนไลน์!

05AB1E ไม่มี regexes ดูไม่เหมือนเครื่องมือที่ดีที่สุดสำหรับงานนี้ แต่ถึงกระนั้นก็ยังพอที่จะเอาชนะ 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-style factify จะส่งผล0ให้สตริงว่างและสตริงที่1ไม่ว่างแล้ว
Kevin Cruijssen

@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]]เข้าร่วมก่อนกลับมา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.