文から重複する単語を削除する


10

この課題では、各文から重複する単語を削除します。

Hello Hello, World!
Hello, World!

Code Code! Golf Code
Code! Golf Code

Hello  hello   World
Hello   World

Programming Golf Programming!
Programming Golf!

仕様

  • 入力はASCII文字列になります。
  • 文は、文字列の終わり、改行(\n)、または句読点(.!?)までの任意のものとして定義されます。
  • 単語はのシーケンスとして定義されA-Za-zます。
  • 単語は大文字と小文字を区別しません(Hello== heLlO)。
  • 文中の単語の最初の出現のみが保持されます。
  • 単語が削除された場合、削除された単語ののスペースは削除する必要があります。(例A A B-- A B)。

これはので、バイト単位の最短コードが優先されます!


1
a b a.何に行くの?
リルトシアスト2016年

@ThomasKwa a b.`A`が削除されたため。
ダウンゴート2016年

についてa__b_b_aa_b_a(最初にb削除された)またはa__b_a(2番目にb削除された)を取得しますか?

あなたはなるだろう@CamilStaps a__b__を繰り返すので、b削除され、繰り返しa削除される
Downgoat

1
@ BradGilbertb2gills入力ではすべてのASCII文字を使用できます。ただし、文字のみが単語と見なされます
Downgoat

回答:


3

Vim、27バイト

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

27バイトには、最後にキャリッジリターンが含まれることに注意してください。

オンラインでお試しください!補足:これは私が書いている "V"と呼ばれる別の言語へのリンクです。Vはほとんど vimと下位互換性があるため、すべての意図と目的で、vimインタープリターとしてカウントできます。%すべてのテストケースを一度に確認できるように、1バイトも追加しました。

説明:

: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

6

JavaScript(ES6)、98

私はそれを自分自身を発見しながら、それは追加のロジックは、文章で入力文字列全体を分割するだけで、ニールさん@とうるさく似ています。

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

テスト

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>


6

Retina66 46バイト

バイト数はISO 8859-1エンコーディングを想定しています。

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

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

説明

文字のみを単語文字と見なす必要があるため(ただし、正規表現は数字とアンダースコアも単語文字として扱います)、独自の単語境界を作成する必要があります。入力にはASCII文字のみが含まれていることが保証されているため、·すべての単語の周囲に(ASCIIの外部、ただしISO 8859-1の内部に)挿入し、重複した単語を再度削除します。これにより、ルックアラウンドを使用して一般的な単語の境界を実装するよりも20バイト節約されます。

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

これはすべての単語に一致し、それをで囲み·ます。

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

これは2つのステップを1つに圧縮したものです。<sp>*(·[a-z]+·)(?<=\1[^.!?¶]+)完全な単語(一致にを含めることで保証され·ます)とその前のスペースを照合します(後読みで確認されているように)、文のどこかで同じ単語を見つけることができます。(は改行に一致します。)

もう1つの部分は単にであり·、前半の一部として一致しなかったすべての人工的な単語の境界に一致します。どちらの場合も、一致は単に文字列から削除されます。


4

C、326バイト

正規表現が必要なのは誰ですか?

#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]);}

3

Perl 6、104バイト

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

使用法:

# 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!

説明

{
  [~]                         # 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 
    }
  )
}

1

Perl 5、57バイト

56バイトのコード+ 1 -p

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

使用法:

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!

+1である必要があるかもしれません。現在、入力ではスペースはなく、タブはないと想定しています。


コメントから「入力ではすべてのASCII文字が許可されます。ただし、文字のみが単語と見なされます」(これをチャレンジに編集します)
Martin Ender

@MartinBüttnerくそー、\s代わりに使用するように更新します...それでも、網膜の答えの近くにはどこにもありません!
Dom Hastings

ああ、あなたが今尋ねた理由がわかります。単語の前にある空白を削除する必要がある場合は、別のバイトも必要です。質問は具体的には「スペース」と言っています。説明を求めました。
マーティンエンダー

@MartinBüttner私のコメントもあまり明確ではなかったと思います!でもコメントありがとうございます!
Dom Hastings
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.