Hapus duplikat kata dari kalimat

10

Dalam tantangan ini, Anda akan menghapus kata-kata rangkap dari setiap kalimat .

Contohnya

Hello Hello, World!
Hello, World!

Code Code! Golf Code
Code! Golf Code

Hello  hello   World
Hello   World

Programming Golf Programming!
Programming Golf!

Spesifikasi

  • Input akan berupa string karakter ASCII.
  • Sebuah kalimat didefinisikan sebagai apa saja hingga akhir string, sebuah linefeed ( \n), atau tanda baca ( .!?).
  • Sebuah kata didefinisikan sebagai urutan A-Za-z.
  • Kata-kata tidak peka huruf besar-kecil ( Hello== heLlO).
  • Hanya kemunculan pertama kata dalam kalimat yang disimpan.
  • Jika sebuah kata dihapus, spasi sebelum kata yang dihapus harus dihapus. (misalnya A A B-> A B).

Ini adalah sehingga kode terpendek dalam byte menang!

Downgoat
sumber
1
a b a.pergi ke apa?
lirtosiast
@ThomasKwa a b.karena `a` dihapus.
Downgoat
Sebab a__b_b_a, apakah Anda mendapatkan a_b_a( bdihapus pertama ) atau a__b_a( bdihapus kedua )?
@CamilStaps Anda akan dapatkan a__b__karena yang diulang bdihapus dan yang diulang adihapus
Downgoat
1
@ BradGilbertb2gills Semua karakter ASCII diizinkan dalam input. Hanya huruf yang dianggap kata
Downgoat

Jawaban:

3

Vim, 27 byte

:s/\v\c(<\a+>).{-}\zs\s+\1

Perhatikan bahwa 27 byte termasuk carriage return di akhir.

Cobalah online! Catatan: Ini adalah tautan ke bahasa lain yang saya tulis disebut "V". V sebagian besar kompatibel dengan vim, jadi untuk semua maksud dan tujuan, ia dapat dihitung sebagai penerjemah vim. Saya juga menambahkan satu byte %sehingga Anda dapat memverifikasi semua kasus uji sekaligus.

Penjelasan:

:s/\v                       "Substitute with the 'Magic flag' on. This magic flag allows us
                            "to shorten the regex by removing a lot of \ characters.
     \c(<\a+>)              "A case-insensitive word
              .{-}          "Any character (non-greedy)
                  \zs       "Start the selection. This means everything after this atom
                            "will be removed
                     \s+    "One or more whitespace characters,
                        \1  "Followed by the first word
James
sumber
6

JavaScript (ES6), 98

Catatan sementara saya menemukannya sendiri, sangat mirip dengan @ Neil, hanya dengan logika tambahan untuk membagi seluruh string input menjadi kalimat.

s=>s.replace(/[^\n.!?]+/g,s=>s.replace(/ *([a-z]+)/ig,(r,w)=>k[w=w.toUpperCase()]?'':k[w]=r,k=[]))

Uji

f=s=>s.replace(/[^\n.!?]+/g,s=>s.replace(/ *([a-z]+)/ig,(r,w)=>k[w=w.toUpperCase()]?'':k[w]=r,k=[]))

console.log=x=>O.textContent+=x+'\n'

;[['Hello Hello, World!','Hello, World!']
,['Code Code! Golf Code','Code! Golf Code']
,['Hello  hello   World','Hello   World']
,['Programming Golf Programming!','Programming Golf!']]
.forEach(t=>{
  var i=t[0],k=t[1],r=f(i)
  console.log((r==k?'OK ':'KO ')+i+' -> '+r)
})  
<pre id=O></pre>

edc65
sumber
6

Retina , 66 46 byte

Hitungan byte mengasumsikan penyandian ISO 8859-1.

i`[a-z]+
·$0·
i` *(·[a-z]+·)(?<=\1[^.!?¶]+)|·

Cobalah online!

Penjelasan

Karena hanya huruf yang harus dianggap sebagai karakter kata (tetapi regex juga memperlakukan digit dan garis bawah sebagai karakter kata), kita perlu membuat batasan kata sendiri. Karena input dijamin hanya berisi karakter ASCII, saya memasukkan ·(di luar ASCII, tetapi di dalam ISO 8859-1) di sekitar semua kata dan menghapusnya lagi dengan duplikat. Itu menghemat 20 byte daripada menggunakan lookarounds untuk menerapkan batas kata umum.

i`[a-z]+
·$0·

Ini cocok dengan setiap kata dan mengelilinginya ·.

i` *(·[a-z]+·)(?<=\1[^.!?¶]+)|·

Ini adalah dua langkah yang dikompresi menjadi satu. <sp>*(·[a-z]+·)(?<=\1[^.!?¶]+)cocok dengan kata lengkap (dipastikan dengan memasukkan ·dalam pertandingan), bersama dengan spasi apa pun sebelumnya, asalkan (seperti yang dijamin oleh tampilan di belakang) kita dapat menemukan kata yang sama di suatu tempat sebelumnya dalam kalimat. (Yang cocok dengan linefeed.)

Bagian lainnya hanyalah ·, yang cocok dengan semua batas kata artifisial yang tidak cocok sebagai bagian dari paruh pertama. Dalam kedua kasus, kecocokan hanya dihapus dari string.

Martin Ender
sumber
4

C, 326 byte

Siapa yang butuh ekspresi reguler?

#include <ctype.h>
#define a isalpha
#define c(x)*x&&!strchr(".?!\n",*x)
#define f(x)for(n=e;*x&&!a(*x);++x);
main(p,v,n,e,o,t)char**v,*p,*n,*e,*o,*t;{for(p=v[1];*p;p=e){f(p)for(e=p;c(e);){for(;a(*++e););f(n)if(c(n)){for(o=p,t=n;a(*o)&&(*o-65)%32==(*t-65)%32;o++,t++);if(a(*t))e=n;else memmove(e,t,strlen(t)+1);}}}puts(v[1]);}
Cole Cameron
sumber
3

Perl 6 , 104 byte

{[~] .split(/<[.!?\n]>+/,:v).map(->$_,$s?{.comb(/.*?<:L>+/).unique(as=>{/<:L>+/;lc $/}).join~($s//'')})} # 104

Pemakaian:

# give it a lexical name
my &code = {...}

say code "Hello Hello, World!
Code Code! Golf Code
Hello  hello   World
Programming Golf Programming!";
Hello, World!
Code! Golf Code
Hello   World
Programming Golf!

Penjelasan

{
  [~]                         # join everything that follows:

  .split(/<[.!?\n]>+/,:v)     # split on boundaries, keeping them
  .map(                       # loop over sentence and boundary together
    -> $_, $s? {              # boundary is optional (at the end of the string)
      .comb(/.*?<:L>+/)       # grab the words along with leading non letters
      .unique(                # keep the unique ones by looking at …
        as => {/<:L>+/;lc $/} # only the word chars in lowercase
      )
      .join                   # join the sentence parts
      ~                       # join that with …
      ($s//'')                # the boundary characters or empty string 
    }
  )
}
Brad Gilbert b2gills
sumber
1

Perl 5, 57 byte

56 byte kode +1 untuk -p

s/[^.!?
]+/my%h;$&=~s~\s*([A-z]+)~!$h{lc$1}++&&$&~egr/eg

Pemakaian:

perl -pe 's/[^.!?
]+/my%h;$&=~s~\s*([A-z]+)~!$h{lc$1}++&&$&~egr/eg' <<< 'Hello Hello, World!
Code Code! Golf Code
Hello  hello   World
Programming Golf Programming!
'
Hello, World!
Code! Golf Code
Hello   World
Programming Golf!

Mungkin perlu +1, saat ini saya mengasumsikan bahwa hanya akan ada spasi di input, tidak ada tab.

Dom Hastings
sumber
Dari komentar, "Semua karakter ASCII diizinkan dalam input. Hanya huruf yang dianggap kata" (saya pikir saya akan menyunting ini menjadi tantangan)
Martin Ender
@ MartinBüttner Sialan, ok saya akan memperbarui untuk menggunakan \ssebagai gantinya ... Masih jauh dari jawaban retina Anda sekalipun!
Dom Hastings
Oh saya mengerti mengapa Anda bertanya sekarang. Jika kita perlu menghapus spasi putih di depan kata-kata, maka saya perlu byte lain juga. Pertanyaannya secara khusus mengatakan "spasi". Saya sudah meminta klarifikasi.
Martin Ender
@ MartinBüttner Saya kira komentar saya juga tidak terlalu jelas! Terima kasih atas komentar Anda!
Dom Hastings