การทำให้เป็นสตริงย่อยแบบคอมมิวนิสต์


13

ถ้าสตริงTของความยาวKปรากฏKครั้งหรือมากกว่าในสตริงSแล้วมันอาจเป็นคอมมิวนิสต์ ยกตัวอย่างเช่น10ใน10/10อาจเป็นคอมมิวนิสต์มันปรากฏขึ้น2ครั้งและมีความยาว2 โปรดทราบว่าสตริงย่อยเหล่านี้ไม่สามารถทับซ้อนกันได้

เปลี่ยนแปลงคอมมิวนิสต์เป็นหนึ่งที่จะสายนี้Tและย้ายตัวละครแต่ละทีฉันของTกับฉันการเกิดขึ้นของTในS ดังนั้นสำหรับตัวอย่างก่อนหน้าการเปลี่ยนแปลงของคอมมิวนิสต์จะให้ผล1/0; ตัวอักษรตัวแรกของ10แทนที่10ครั้งแรกที่10พบและ0ครั้งที่สอง

ฟื้นฟูคอมมิวนิสต์เป็นฟังก์ชั่นที่ใช้เวลาสตริงทั้งหมดเช่นTกับK ≥ 2 และดำเนินการเปลี่ยนแปลงคอมมิวนิสต์กับพวกเขา

ข้อมูลจำเพาะบางอย่างเกี่ยวกับอัลกอริทึม:

  1. ดำเนินการแปลงคอมมิวนิสต์ในสายที่ยาวที่สุดที่ถูกต้องT แรก Favor เกิดขึ้นเป็นครั้งแรกของT
  2. จากนั้นทำการแปลงคอมมิวนิสต์ในสตริงถัดไปยาวที่สุดจากนั้นถัดไปยาวที่สุด ... ฯลฯ
  3. ทำซ้ำจนกระทั่งไม่มีสตริงดังกล่าวอยู่ในสตริง

โปรดทราบว่าบางสตริงเช่นตัวอย่าง "Hello, Hello" ในกรณีทดสอบสามารถตีความได้สองวิธี คุณสามารถใช้ellสำหรับTlloแต่คุณยังสามารถใช้ ในกรณีนี้รหัสของคุณสามารถเลือกได้ทั้งตัวเลือก กรณีทดสอบที่แสดงใช้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#.:

ชุดทดสอบ

หากต้องการดูสิ่งที่โปรแกรมกำลังทำอยู่ให้ตรวจสอบสิ่งนี้:

internals

โดยเฉพาะอย่างยิ่งโปรแกรมจะใช้การแทนที่ที่เกิดขึ้นครั้งสุดท้ายของการเปลี่ยนที่ยาวที่สุดเสมอ

คำอธิบาย:

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จะไม่โทรกลับ)

ในที่สุดมันก็ recurses ในสตริงใหม่นี้จนกว่าจะไม่มีอีกต่อไปคอมมิวนิสต์

กรณีทดสอบ:


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 ที่น่าสนใจเพราะมันเป็นพอร์ตโดยตรงของการแก้ปัญหาการอ้างอิง ฉันจะลบจนกว่าจะได้รับการแก้ไข
Janurous

@Riker แก้ไขแล้ว
Janurous
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.