Communistic 하위 문자열 정규화


13

길이 K 의 문자열 T 가 문자열 S 에서 K 이상으로 나타날 경우 잠재적으로 통신 가능 합니다. 예를 들어, in 은 잠재적으로 친숙합니다. 2 번 나타나고 길이가 2 이기 때문입니다 . 이 하위 문자열은 겹칠 수 없습니다.1010/10

공산주의 변환 문자열 얻어 하나 T를 , 각 캐릭터를 이동 t를 IT 받는 I 의 발생 T 에서 S . 따라서, 이전 예를 들면, 공산주의 변환은 얻을 것이다 1/0; 의 첫 번째 문자 10을 대체 10처음으로 10발견하고, 0두 번째 시간입니다.

공산주의 정규화는 그러한 모든 문자열 취하는 함수이다 TK ≥ 2가 행하는 공산주의 변환 그들.

알고리즘에 대한 일부 세부 사항 :

  1. 가장 긴 유효한 문자열 T에서 먼저 변환 변환을 수행하십시오 . T 의 첫 항목을 선호하십시오 .
  2. 그런 다음 가장 긴 문자열에서 다음으로 가장 긴 문자열 등에서 공산주의 적 변환을 수행하십시오.
  3. 해당 문자열이 문자열에 없을 때까지 반복하십시오.

테스트 사례에서 "Hello, Hello"예제와 같은 일부 문자열은 두 가지 다른 방식으로 해석 될 수 있습니다. 당신은 사용할 수 있습니다 ell에 대한 T ,하지만 당신은 또한 사용할 수 있습니다 llo. 이 경우 코드에서 옵션을 선택할 수 있습니다. 표시된 테스트 사례는을 사용 llo하지만 다른 동일한 결과를 얻을 수 있습니다.


당신의 임무는 공산주의 정상화를 구현하는 것입니다. 입력은 인쇄 가능한 ASCII 문자 (0x20 ~ 0x7E, 물결표 간격)로만 구성됩니다. 이 작업을 해결하기위한 프로그램이나 함수를 작성할 수 있습니다. 입력은 STDIN의 행, 문자열 / 문자 배열 인수, ARGV의 인수 등으로 가져올 수 있습니다.

테스트 사례

'123' -> '123'
'111' -> '111'
'1111' -> '11'
'ABAB' -> 'AB'
'111111111' -> '111'
'asdasdasd' -> 'asd'
'10/10' -> '1/0'
'100/100+100' -> '1/0+0'
'   +   +   ' -> ' + '
'Hello, hello, dear fellow!' -> 'Hel he, dear feow!' OR 'Heo hl, dear flow!'
'11122333/11122333/11122333' -> '112/13' OR '132/23'

'ababab1ababab' -> 'a1bab'
'1ab2ab3ab4ab5ab6' -> '1a2b3a4b5ab6'

테스트 사례 해결

'string', 'substring'각 교체 단계에서 형식은 입니다. 교체 된 비트는 괄호로 묶습니다.

'11[122]333/11[122]333/11[122]333', '122'
'111[333]/112[333]/112[333]', '333'
'1113/11[23]/11[23]', '23'
'11[13]/112/1[13]', '13'
'1[11]/[11]2/13', '11'
'1[/1]12[/1]3', '/1'
'112/13', ''

다른 테스트 사례 :

'Hello, hello, dear fellow!', 'llo'
'Hel, hel, dear feow!', 'l,'
'Hel he, dear feow!', ''

참조 코드 (Python)

알고리즘을 시각화하는 데 유용 할 수 있습니다.

#!/usr/bin/env python

import re

def repeater(string):
    def repeating_substring(substring):
        return (string.count(substring) == len(substring)) and string.count(substring) > 1

    return repeating_substring

def get_substrings(string):
    j = 1
    a = set()
    while True:
        for i in range(len(string) - j+1):
            a.add(string[i:i+j])
        if j == len(string):
            break
        j += 1
    return list(a)

def replace_each_instance(string, substring):
    assert `string`+',', `substring`
    for i in substring:
        string = re.sub(re.escape(substring), i, string, 1)

    return string


def main(s):
    repeats = repeater(s)
    repeating_substr = filter(repeater(s), get_substrings(s))

    while repeating_substr:
        repeating_substr.sort(lambda x,y: cmp(len(y), len(x)))
        s = replace_each_instance(s, repeating_substr[0])
        repeating_substr = filter(repeater(s), get_substrings(s))

    return s

assert main('123') == '123'
assert main('111') == '111'
assert main('1111') == '11'
assert main('ABAB') == 'AB'
assert main('111111111') == '111'
assert main('asdasdasd') == 'asd'
assert main('10/10') == '1/0'
assert main('100/100+100') == '1/0+0'
assert main('   +   +   ') == ' + '
assert main('Hello, hello, dear fellow!') == 'Hel he, dear feow!'
assert main('11122333/11122333/11122333') == '112/13'

이 도전의 원래 아이디어를 게시 한 @ ConorO'Brien에게 감사합니다.


테스트 사례 : ababab1ababab,1ab2ab3ab4ab5ab6
Zgarb

왜 변화가 없습니까? ab두 문자열에서 두 번 이상 발생합니다.
Zgarb

@ Zgarb는 테스터가 나쁜 것 같습니다. 나중에 수정하겠습니다. 테스트 케이스를 수동으로 수정하십시오.
Rɪᴋᴇʀ

답변:


2

Pyth, 22 바이트

u.xse.iLcGdf>cGTlTt#.:

테스트 스위트

실제로 프로그램이 수행하는 작업을 보려면 다음을 확인하십시오.

내부

특히, 프로그램은 항상 가장 긴 교체의 최종 발생 교체를 사용합니다.

설명:

u.xse.iLcGdf>cGTlTt#.:
u.xse.iLcGdf>cGTlTt#.:G)GQ    Implicit
u                        Q    Starting with the input, repeat the following
                              until a fixed point is reached.
                    .:G)      Construct all substrings of the current value
                              ordered smallest to largest, front to back.
                  t#          Filter on having more than 1 element.
                              These are the eligible substrings.
           f                  Filter these substrings on
             cGT              Chop the current value on the substring,
            >   lT            Then remove the first len(substring) pieces.
                              The result is nonempty if the substring is
                              one we're looking for. 
                              Chopping gives nonoverlapping occurrences.
     .iL                      Interlace the substrings with
        cGd                   Chop the current value on that substring
   se                         Take the final result, make it a string.
 .x                     G     If there weren't any, the above throws an error,
                              So keep the current value to halt.

4

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

f=(s,j=2,o,m=s.match(`(.{${j}})(.*\\1){${(j-1)}}`))=>m?f(s,j+1,s.split(m[1]).map((e,i)=>e+(m[1][i]||'')).join``):o?f(o):s

패턴을 재귀 적으로 일치시킵니다.

(.{2})(.*\1){1}  //2 characters, repeated 1 time 
(.{3})(.*\1){2}  //3 characters, repeated 2 times 
(.{4})(.*\1){3}  //4 characters, repeated 3 times 
etc.

… 패턴을 찾을 수 없을 때까지. 이렇게하면 가장 긴 문자열을 먼저 처리 할 수 ​​있습니다.

그런 다음 일치 항목을 분할하고 각 일치하는 문자를 결합하여 마지막 발견 패턴에서 "공동 변환"을 수행합니다. ( map이 목적으로 사용됩니다. 너무 나쁘면 join콜백하지 않습니다.)

더 이상 때까지 드디어 새로운 문자열에 재귀하지 공산주의 .

테스트 사례 :


1

클린 , 420 ... 368 바이트

import StdEnv,StdLib
l=length
%q=any((==)q)
?_[]=[]
?a[(y,x):b]|isPrefixOf a[x:map snd b]=[y: ?a(drop(l a-1)b)]= ?a b
$s=sortBy(\a b=l a>l b)(flatten[[b: $a]\\(a,b)<-map((flip splitAt)s)[0..l s-1]])
f s#i=zip2[0..]s
#r=filter(\b=l(?b i)>=l b&&l b>1)($s)
|r>[]#h=hd r
#t=take(l h)(?h i)
=f[if(%n t)(h!!hd(elemIndices n t))c\\(n,c)<-i|not(%n[u+v\\u<-t,v<-[1..l h-1]])]=s

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


이 답변은 유효하지 않습니다. 여길 봐. 변경해야합니다. 테스트 사례를 참조하십시오.
Rɪᴋᴇʀ

@Riker는 참조 솔루션의 직접적인 포트이기 때문에 흥미 롭습니다. 수정 될 때까지 삭제하겠습니다.
OUurous

@Riker가 수정되었습니다.
OUurous
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.