Normalisasi Substring Komunis

13

Jika string T dengan panjang K muncul K atau lebih banyak dalam string S , maka berpotensi komunis . Misalnya, 10dalam 10/10berpotensi komunis, karena muncul 2 kali dan panjangnya 2 . Perhatikan bahwa substring ini tidak dapat tumpang tindih.

Sebuah transformasi komunis adalah salah satu yang mengambil string ini T dan bergerak masing-masing karakter t i dari T ke saya terjadinya T di S . Jadi, untuk contoh sebelumnya, transformasi komunis akan menghasilkan 1/0; char pertama 10menggantikan 10pertama kali 10ditemukan, dan 0kedua kalinya.

Sebuah normalisasi komunis adalah fungsi yang mengambil semua string seperti T dengan K ≥ 2 dan melakukan transformasi komunis pada mereka.

Beberapa spesifikasi algoritma:

  1. Lakukan transformasi komunistik pada string T terlama yang valid terlebih dahulu . Mendukung kejadian pertama T .
  2. Kemudian, lakukan transformasi komunistik pada string terpanjang berikutnya, kemudian selanjutnya-terpanjang ... dll
  3. Ulangi sampai tidak ada string seperti itu di string.

Perhatikan bahwa beberapa string, seperti contoh "Halo, Halo" dalam kasus uji, dapat diartikan dua cara berbeda. Anda dapat menggunakan elluntuk T , tetapi Anda juga dapat menggunakan llo. Dalam hal ini, kode Anda dapat memilih salah satu opsi. Kasing uji yang ditampilkan menggunakan llo, tetapi Anda mungkin mendapatkan hasil yang berbeda dan sama-sama valid.


Tugas Anda adalah menerapkan normalisasi komunis. Input hanya akan terdiri dari karakter ASCII yang dapat dicetak (0x20 hingga 0x7E, space to tilde). Anda dapat menulis program atau fungsi untuk menyelesaikan tugas ini; input dapat diambil sebagai garis dari STDIN, argumen array karakter / string, argumen dari ARGV, dll.

Uji kasus

'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'

Mengerjakan test case

Formatnya adalah 'string', 'substring', pada setiap langkah penggantian. Bit yang diganti diberi tanda kurung.

'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', ''

Test case lain:

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

Kode referensi (Python)

Anda mungkin menemukan ini berguna untuk memvisualisasikan algoritma.

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

Terima kasih kepada @ ConorO'Brien karena memposting ide orisinil dari tantangan ini.

Rɪᴋᴇʀ
sumber
Uji kasus: ababab1ababab,1ab2ab3ab4ab5ab6
Zgarb
Mengapa tidak ada perubahan? abterjadi setidaknya dua kali di kedua string.
Zgarb
@Zgarb sepertinya penguji saya jelek, saya akan memperbaikinya nanti. Memperbaiki kasus uji secara manual.
Rɪᴋᴇʀ

Jawaban:

2

Pyth, 22 byte

u.xse.iLcGdf>cGTlTt#.:

Suite uji

Untuk benar-benar melihat apa yang sedang dilakukan program, lihat ini:

Internal

Secara khusus, program selalu menggunakan penggantian pengganti terpanjang yang terjadi akhir.

Penjelasan:

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.
isaacg
sumber
4

JavaScript (ES6), 121 byte

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

Secara rekursif cocok dengan pola:

(.{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.

... sampai polanya tidak ditemukan. (Ini menjamin bahwa string terpanjang ditangani terlebih dahulu.)

Kemudian melakukan "transformasi komunis" pada pola yang terakhir ditemukan, dengan memisahkan pada pertandingan, dan bergabung pada setiap karakter pertandingan. ( mapdigunakan untuk tujuan ini. Sayang sekali jointidak menerima panggilan balik.)

Akhirnya muncul kembali pada string baru ini sampai tidak lagi komunis .

Kasus uji:

Rick Hitchcock
sumber
1

Bersih , 420 ... 368 byte

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

Cobalah online!

Suram
sumber
Jawaban ini tidak valid. Lihat disini. Itu harus diubah, lihat test case.
Rɪᴋᴇʀ
@Riker menarik, karena ini adalah port langsung dari solusi referensi. Saya akan menghapus sampai diperbaiki.
Surous
@Riker memperbaiki sekarang.
Surous