Hapus jamak ambigu!


21

Pemrogramannya sangat kaku. Anda tidak dapat memberi tahu program untuk "menampilkan jumlah pisang", Anda harus memberi tahu print(bananas).

Tetapi ketika Anda melakukan itu, Anda berakhir dengan masalah: Anda tidak tahu berapa banyak pisang yang Anda miliki sebelumnya, jadi Anda tidak tahu apakah akan menggunakan jamak.

Terkadang, pemrogram melakukan hal yang malas. Alih-alih memeriksa, mereka hanya mencetak there are X banana(s).

Tapi itu jelek, jadi kita perlu program untuk memperbaikinya.

Metode

Untuk menghapus bentuk jamak ambigu dalam string, ikuti langkah-langkah berikut:

  1. Pisahkan string pada spasi menjadi daftar kata.

  2. Untuk setiap kata yang diakhiri dengan (s), lakukan hal berikut:

    • Jika kata sebelumnya adalah a, an, 1atau one, menghapus (s)pada akhir kata.
    • Jika tidak, jika kata adalah kata pertama dalam string atau kata sebelumnya tidak a, an, 1atau one, ganti (s)di akhir kata dengan s.
  3. Gabung daftar kata kembali bersama menjadi string, melestarikan spasi putih asli.

Contoh

Mari kita ambil string there's a banana(s) and three apple(s).

Pertama, kami membagi string menjadi daftar kata: ["there's", "a", "banana(s)", "and", "three", "apple(s)"]

Untuk langkah kedua, kita ambil dua kata yang diakhiri dengan (s): banana(s)dan apple(s).

Kata sebelumnya banana(s)adalah a, jadi kami menghapus (s), membuatnya banana. Kata sebelumnya apple(s)adalah three, jadi kami mengubah (s)to s, dengan demikian menjadi apples.

Kami sekarang punya ["there's", "a", "banana", "and", "three", "apples"]. Bergabung kembali dengan daftar, kita dapatkan there's a banana and three apples. Ini adalah hasil akhir kami.

Tantangan)

Buat program atau fungsi yang mengambil string ambigu dalam format apa pun yang masuk akal dan mengembalikan versi string yang tidak ambigu .

Anda dapat mengasumsikan string tidak mengandung baris baru, tab, atau carriage return.

Saya lupa menentukan apakah akan membagi pada kelompok ruang atau ruang (yaitu apakah okay thendengan dua ruang seharusnya ["okay", "then"]atau ["okay", "", "then"]) ketika memposting tantangan, sehingga Anda dapat menganggap salah satu bentuk pemisahan.

Test case

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

Mencetak gol

Karena ini adalah , pengiriman dengan byte paling sedikit akan menang!


Pertanyaan ini telah di- sandbox .
LyricLy

Haruskah apple(s)test case menghasilkan applessebagai gantinya? Tantangannya menyatakan Otherwise, if the word is the first word in the string . . . replace the (s) at the end of the word with s.saya perhatikan bahwa kasus ini menghasilkan appleskotak pasir untuk tiga revisi pertama tetapi berubah pada yang keempat.
fireflame241

@ fireflame241 Saat menulis draf kedua aturan, saya akan membuatnya sehingga awal string tidak berubah. Saya mengubah aturan itu nanti, tetapi bukan pada test case. Tangkapan yang bagus.
LyricLy

Saran uji kasus: There's a single banana(s)-> There's a single bananas.
Jonathan Allan

1
@ JonathanAllan Anda tidak bisa. Saya akan menambahkan beberapa test case.
LyricLy

Jawaban:


6

Mathematica, 151 148 byte

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}&

Penjelasan

j=" ";k=Except@j

Setel jke karakter spasi putih. Setel kke pola "tidak j" (= karakter bukan spasi).

j<>j<>#<>j

Tambahkan dua spasi putih dan tambahkan satu spasi putih ke input.

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

Untuk substring yang cocok dengan polanya:

  1. Satu spasi putih, diikuti oleh
  2. substring panjang-nol atau lebih panjang yang hanya terdiri dari karakter non-spasi putih (kuantifier) ​​(panggil ini a), diikuti oleh
  3. substring panjang-satu atau lebih panjang yang hanya terdiri dari karakter spasi putih (sebut ini s), diikuti oleh
  4. substring panjang-satu atau lebih panjang yang terdiri dari hanya karakter non-spasi (kata) (sebut ini w), diikuti oleh
  5. string "(s)", diikuti oleh
  6. ruang kosong
Jika [FreeQ [a, "a" | "an" | "1" | "one"], "s", ""]

Jika abukan salah satu dari kata tunggal, evaluasi untuk "s", sebaliknya "".

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

Mengganti pola yang cocok dengan j, a, s, w, If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""], dan jbergabung bersama-sama.

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

Ambil dari posisi 3 ke posisi -2 (1-diindeks; indeks negatif dihitung dari akhir). Ini karena kami menambahkan tiga spasi di awal.


3
Mengapa tidak menggunakan builtin untuk menghapus plural-S?
Thomas Weller

5

Python 3 , 94 byte

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

Cobalah online!

-4 byte terima kasih kepada i cri everytim (saya pikir ini bisa diterima)


@ Jonathan Allan Diperbaiki, terima kasih.
HyperNeutrino

1
__import__tidak mungkin lebih pendek ... Yup, ini 4 byte lebih pendek dari biasanya import re.
totallyhuman

@icrieverytim ya kamu benar (hanya 3 byte) terima kasih
HyperNeutrino


@icrieverytim ._. Oh bagus. Terima kasih!
HyperNeutrino


4

Mathematica, 313 byte

(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)&

3

Perl 5, 43 + 1 (-p) = 44 byte

s/\b((one|1|an?) +)?\S+\K\(s\)\B/"s"x!$1/ge

Cocokkan setiap (s)akhir kata, gantikan dengan !$1(1 atau 0) eses.


2

Pyth - 53 byte

Mengikuti algoritma seperti ini.

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

Cobalah online di sini .


1
Gagal aktif there are two banana(s) and one leprechaun(s)(dua spasi setelah one). Ruang putih asli dipertahankan, tetapi leprechaun(s)mengabaikan onesebelumnya.
LyricLy

1
@LyricLy Anda belum secara eksplisit menyatakan ini di OP. Dengan dua spasi (menggunakan (1) bagian "metode" bagian dari "pisahkan string pada spasi menjadi daftar kata") sebenarnya ada kata kosong di antara onedanleprechaun(s)
Jonathan Allan

2

Jelly ,  52 51  49 byte

Jelly tidak memiliki satu atom regex

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

Program lengkap yang menerima string (menggunakan format Python jika multiline atau mengandung tanda kutip) dan mencetak hasilnya.

Cobalah online! atau lihat test-suite .

Bagaimana?

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

Saya ingin tahu mengapa Anda menggunakan tautan terpisah. Apakah ini mencegah dari menghapus elemen dari daftar asli?
HyperNeutrino

Tidak, saya perlu mendapatkan ekor dari pasangan ... menulis komentar kode, mungkin Anda bisa melihat golf begitu Anda melihatnya.
Jonathan Allan

Ah baiklah. Terima kasih, saya akan mencoba mengenali golf begitu ada komentar (atau sebelum itu)!
HyperNeutrino

Jadi tautan 1, 2 dan 3 semuanya berekor, dan tautan 5 memilih yang akan dipanggil dan digunakan Ŀuntuk melakukannya, tetapi saya tidak melihat cara singkat untuk mengekor di dalam tautan 4, tetapi mungkin ada. Bahkan mungkin ada cara untuk mendapatkan ekor tautan 4 di sana juga!
Jonathan Allan

@HyperNeutrino Saya pikir Ŀthingy dapat memanggil tautan pertama, itu sebabnya tautan itu sendiri.
Erik the Outgolfer


1

Perl 5 , 56 +1 ( -p) = 57 byte

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

Cobalah online!


1
Bukan pada kasus uji, tapi saya pikir ini gagal a hel(s)lo.
Neil

Itu berfungsi dengan baik seperti yang disediakan dalam test case. Itu dekat bagian bawah kotak uji di tautan TIO saya.
Xcali

Yah saya hanya harus a hel(s)loditambahkan ke kasus uji, dan kemudian mungkin Anda akan memperbaiki kode Anda ...
Neil

0

JavaScript (ES6), 88 87 byte

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

Penjelasan segera hadir.


1
Anda dapat mengganti \sdengan `` menurut "Anda dapat mengasumsikan string tidak mengandung baris baru, tab, atau carriage return."
SuperStormer

Gagal pada "this is a te (s) t". Anda dapat memperbaikinya dengan menambahkan (\s|$)ke akhir regex.
Birjolaxew

Juga gagal pada "apel". Diperbaiki dalam TIO ini
Birjolaxew

Terima kasih @Birjolaxew, akan mengedit perubahan yang saya bisa ...
XavCo7

0

JavaScript (ES6), 84 byte

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

Berikut adalah cara yang menarik untuk mengatur ulang bagian terakhir, yang sayangnya 2 byte lebih lama:

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

0

JavaScript (SpiderMonkey) , 82 byte

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

Cobalah online!

Versi 78 Byte (kurang kuat)

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

Ini adalah versi modifikasi dari ETHproductions '(Saya tidak punya 50 rep.)

Penjelasan

  • /(\S+ +(\S+))\(s\)/g- pola aktual untuk dicari ( amount object(s))
  • (_,a)=>a- _Adalah menangkap semua variabel, aadalah(\S+ +(\S+))
  • "s"[+/^(1|one|an?)/i.test(a)]||""- Alih-alih mengiris array, buat saja array dummy dan dapatkan indeks ( +/.../.testmengembalikan angka)
    • harus "s"[+/^(1|one|an?)/i.test(a)]mengembalikan undefined( true, atau 1untuk ujian) kembali""
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.