ลบพหูพจน์ที่ไม่ชัดเจนออก!


21

การเขียนโปรแกรมมีความแข็งแกร่งมาก คุณไม่สามารถบอกโปรแกรมที่จะ "เอาท์พุทนับกล้วย" print(bananas)คุณต้องบอกให้

แต่เมื่อคุณทำเช่นนั้นคุณจะพบปัญหา: คุณไม่รู้ว่ามีกล้วยอยู่กี่ตัวก่อนหน้านี้ดังนั้นคุณจึงไม่รู้ว่าจะใช้พหูพจน์หรือไม่

บางครั้งโปรแกรมเมอร์ก็ไปอย่างขี้เกียจ there are X banana(s)แทนการตรวจสอบพวกเขาเพียงแค่พิมพ์

แต่มันน่าเกลียดดังนั้นเราต้องมีโปรแกรมเพื่อแก้ไขปัญหานี้

วิธีการ

หากต้องการลบพหูพจน์ที่ไม่ชัดเจนในสตริงให้ทำตามขั้นตอนต่อไปนี้:

  1. แยกสตริงบนช่องว่างออกเป็นรายการคำ

  2. สำหรับทุกคำที่ลงท้ายด้วย(s)ทำต่อไปนี้:

    • หากคำก่อนคือa, an, 1หรือoneเอา(s)ในตอนท้ายของคำว่า
    • มิฉะนั้นถ้าเป็นคำที่คำแรกในสตริงหรือคำที่ก่อนหน้านี้ไม่ได้a, an, 1หรือoneเปลี่ยนตอนท้ายของคำที่มี(s)s
  3. เข้าร่วมรายการคำกลับมารวมกันเป็นสตริงรักษาช่องว่างดั้งเดิม

ตัวอย่าง)

ลองสตริงthere's a banana(s) and three apple(s)ดู

อันดับแรกเราแบ่งสตริงออกเป็นรายการคำ: ["there's", "a", "banana(s)", "and", "three", "apple(s)"]

สำหรับขั้นตอนที่สองเราจะใช้คำสองคำที่ลงท้ายด้วย(s): และbanana(s)apple(s)

คำก่อนหน้าbanana(s)นี้คือaเราจึงลบ(s)มันbananaออก คำก่อนที่จะapple(s)เป็นthreeดังนั้นเราจึงเปลี่ยน(s)ไปดังนั้นมันจะกลายเป็นsapples

["there's", "a", "banana", "and", "three", "apples"]ขณะนี้เรามี there's a banana and three applesการเข้าร่วมรายการกลับมารวมกันที่เราได้รับ นี่คือผลลัพธ์สุดท้ายของเรา

ความท้าทาย

สร้างโปรแกรมหรือฟังก์ชั่นที่รับสตริงที่ไม่ชัดเจนในรูปแบบที่เหมาะสมและส่งคืนเวอร์ชันที่ไม่ได้คลุมเครือของสตริงนั้น

คุณอาจถือว่าสตริงไม่มีการขึ้นบรรทัดใหม่แท็บหรือการขึ้นบรรทัดใหม่

ฉันลืมที่จะระบุว่าจะแบ่งกลุ่มของช่องว่างหรือช่องว่าง (เช่นควรokay thenมีสองช่องว่าง["okay", "then"]หรือ["okay", "", "then"]) เมื่อโพสต์ความท้าทายดังนั้นคุณอาจสันนิษฐานว่าเป็นรูปแบบการแยก

กรณีทดสอบ

Input                                         -> Output
there are two banana(s) and one leprechaun(s) -> there are two bananas and one leprechaun
there's a banana(s) and three apple(s)        -> there's a banana and three apples
apple(s)                                      -> apples
one apple(s)                                  -> one apple
1 banana(s)                                   -> 1 banana
banana                                        -> banana
preserve    original      whitespace(s)       -> preserve    original      whitespaces
11 banana(s)                                  -> 11 bananas
an apple(s)                                   -> an apple
this is a te(s)t                              -> this is a te(s)t
I am a (s)tranger(s)                          -> I am a (s)tranger

เกณฑ์การให้คะแนน

เช่นนี้เป็นการส่งที่มีไบต์น้อยที่สุดชนะ!


คำถามนี้ได้รับการทดลองใช้ผลิตภัณฑ์
LyricLy

apple(s)กรณีทดสอบควรให้ผลตอบแทนapplesแทนหรือไม่? ความท้าทายระบุOtherwise, if the word is the first word in the string . . . replace the (s) at the end of the word with s.ว่ากรณีนี้ให้ผลเป็นapplesแซนด์บ็อกซ์สำหรับการแก้ไขสามครั้งแรก แต่เปลี่ยนที่สี่
fireflame241

@ fireflame241 เมื่อเขียนร่างที่สองของกฎฉันจะทำมันเพื่อให้การเริ่มต้นของสตริงไม่เปลี่ยนแปลง ฉันเปลี่ยนกฎนั้นในภายหลัง แต่ไม่ใช่กรณีทดสอบ จับดี.
LyricLy

การทดสอบกรณีข้อเสนอแนะ: ->There's a single banana(s) There's a single bananas
Jonathan Allan

1
@JonathanAllan คุณทำไม่ได้ ฉันจะเพิ่มกรณีทดสอบสองสามข้อ
LyricLy

คำตอบ:


6

Mathematica, 151 148 bytes

StringReplace[j=" ";k=Except@j;j<>j<>#<>j,j~~a:k...~~s:j..~~w:k..~~"(s)"~~j:>{j,a,s,w,If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""]}<>j]~StringTake~{3,-2}&

คำอธิบาย

j=" ";k=Except@j

ตั้งค่าjเป็นอักขระช่องว่าง ตั้งค่าkเป็นรูปแบบ "ไม่ใช่j" (= อักขระที่ไม่ใช่ช่องว่าง)

j<>j<>#<>j

เตรียมสองช่องว่างและผนวกหนึ่งช่องว่างเข้ากับอินพุต

j~~a:k...~~s:j..~~w:k..~~"(s)"~~j

สำหรับสตริงย่อยที่ตรงกับรูปแบบ:

  1. หนึ่งช่องว่างตามด้วย
  2. ซับสตริงที่มีความยาวเป็นศูนย์หรือมากกว่านั้นประกอบด้วยอักขระที่ไม่ใช่ช่องว่างเท่านั้น (ตัวระบุปริมาณ) (เรียกสิ่งนี้a) ตามด้วย
  3. ซับสตริงที่มีความยาวหนึ่งหรือมากกว่านั้นประกอบด้วยอักขระช่องว่างเท่านั้น (เรียกสิ่งนี้s) ตามด้วย
  4. ซับสตริงที่มีความยาวหนึ่งหรือมากกว่านั้นประกอบด้วยอักขระที่ไม่ใช่ช่องว่าง (คำ) (เรียกว่านี้w) เท่านั้นตามด้วย
  5. สตริง"(s)"ตามด้วย
  6. พื้นที่ว่าง
หาก [FreeQ [a, "A" | "เป็น" | "1" | "หนึ่ง"], "S", ""]

ถ้าaไม่ได้เป็นหนึ่งของคำเอกพจน์ (s), ประเมินมิฉะนั้น"s"""

StringReplace[..., ... :>{j,a,s,w,If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""]}<>j]

เปลี่ยนรูปแบบการจับคู่กับj, a, s, w, If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""]และjร่วมกัน

... ~StringTake~{3,-2}

ใช้จากตำแหน่ง 3 ถึงตำแหน่ง -2 (ดัชนี 1 ดัชนีลบนับจากท้าย) นี่เป็นเพราะเราได้เพิ่มสามช่องว่างในตอนต้น


3
ทำไมไม่ใช้ builtin เพื่อลบ plural-S?
โทมัสเวลเลอร์

5

Python 3 , 94 ไบต์

lambda s,r=re.sub:r(r"\(s\)( |$)","s",r(r"\b(an?|1|one)(\s+)(.+)\(s\)",r"\1\2\3",s))
import re

ลองออนไลน์!

-4 ไบต์ขอบคุณ i cri ทุกครั้ง (ฉันคิดว่านี่เป็นที่ยอมรับได้)


@JanathanAllan คงที่ขอบคุณ
HyperNeutrino

1
__import__ไม่อาจจะสั้น ... Yup ก็ 4 import reไบต์สั้นเป็นปกติ
สิ้นเชิงมนุษย์

@icrieverytim huh คุณพูดถูก (แค่ 3 ไบต์เท่านั้น) ขอบคุณ
HyperNeutrino


@icrieverytim ._ ดี. ขอบคุณ!
HyperNeutrino


4

Mathematica, 313 ไบต์

(Table[If[StringLength@z[[i]]>3&&StringTake[z[[i]],-3]=="(s)",z[[i]]=StringDrop[z[[i]],-3];t=1;While[z[[i-t]]=="",t++];If[FreeQ[{"a","an","1","one"},z[[i-t]]],z[[i]]=z[[i]]<>"s"]],{i,2,Length[z=StringSplit[#," "]]}];If[StringTake[z[[1]],-3]=="(s)",z[[1]]=StringDrop[z[[1]],-3];z[[1]]=z[[1]]<>"s"];StringRiffle@z)&


2

Pyth - 53 ไบต์

ทำตามอัลกอริธึมอย่างที่มันเป็น

K+kczdjdt.e?q"(s)"gb_2+<b_3*\s!}@Ktk[\a"an""one"\1)bK

ลองมันออนไลน์ได้ที่นี่


1
ล้มเหลวในthere are two banana(s) and one leprechaun(s)(สองช่องว่างหลังจากนั้นone) ช่องว่างดั้งเดิมถูกเก็บรักษาไว้ แต่leprechaun(s)จะข้ามไปoneก่อนหน้า
LyricLy

1
@LyricLy คุณไม่ได้ระบุเรื่องนี้อย่างชัดเจนใน OP ด้วยช่องว่างสองช่อง (โดยใช้ (1) จากส่วน "method (s)" ของ "แยกสตริงในช่องว่างเป็นรายการคำ") จริง ๆ แล้วมีคำว่างระหว่างoneและleprechaun(s)
Jonathan Allan

2

เจลลี่ ,  52 51  49 ไบต์

เจลลี่ไม่ได้มีอะตอมหนึ่ง regex

Ṫ
Ñ;”s
Ṫḣ-3
UṪw“)s(”⁼1
“µḣ⁴µuʠg*»ḲċḢ‘×Ç‘
⁶;ḲÇĿ2ƤK

โปรแกรมเต็มรูปแบบยอมรับสตริง (โดยใช้การจัดรูปแบบ Python ถ้าหลายบรรทัดหรือมีเครื่องหมายคำพูด) และพิมพ์ผลลัพธ์

ลองออนไลน์! หรือดูการทดสอบในตัว

อย่างไร?

Ṫ - Link 1, tail: two words (list of lists)
Ṫ - tail

Ñ;”s - Link 2, tail and replace last three chars with an 's': two words (list of lists)
Ñ    - call the next link (3) as a monad
  ”s - literal 's'
 ;   - concatenate

Ṫḣ-3 - Link 3, tail and remove the last three chars: two words (list of lists)
Ṫ    - tail
  -3 - literal minus three
 ḣ   - head from index (1-indexed and modular)

UṪw“)s(”⁼1 - Link 4, tail ends with "(s)"?: two words (list of lists)
U          - upend (reverse each word)
 Ṫ         - tail
   “)s(”   - literal [')', 's', '('] - that is "(s)" reversed
  w        - index of first sublist equal to that or 0 if not found
         1 - literal one
        ⁼  - equal?

“µḣ⁴µuʠg*»ḲċḢ‘×Ç‘ - Link 5, categorise: two words (list of lists)
“µḣ⁴µuʠg*»        - compression of string "a 1" + word " an" + word " one"
          Ḳ       - split on spaces = ["a", "1", "an", "one"]
            Ḣ     - head (the first word)
           ċ      - count occurrences (of head in the list - either 0 or 1)
             ‘    - increment
               Ç  - call the last link (4) as a monad - i.e. f(two words)
              ×   - multiply
                ‘ - increment - so we have: 1 for ["1", "blah"],
                  -             2 for ["blah", "blah(s)"] or 3 for ["1", "blah(s)"]

⁶;ḲÇĿ2ƤK - Main link: list of characters, the string
⁶        - literal space character
 ;       - concatenate (place a space at the beginning as we want to inspect pairs)
  Ḳ      - split on spaces (giving an empty list at the start)
     2Ƥ  - for all infixes of length two:
    Ŀ    -   call the link at the given index as a monad:
   Ç     -     call the last link (5) as a monad
       K - join the result with spaces
         - implicit print

ฉันอยากรู้ว่าทำไมคุณถึงใช้ลิงค์แยกต่างหาก สิ่งนี้ป้องกันไม่ให้ลบองค์ประกอบออกจากรายการเดิมหรือไม่
HyperNeutrino

ไม่ฉันต้องเอาหางของทั้งคู่ออกไป ... เขียนคำอธิบายรหัสบางทีคุณอาจมองเห็นสนามกอล์ฟเมื่อคุณเห็นสิ่งนั้น
Jonathan Allan

อ่าโอเค. ขอบคุณฉันจะพยายามมองกอล์ฟเมื่อมีคำอธิบาย (หรือก่อนหน้านั้น)!
HyperNeutrino

ดังนั้นลิงก์ 1, 2 และ 3 tail ทั้งหมดและลิงก์ 5 เลือกว่าจะโทรและใช้Ŀทำอะไร แต่ฉันไม่เห็นวิธีสั้น ๆ ในการลิงค์ภายในลิงค์ 4 แต่อาจมี อาจมีวิธีที่จะทำให้ส่วนท้ายของลิงค์ 4 อยู่ในนั้นด้วย!
Jonathan Allan

@HyperNeutrino ฉันคิดว่าสิ่งที่Ŀอาจเรียกได้ว่าลิงค์แรกนั่นคือเหตุผลว่าทำไมลิงค์ถึงเป็นของมันเอง
Erik the Outgolfer


1

Perl 5 , 56 + 1 ( -p) = 57 ไบต์

s/\b(an?|1|one) +\S+\K\(s\)(?= |$)//g;s/\(s\)( |$)/s$1/g

ลองออนไลน์!


1
ไม่ได้อยู่ในกรณีทดสอบ a hel(s)loแต่ฉันคิดว่านี้ล้มเหลว
Neil

ทำงานได้อย่างถูกต้องตามที่ระบุไว้ในกรณีทดสอบ ใกล้ด้านล่างของกรณีทดสอบในลิงค์ TIO ของฉัน
Xcali

ดีฉันก็จะต้องได้รับa hel(s)loการเพิ่มในกรณีทดสอบแล้วบางทีคุณอาจจะแก้ไขรหัสของคุณ ...
นีล

0

JavaScript (ES6), 88 87 ไบต์

a=>a.replace(/(\S+)( +)(\S+)\(s\)/g,(m,f,s,w)=>f+s+w+(/^(a|an|1|one)$/.exec(f)?'':'s'))

คำอธิบายจะมาเร็ว ๆ นี้


1
คุณสามารถแทนที่\sด้วย `` ตาม "คุณอาจถือว่าสตริงไม่มีการขึ้นบรรทัดใหม่แท็บหรือการขึ้นบรรทัดใหม่"
SuperStormer

ล้มเหลวใน "นี่คือ te (s) t" คุณสามารถแก้ไขได้โดยการเพิ่ม(\s|$)ไปยังจุดสิ้นสุดของ regex
Birjolaxew

ยังล้มเหลวใน "แอปเปิ้ล (s)" แก้ไขใน TIO นี้
Birjolaxew

ขอบคุณ @Birjolaxew จะแก้ไขในการเปลี่ยนแปลงเมื่อฉันสามารถ ...
XavCo7

0

JavaScript (ES6), 84 ไบต์

s=>s.replace(/((^|\S+ +)\S+)\(s\)(?!\S)/g,(_,a)=>a+(/^(1|an?|one) /.test(a)?'':'s'))

นี่คือวิธีที่น่าสนใจในการจัดเรียงส่วนสุดท้ายซึ่งมีความยาว 2 ไบต์ที่น่าเศร้า:

s=>s.replace(/((^|\S+ +)\S+)\(s\)(?!\S)/g,(_,a)=>a+'s'.slice(/^(1|an?|one) /.test(a)))

0

JavaScript (SpiderMonkey) , 82 ไบต์

s=s.replace(/(\S+ +(\S+))\(s\)\B/g,(_,a)=>a+("s"[+/^(1|one|an?)\b/i.test(a)]||""))

ลองออนไลน์!

เวอร์ชัน 78 ไบต์ (น้อยกว่าที่แข็งแกร่ง)

s=s.replace(/(\S+ +(\S*))\(s\)/g,(_,a)=>a+("s"[+/^(1|one|an?)/i.test(a)]||""))

นี่เป็นรุ่นที่ดัดแปลงของ ETHproductions '(ฉันไม่มี 50 rep)

คำอธิบาย

  • /(\S+ +(\S+))\(s\)/g- รูปแบบที่แท้จริงที่จะมองหา ( amount object(s))
  • (_,a)=>a- _เป็นตัวแปรที่จับได้ทั้งหมดaคือ(\S+ +(\S+))
  • "s"[+/^(1|one|an?)/i.test(a)]||""- แทนการแบ่งอาร์เรย์เพียงทำอาร์เรย์จำลองและรับดัชนี ( +/.../.testคืนค่าตัวเลข)
    • ควร"s"[+/^(1|one|an?)/i.test(a)]กลับundefined( trueหรือ1สำหรับการทดสอบ) กลับ""
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.