중간에 반복없이 반복없이 원래 문자열을 찾으십시오.


25

때로는 문장을 입력하는 동안 산만 해져 같은 단어를 두 번 연속해서 번 입력하는 경우가 있습니다.

다른 사람들이 이것으로 방해받지 않도록 하려면 ,이 문제를 해결하는 프로그램을 작성해야합니다!

태스크

입력 문자열이 주어지면 (귀하의 언어에 중요하다면 줄 바꿈이 포함되지 않은 ASCII 전용 입력이라고 가정 할 수 있습니다.) str중간에 어딘가에 연속적으로 두 번 발생하는 하위 문자열이 포함되어 있으면이 인스턴스를 사용하여 문자열을 반환하십시오 부분 문자열이 제거되었습니다.

여러 가능성의 경우 가능한 가장 짧은 답변을 반환하십시오 (즉, 가장 긴 연속 반복 하위 문자열을 선택하고 해당 문자열을 제거하십시오).

동일한 길이의 연속 반복 서브 스트링이 여러 개인 경우 첫 번째 (즉, 문자열을 처음부터 끝까지 읽을 때 처음 발생한 것)를 제거하십시오.

입력이 올바르다 고 가정 할 수 있습니다 (즉, 항상 연속적인 반복 서브 스트링이 포함됨).


  1. 입력 : hello hello world-> 출력 : hello world.
  2. 입력 : foofoo-> 출력 : foo. (그래서 문자열은 반복 부분으로 만 두 번 구성 될 수 있습니다).
  3. 입력 : aaaaa-> 출력 : aaa, 가장 긴 반복 연속 하위 문자열이 여기에 있습니다 aa.
  4. 입력 : Slartibartfast-> 연속적인 반복 하위 문자열을 포함하지 않으므로 유효한 입력이 아니므로이 경우를 처리 할 필요가 없습니다.
  5. 입력 : the few the bar-> 반복되는 부분이 원래 부분을 즉시 따라야하기 때문에 이것은 또 다른 잘못된 입력입니다. 이 경우, the그리고 the이러한 입력은 무효이다, 그래서 그 사이 다른 것에 의해 분리된다.
  6. 입력 : ababcbc-> 출력 : abcbc. 두 개의 가능한 가장 긴 연속 반복 서브 스트링은 abbc입니다. ab문자열의 앞부분에서 볼 수 있듯이 이것은 정답입니다.
  7. 입력 : Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo. 출력 : Buffalo buffalo buffalo buffalo Buffalo buffalo. 수행 된 교체는 대소 문자를 구분해야합니다.
  8. 입력 : Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice couple of words twice in succession.-> 출력 : Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. 가장 긴 연속 반복 하위 문자열 만 제거됩니다.

이므로 가능한 한 짧아야 하므로 바이트 단위의 최단 답변이 우선합니다. 행운을 빕니다!


@manatwork 첫 문장 Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice couple of words twice in succession.을 입력 할 때 , 즉 출력은이어야합니다 Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. 가장 긴 중복 항목 만 제거됩니다.
Qqwy

1
가능한 두 가지 교체가있는 테스트를 추가하는 것이 좋습니다. 두 번째 교체는 첫 번째 교체보다 깁니다. 나는 대부분의 답변이 그 중 하나를 통과하지 못할 것이라고 생각합니다 :)
aross

@aross 테스트 사례 8은 정확히 다음과 같습니다.)
Qqwy

나와 테스트 코드가 틀리지 않으면 반복되는 문자열이 하나만 있습니다.
aross

@aross에는 더블 p이 있습니다happens
Qqwy

답변:


8

펄 6 , 40 바이트

{.subst: m:ex/(.*))>$0/.max(*.chars),''}

시도 해봐

{
  .subst:             # substitute


    m                 # match
    :exhaustive
    /
      ( .* )          # any number of chars

      )>              # don't include the following in what is returned

      $0              # the first match again
    /.max( *.chars ), # find the first longest submatch


    ''                # substitute it with nothing
}

8

망막 , 35 33 바이트

바이트 수는 ISO 8859-1 인코딩을 가정합니다.

(?=(.+)(\1.*))
$2¶$`
O$#`
$.&
G1`

온라인으로 사용해보십시오!

설명

정규식 엔진은 왼쪽에서 오른쪽으로 일치하는 항목을 찾기 때문에 위치에 관계없이 가장 긴 일치 항목을 찾는 것은 쉽지 않습니다. .NET의 밸런싱 그룹으로 수행 할 수 있지만 결과는 다소 불쾌합니다.

1`((.)+)\1(?<=(?!.*((?>(?<-2>.)+).+)\3)^.*)
$1

그래서 나는 다른 Retina 기능을 사용하여이를 피하려고 노력했습니다.

(?=(.+)(\1.*))
$2¶$`

우리는 본질적으로 가능한 모든 대체를 각 줄에 하나씩 적용하여 시작 합니다. 이를 위해 일치 자체가 아닌 일치 앞에있는 위치를 일치시켜 중복 일치를 허용합니다. 이것은 실제 정규 표현식을 미리 보며 수행됩니다. 그런 다음 lookahead는 그룹 2에서 제거하려는 복제본을 제외하고 나머지를 캡처합니다. 그룹 2 (중복 삭제), 줄 바꿈을 기록한 다음 전체 입력을 일치 항목까지 다시 작성하여 기본적으로 새로운 행을 제공합니다. 대체된다.

마지막에는 각 경기마다 한 줄씩 표시되며 해당 중복은 제거됩니다. 마지막에는 대체하지 않고 전체 입력이 다시 있습니다.

이제 가능한 모든 대체가 있으므로 가장 짧은 결과를 원합니다 (가장 긴 제거 반복에 해당).

O$#`
$.&

먼저 길이를 기준으로 선을 정렬합니다.

G1`

그리고 우리는 첫 줄만 유지합니다.


와우, 그 교체 기술은 정말 영리합니다!
Leo

6

젤리 , 22 19 바이트

Dennis 덕분에 -2 바이트 (인수 반전 방지, 미묘한 중복 증분 제거)

ẋ2³wȧ+¥J
ẆÇ€LÐṀḢṬœp

온라인으로 사용해보십시오!

전체 프로그램 ( ÐṀdyads에 대한 올바른 arity로 작동하지 않는 버그가 발견되었으며 조만간 수정 될 것입니다. 여기서는 더 짧은 코드를 만들 수는 없지만).

방법?

입력에 반복이 존재하도록 입력에서 가장 긴 입력 조각 중 첫 번째 조각을 찾아 입력에서 제거합니다.

ẋ2³wȧ+¥J - Link 1, removal indices for given slice if valid, else 0: slice, x
ẋ2       - repeat x twice, say y
  ³      - program input: s
   w     - index of first occurrence of y in s (1-based) or 0, say i
       J - range(length(x)): [1,2,3,...,length(x)]
      ¥  - last two links as a dyad
    ȧ    -     and (non-vectorising)
     +   -     addition: [1+i,2+i,3+i,...,length(x)+i] or 0
         - note: no need to decrement these since the last index will be the 1st index
         - of the repetition (thanks to Dennis for spotting that!)

ẆÇ€LÐṀḢṬœp - Main link: string, s
Ẇ          - all sublists of s (order is short to long, left to right, e.g. a,b,c,ab,bc,abc)
 Ç€        - call the last link (1) as a monad for €ach
    ÐṀ     - filter by maximal
   L       -     length
      Ḣ    - head: get the first (and hence left-most) one
       Ṭ   - untruth: make a list with 1s at the indexes given and 0s elsewhere
        œp - partition s at truthy indexes of that, throwing away the borders
           - implicit print

6

자바 스크립트 (ES6), 81 74 바이트

f=
s=>s.replace(/(?=(.+)\1)/g,(_,m)=>r=m[r.length]?m:r,r='')&&s.replace(r,'')
<input oninput=o.textContent=f(this.value)><pre id=o>

편집 : @ Arnauld의 m[r.length]트릭 을 훔쳐서 7 바이트를 절약했습니다 .


5

PowerShell , 87 바이트

param($s)([regex](([regex]'(.+)\1'|% *hes $s|sort L*)[-1]|% Gr*|% V*)[1])|% Re* $s '' 1

온라인으로 사용해보십시오! (모든 테스트 사례)

설명

내부에서 시작 하여 지정된 문자열에 대한 모든 일치 객체를 반환하기 Matches위해 (.+)\1정규식으로 실행 합니다. 정규식은 그 뒤에 나오는 모든 문자 시퀀스와 일치합니다.

그런 다음 결과 일치 오브젝트를 파이프하여 속성 sort별로 정렬 Length합니다 (와일드 카드로 줄임). 이렇게하면 길이, 오름차순으로 정렬 된 일치 배열이 생겨 [-1]마지막 요소 (가장 긴 요소)를 얻을 수 있습니다. 일치하는 값은 그룹이 아니라 일치하므로 반복이 포함되므로 Group 객체 ( |% Gr*)를 검색 한 다음 그 값 ( |% V*)을 검색하여 가장 큰 반복 문자열을 가져옵니다. 그룹 0은 항상 일치하기 때문에 그룹 객체는 실제로 배열이지만 실제 그룹 (1)을 원하므로 결과 값은 실제로 값 s 이므로 인덱스는 두 번째 요소를 가져옵니다 [1]. 이 값은 정규식 객체 자체로 캐스팅 된 다음Replace메소드는 원래 문자열에 대해 호출되고 아무것도 대체하지 않으며 첫 번째 일치 항목 만 대체됩니다 ( |% Re* $s '' 1).


5

하스켈 , 101 바이트

주요 기능은 f그것이 필요하고를 반환합니다 String.

l=length
a=splitAt
f s|i<-[0..l s-1]=[p++t|n<-i,(p,(r,t))<-fmap(a$l s-n).(`a`s)<$>i,r==take(l r)t]!!0

온라인으로 사용해보십시오!

나는이 작업을 시작했을 때, 나는 수입 Data.List및 사용 maximum, tails, initsisPrefixOf. 어떻게 든 이것이 이것으로 바뀌 었습니다. 그러나 나는 여전히 11 바이트 만 면도했습니다 ...

노트

  • splitAt/ a주어진 인덱스에서 문자열을 분할합니다.
  • s 입력 문자열입니다.
  • i번호 목록이 [0 .. length s - 1]의는 -1것을 해결할 것입니다 splitAt끝에 분할이 너무 큰 인덱스를 제공합니다.
  • n되는 length s마이너스 현재 길이의 목표는 반복되는 부분, 그것은 그 방법을 선택이야 우리는리스트 구문을 감소 자세한 개의 번호 목록 및 / 또는를 사용 할 필요가 없습니다.
  • p, rt의 데이라이트를 분할 s하여, r(가) 부분을 반복하도록되어 있습니다. 는 fmap가 사용 (,) String Functor하는 중간 분할 가변 않도록.
  • !!0 일치하는 목록의 첫 번째 요소를 선택합니다.


4

Mathematica, 63 60 59 바이트

Martin Ender 로 인해 4 바이트가 절약되었습니다 .

#&@@StringReplaceList[#,a__~~a__->a]~SortBy~{StringLength}&

익명의 기능. 문자열을 입력으로 받아서 문자열을 출력으로 반환합니다.


이것은 예제 6에서 작동하지 않는 것 같습니다 – ~SortBy~StringLength길이가 같은 경우 문자열을 알파벳순으로 정렬합니다 ...
나무가 아닙니다

1
@ LegionMammal978 짧은 수정은 안정적인 정렬을 위해 목록을 유지 SortBy하고 감싸는 StringLength것입니다.
마틴 엔더

3

자바 스크립트 (ES6), 70 바이트

s=>s.replace(s.match(/(.+)(?=\1)/g).reduce((p,c)=>c[p.length]?c:p),'')

테스트 사례


에 실패 aaaabaaab하지만 잘 사용 reduce합니다.
Neil

2

이것은 의견이어야하지만 의견을 말할만큼 평판이 충분하지 않습니다. @Neil에게 그의 코드를 77 바이트로 줄일 수 있다고 말하고 싶습니다. 정규식에서는 정방향 어설 션을 사용할 필요가 없습니다. 다음은 축소 된 버전입니다.

s=>s.replace(/(.+)\1/g,(_,m)=>(n=m.length)>l&&(l=n,r=m),l=0)&&s.replace(r,'')

2
안녕하세요, PPCG에 오신 것을 환영합니다! 당신은 당신의 자신의 JavaScript 답변으로 제출할 수 있습니다! 원하는 경우 게시물을 수정하고 어떻게 표시되는지 보여줄 수 있습니다.
NoOneIsHere 여기

2
일치하는 일치하는 경우를 처리하려면 정방향 어설 션을 사용해야합니다. aabab제안이 실패하는 가장 짧은 예입니다.
Neil

0

C #, 169 바이트

(s)=>{var x="";for(int i=0;i<s.Length-2;i++){for(int l=1;l<=(s.Length-i)/2;l++){var y=s.Substring(i,l);if(s.Contains(y+y)&l>x.Length)x=y;}}return s.Replace(x+x,x);}

설명

(s) => {                // Anonymous function declaration    
    var x = "";         // String to store the longest repeating substring found
    for (int i = 0; i < s.Length - 2; i++) {               // Loop through the input string
        for (int l = 1; l <= (s.Length - i) / 2; l++) {    // Loop through all possible substring lengths
            var y = s.Substring(i, l);
            if (s.Contains(y + y) & l > x.Length) x = y;   // Check if the substring repeats and is longer than any previously found
        }
    }
    return s.Replace(x + x, x);    // Perform the replacement
}

이것은 무차별 접근 방식입니다. 가장 긴 반복 하위 문자열을 찾을 때까지 가능한 모든 하위 문자열을 시도하십시오. 의심 할 여지없이 정규식이 더 효율적이지만 C #에서 정규식을 처리하는 것은 매우 장황한 경향이 있습니다.


PPCG에 오신 것을 환영합니다! 모든 답변은 완전한 프로그램이거나 호출 가능한 함수 여야하며 하드 코딩 된 변수의 입력이있는 스 니펫은 확실하지 않습니다. 또한 불필요한 모든 공백을 제거하고 실제로 계산 한 코드 버전을 표시하십시오. 당신은 항상 완전히 골프 버전뿐만 아니라 들여 쓰기와 함께 더 읽기 쉬운 버전을 포함 할 수 있습니다.
Martin Ender

0

PHP, 84 82 바이트

참고 : IBM-850 인코딩을 사용합니다.

for($l=strlen($argn);--$l&&!$r=preg_filter("#(.{0$l})\g-1#",~█╬,$argn,1););echo$r;

다음과 같이 실행하십시오.

echo 'hello hello world' | php -nR 'for($l=strlen($argn);--$l&&!$r=preg_filter("#(.{0$l})\g-1#",~█╬,$argn,1););echo$r;';echo
> hello world

설명

for(
  $l=strlen($argn);   # Set $l to input length.
  --$l   &&           # Decrement $l each iteration until it becomes 0.
  !$r=preg_filter(    # Stop looping when preg_filter has a result
                      # (meaning a successful replace).
    "#(.{0$l})\g-1#", # Find any character, $l times (so the longest
                      # match is tried first), repeated twice.
    ~█╬,              # Replace with $1: first capture group, removing the
                      # duplicate.
    $argn,
    1                 # Only replace 1 match.
  );
);
echo$r;               # Print the result of the (only) successful
                      # search/replace, if any.

조정

  • 반복되는 하위 문자열의 최소 길이가 없으므로 2 바이트가 절약되었습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.