Нормалізація комуністичної підрядки


13

Якщо рядок T довжиною K з’являється K або більше разів у рядку S , він потенційно є комуністичним . Наприклад, 10у 10/10потенційно комуністична, бо вона з'являється в 2 рази і має 2 довжини . Зауважте, що ці підрядки не можуть перетинатися.

Комуністичне перетворення є той , який приймає цей рядок T і переміщує кожен символ т I з Т до я входженню Т в S . Так, для попереднього прикладу комуністична трансформація дала б результат 1/0; перший знак 10замінює 10перший раз 10, а 0другий раз.

Комуністична нормалізація це функція , яка приймає всі такі рядки T з K ≥ 2 і виконує комуністичне перетворення на них.

Деякі особливості алгоритму:

  1. Виконання перетворень на комуністичні довжелезних дійсні рядки T першими . Favor перші входження Т .
  2. Потім виконайте комуністичні перетворення на наступних найдовших струнах, потім наступних-наступних-найдовших ... і т.д.
  3. Повторюйте, поки в рядку не існує таких рядків.

Зауважте, що деякі рядки, наприклад приклад "Привіт, привіт" у тестових випадках, можна інтерпретувати двома різними способами. Ви можете використовувати 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 схоже, що мій тестер поганий, я це виправлю пізніше. Виправлення тестових випадків вручну.
Rɪᴋᴇʀ

Відповіді:


2

Піт, 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

JavaScript (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 цікаво, адже це прямий порт референтного рішення. Я видалю, поки не буде виправлено.
Οurous

@Riker виправлено зараз.
Οurous
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.