문장에서 중복 단어 제거


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.무엇으로가요?
lirtosiast

a b.`a`가 제거 되었으므로 @ThomasKwa .
Downgoat

의 경우 (첫 번째 제거) 또는 (두 번째 제거) a__b_b_a를 얻 습니까? a_b_aba__b_ab

당신은 얻을 것이다 @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

자바 스크립트 (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

레티 나 , 66 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[^.!?¶]+)|·

이것은 하나의 단계로 압축 된 두 단계입니다. <sp>*(·[a-z]+·)(?<=\1[^.!?¶]+)합니다 (포함하여 보장 전체 단어 일치 ·를 앞에 공백과 함께, 경기의)를 이 제공 우리가 어딘가에 이전 문장에서 같은 단어를 찾을 수 있습니다합니다 (lookbehind에 의해 보장으로). ( 줄 바꿈과 일치합니다.)

다른 부분은 단순히이며 ·, 이는 전반부의 일부로 일치하지 않은 모든 인공 단어 경계와 일치합니다. 두 경우 모두 문자열에서 일치 항목이 제거됩니다.


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

펄 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

펄 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

아 왜 지금 물어 봤는지 알 겠어 단어 앞에서 공백 을 제거 해야하는 경우 다른 바이트도 필요합니다. 질문은 구체적으로 "공백"이라고 말합니다. 설명을 요청했습니다.
Martin Ender

@ MartinBüttner 내 의견이 실제로 명확하지 않은 것 같습니다! 그래도 귀하의 의견에 감사드립니다!
Dom Hastings
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.