ยกเลิกการทำซ้ำสตริง


33

บทนำ

ลองสังเกตสตริงต่อไปนี้:

AABBCCDDEFFGG

คุณจะเห็นว่าจดหมายทุกฉบับได้รับการซ้ำEยกเว้นตัวอักษร นั่นหมายความว่าตัวอักษรที่Eได้รับde-ซ้ำ ดังนั้นสิ่งเดียวที่เราต้องทำที่นี่คือการย้อนกระบวนการนั้นซึ่งทำให้เราไม่ได้ทำซ้ำสตริงต่อไปนี้:

AABBCCDDEEFFGG

ลองตัวอย่างที่ยากกว่านี้:

AAAABBBCCCCDD

คุณจะเห็นว่ามีจำนวนติดต่อกันไม่สม่ำเสมอBดังนั้นหมายความว่าหนึ่งในBBนั้นถูกทำซ้ำจากสตริงเดิม เราจำเป็นต้องยกเลิกการคัดลอกจดหมายฉบับนี้ซึ่งทำให้เรา:

AAAABBBBCCCCDD


ความท้าทาย

รับสตริงที่ไม่ซ้ำกันที่ไม่ว่างประกอบด้วยอักขระที่เป็นตัวอักษรเท่านั้น (ไม่ว่าจะเป็นตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็กเท่านั้น) ให้ส่งคืนสตริงที่ไม่ซ้ำกัน คุณสามารถสันนิษฐานได้ว่าจะมีอักขระที่ซ้ำกันอย่างน้อยหนึ่งตัวในสตริงเสมอ


กรณีทดสอบ

AAABBBCCCCDDDD    -->    AAAABBBBCCCCDDDD
HEY               -->    HHEEYY
AAAAAAA           -->    AAAAAAAA
N                 -->    NN
OOQQO             -->    OOQQOO
ABBB              -->    AABBBB
ABBA              -->    AABBAA

นี่คือดังนั้นการส่งที่ถูกต้องสั้นที่สุดในหน่วยไบต์ชนะ!


@ mbomb007 AABBBBใช่ว่าจะส่งผลในการ
Adnan

1
ฉันไม่แน่ใจว่าฉันเข้าใจความท้าทาย ทำไมABBBแมปไปAABBBBไม่ได้AABBBBBB?
เดนนิส

2
@Dennis ถ้าคุณแยกแต่ละกลุ่มของตัวละครที่เป็นกลุ่มของ 2, A BB Bคุณจะได้รับต่อไปนี้: อักขระที่ไม่ได้จับคู่ (และดังนั้นจึงไม่ซ้ำกัน) จะต้องมีการทำซ้ำส่งผลให้เกิดAA BB BBซึ่งเป็นสตริงที่ไม่ซ้ำกัน
Adnan

8
ดังนั้น: ตรวจสอบให้แน่ใจว่าตัวละครทุกตัวมีองค์ประกอบจำนวนเท่ากันโดยการเพิ่มองค์ประกอบเข้าไปในการเรียกใช้มากที่สุด
นักฟิสิกส์บ้า

1
@MadPhysicist ใช่ถูกต้องแล้ว
Adnan

คำตอบ:


20

MATL , 7 ไบต์

Y'to+Y"

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบทั้งหมด

ลองมา'ABBA'เป็นตัวอย่างอินพุต

Y'   % Implicit input. Run-length decoding
     % STACK: 'ABA', [1 2 1]
t    % Duplicate top of the stack
     % STACK: 'ABA', [1 2 1], [1 2 1]
o    % Modulo 2
     % STACK: 'ABA', [1 2 1], [1 0 1]
+    % Add, element-wise
     % STACK: 'ABA', [2 2 2]
Y"   % Run-length encoding. Implicit display
     % STACK: 'AABBAA'

11

เรติน่า 11 ไบต์

(.)\1?
$1$1

ลองออนไลน์ -มีกรณีทดสอบทั้งหมด


1
ฉันคาดว่า Retina จะชนะ
อดัม

@ Adámใช่มันค่อนข้างสั้น แต่คำตอบ MATL นั้นยอดเยี่ยม ภาษากอล์ฟทั้งหมดจบลงด้วยการแก้ปัญหาที่สั้นลง
mbomb007

8

Perl, 16 ไบต์

15 ไบต์ของรหัสเมือง + -pธง

s/(.)\1?/$1$1/g

วิธีเรียกใช้:

perl -pe 's/(.)\1?/$1$1/g' <<< 'HEY'

7

Haskell, 36 ไบต์

u(a:b:c)=a:a:u([b|a/=b]++c)
u x=x++x

ตัวอย่างการใช้งาน: ->u "OOQQO""OOQQOO"

หากสตริงมีองค์ประกอบอย่างน้อย 2 ชุดให้คัดลอกชุดแรกสองชุดและต่อท้ายสายเรียกซ้ำด้วย

  • องค์ประกอบที่สองส่วนที่เหลือถ้าองค์ประกอบสองคนแรกแตกต่างกันหรือ
  • ส่วนที่เหลือเพียง

หากมีองค์ประกอบน้อยกว่าสองรายการ (หนึ่งหรือศูนย์) ให้นำสำเนาสองชุดของรายการ


6

Brachylogขนาด 17 ไบต์

@b:{~b#=.l#e,|}ac

ลองออนไลน์!

คำอธิบาย

Example input: "ABBB"

@b                  Blocks: Split into ["A", "BBB"]
  :{          }a    Apply the predicate below to each element of the list: ["AA", "BBBB"]
                c   Concatenate: "AABBBB"

    ~b#=.             Output is the input with an additional element at the beginning, and
                        all elements of the output are the same (e.g. append a leading "B")
        .l#e,         The length of the Output is an even number
             |        Or: Input = Output (i.e. do nothing)


4

JavaScript (ES6), 37 30 ไบต์

ที่บันทึกไว้ 7 ไบต์โดยใช้ประสิทธิภาพมากขึ้น '$ 1 $ 1' เช่น[อื่น ๆ ] [ตอบ]ได้

s=>s.replace(/(.)\1?/g,'$1$1')

กรณีทดสอบ


4

Mathematica, 41 ไบต์

s=StringReplace;s[s[#,a_~~a_->a],b_->b~~b]&

ฟังก์ชันที่ไม่ได้ตั้งชื่อซึ่งป้อนสตริงและส่งออกสตริง ขจัดข้อมูลซ้ำซ้อนโดยสมบูรณ์และไม่ทำซ้ำให้สมบูรณ์ ไม่สั้นจริง แต่ตอนนี้ฉันทำไม่ได้ดีกว่านี้แล้ว


4

Befunge 98 , 24 ไบต์

#@~#;:::#@,~-:!j;$,;-\,;

ลองออนไลน์!

$สามารถเปลี่ยนได้อย่างง่ายดายด้วย-และที่ 2 ด้วย@;

ผมคิดว่านี้สามารถแข็งแรงเล่นกอล์ฟต่อเนื่องจากการ-ที่จุดเริ่มต้นของทั้งสอง-,(หรือ$,ด้านบน) -\,และ

อย่างไร?

Stack notation:  bottom [A, B, C, D] top

#@~     Pushes the first character onto the stack (C henceforth) and ends if EOF
#;      No-op to be used later
:::     Now stack is [C, C, C, C]

#@,~    Prints C, and if EOF is next (odd consecutive Cs), prints again and ends
        Lets call the next character D

-       Now stack is [C, C, C-D]
:!j;    If C == D, go to "$," Else, go to "-\,"

===(C == D)===

$,      C == D (i.e. a pair of Cs) so we discard top and print C (Stack is now [C])
;-\,;   Skipped, IP wraps, and loop starts again

===(C != D)===

-       Stack is [C, C-(C-D)]  By expanding: [C, C - C + D] or just [C, D]
\,      Prints C (Stack is now [D])

;#@~#;  This is skipped, because we already read the first character of a set of Ds,
        and this algorithm works by checking the odd character in a set of
        consecutive similar characters. We already read D, so we don't
        need to read another character.

3

Java 7, 58 ไบต์

String c(String s){return s.replaceAll("(.)\\1?","$1$1");}

Ungolfed:

String c(String s){
  return s.replaceAll("(.)\\1?", "$1$1");
}

รหัสทดสอบ:

ลองที่นี่

class M{
  static String c(String s){return s.replaceAll("(.)\\1?","$1$1");}

  public static void main(String[] a){
    System.out.println(c("AABBCCDDEFFGG"));
    System.out.println(c("AAAABBBCCCCDD"));
    System.out.println(c("AAABBBCCCCDDDD"));
    System.out.println(c("HEY"));
    System.out.println(c("AAAAAAA"));
    System.out.println(c("N"));
    System.out.println(c("OOQQO"));
    System.out.println(c("ABBB"));
    System.out.println(c("ABBA"));
  }
}

เอาท์พุท:

AABBCCDDEEFFGG
AAAABBBBCCCCDD
AAAABBBBCCCCDDDD
HHEEYY
AAAAAAAA
NN
OOQQOO
AABBBB
AABBAA

2

PHP, 65 ไบต์, ไม่มี regex

while(""<$c=($s=$argv[1])[$i])if($c!=$s[++$i]||!$k=!$k)echo$c.$c;

รับอินพุตจากอาร์กิวเมนต์บรรทัดคำสั่ง -rทำงานด้วย

regex? ใน PHP regex ที่ใช้โดยคำตอบส่วนใหญ่จะซ้ำกันทุกตัวอักษร จะเป็น 44 ไบต์:

<?=preg_replace("#(.)\1?#","$1$1",$argv[1]);

2

Brain-Flak 69 ไบต์

รวมถึง +3 สำหรับ -c

{((({}<>))<>[({})]<(())>){((<{}{}>))}{}{(<{}{}>)}{}}<>{({}<>)<>}<>

ลองออนไลน์!

คำอธิบาย:

Part 1:
{((({}<>))<>[({})]<(())>){((<{}{}>))}{}{(<{}{}>)}{}}<>

{                                                  }   # loop through all letters
 (   {}     [ {} ]<(())>){((<{}{}>))}{}                # equals from the wiki   
                                                       # but first:
  ((  <>))<>                                           # push the top letter on the other 
                                                       # stack twice  
             (  )                                      # push the second letter back on
                                       {        }      # if they were equal:
                                        (<    >)       # push a 0 to exit this loop
                                          {}{}         # after popping the 1 from the 
                                                       # comparison and the next letter
                                                       # (the duplicate)
                                                 {}    # pop the extra 0
                                                    <> # switch stacks

Part 2 (at this point, everything is duplicated in reverse order):
{({}<>)<>}<>

{        }   # for every letter:
 ({}<>)      # move the top letter to the other stack
       <>    # and switch back
          <> # Finally switch stacks and implicitly print


1

V 10 ไบต์

ͨ.©±½/±±

TryItOnline

เพียงค้นหาและแทนที่ regex เหมือนกับส่วนที่เหลือทั้งหมดในเธรด ความแตกต่างเพียงอย่างเดียวคือฉันสามารถแทนที่สิ่งที่จะต้องมี\ด้านหน้าด้วยอักขระที่มีค่า ascii เหมือนกัน แต่ตั้งค่าบิตสูง (ดังนั้น(00101000 กลายเป็น¨10101000)


1

Perl 6 , 17 ไบต์

s:g/(.)$0?/$0$0/

ด้วยสวิตช์บรรทัดคำสั่ง -p

ตัวอย่าง:

$ perl6 -pe 's:g/(.)$0?/$0$0/' <<< 'AAABBBCCCCDDDD
> HEY
> AAAAAAA
> N
> OOQQO
> ABBB
> ABBA'
AAAABBBBCCCCDDDD
HHEEYY
AAAAAAAA
NN
OOQQOO
AABBBB
AABBAA

1

แร็กเก็ต 261 ไบต์

(let((l(string->list s))(r reverse)(c cons)(e even?)(t rest)(i first))(let p((l(t l))(ol(c(i l)'())))
(cond[(empty? l)(list->string(if(e(length ol))(r ol)(r(c(i ol)ol))))][(or(equal?(i ol)(i l))(e(length ol)))
(p(t l)(c(i l)ol))][(p(t l)(c(i l)(c(i ol)ol)))])))

Ungolfed:

(define (f s)
  (let ((l (string->list s)))
    (let loop ((l (rest l))
               (ol (cons (first l) '())))
      (cond
        [(empty? l)
         (list->string(if (even? (length ol))
                          (reverse ol)
                          (reverse (cons (first ol) ol))))]
        [(or (equal? (first ol) (first l)) 
             (even? (length ol)))
         (loop (rest l) (cons (first l) ol))]
        [else
         (loop (rest l) (cons (first l) (cons (first ol) ol)))] ))))

การทดสอบ:

(f "ABBBCDDEFFGGG")

เอาท์พุท:

"AABBBBCCDDEEFFGGGG"

1

05AB1E , 10 ไบต์

.¡vy¬ygÉ×J

ลองออนไลน์!

คำอธิบาย

.¡           # split string into groups of the same char
  v          # for each group
   y         # push the group
    ¬        # push the char the group consists of
     yg      # push the length of the group
       É     # check if the length of the group is odd
        ×    # repeat the char is-odd times (0 or 1)
         J   # join to string

1

Python3, 102 94 ไบต์

from collections import*
lambda s:"".join(c*(s.count(c)+1&-2)for c in OrderedDict.fromkeys(s))

ขอบคุณxnorสำหรับการบันทึก 8 ไบต์! -> bithack


สิ่งนี้ไม่ได้เก็บตัวอักษรไว้ในลำดับที่ถูกต้อง
xnor

@ xnor ขอบคุณที่กล่าวถึง! คงที่
Yytsi

ดูดี. คุณสามารถเขียนการแสดงออกเป็นx+x%2 x&-2
xnor

@xnor ฉันลองs.count(c)&-2แล้วมันคืนค่าสตริงว่างเปล่า ... : / ความคิดใด ๆ
Yytsi

1
โอ้คุณพูดถูกและฉันทำผิดไป ฉันคิดว่าx+1&-2ควรทำ Evens ไปกับตัวเองและราคาต่อรองขึ้นไปถึง evens
xnor

1

R, 81 ไบต์

r=rle(el(strsplit(scan(,""),"")));cat(do.call("rep",list(r$v,r$l+r$l%%2)),sep="")

อ่านสตริงจาก stdin, splin เป็นเวกเตอร์ของอักขระและทำการเข้ารหัสแบบ run-length (rle) ต่อจากนั้นทำซ้ำค่าจากแต่ละ RLE 2ผลรวมของความยาวและความยาวพอควร

หากเราสามารถอ่านอินพุตที่คั่นด้วยช่องว่าง (โดยปริยายเป็นเวกเตอร์ / อาเรย์ของอักขระ) จากนั้นเราสามารถข้ามส่วนที่แยกออกและโปรแกรมลดขนาดเป็น 64 ไบต์:

r=rle(scan(,""));cat(do.call("rep",list(r$v,r$l+r$l%%2)),sep="")

1

> <> (ปลา) 39 ไบต์

0v ;oo:~/:@@:@=?!voo
 >i:1+?!\|o !:  !<

ค่อนข้างแน่ใจว่านี่สามารถเล่นกอล์ฟได้มากโดยใช้เทคนิคที่แตกต่าง

มันจะรับอินพุตและเปรียบเทียบกับรายการสแต็กปัจจุบันถ้ามันแตกต่างกันมันจะพิมพ์รายการสแต็กแรกสองครั้งถ้ามันพิมพ์ทั้งคู่

สแต็กเมื่อไม่มีข้อมูลมาพร้อมกับ 0 ซึ่งไม่สามารถพิมพ์ได้ดังนั้นเมื่อใดก็ตามที่ผนวกเข้าด้วยกัน


1

Pyth, 15 ไบต์

Vrz8p*+hN%hN2eN

ตรวจสอบกรณีทดสอบทั้งหมดที่นี่

ขอบคุณLuis Mendoสำหรับวิธีการ

คำอธิบาย

Vrz8p*+hN%hN2eN    z autoinitializes to the input
 rz8               run-length encode the input, returned as list of tuples (A -> [[1,"A"]])
V                  for every element N in this list
      +hN          add the head element of N (the number in the tuple)
         %hN2      to the head element of N mod 2
     *       eN    repeat the tail element of N that many times (the letter in the tuple)
    p              print repeated character without trailing newline

บ่อยครั้งที่ฉันรู้สึกว่ามันอาจสั้นกว่านี้ ฉันคิดว่าควรมีวิธีที่ดีกว่าในการแยกองค์ประกอบออกจากรายการมากกว่าสิ่งที่ฉันใช้ที่นี่


1

PowerShellขนาด 28 ไบต์

$args-replace'(.)\1?','$1$1'

ลองออนไลน์! (รวมถึงกรณีทดสอบทั้งหมด)

พอร์ตของคำตอบ Retina จุดที่น่าสังเกตุคือเราได้รับ$argsแทนที่จะเป็นแบบปกติ$args[0](เนื่องจากมัน-replaceจะวนซ้ำในแต่ละรายการในแถวลำดับเราสามารถตีดัชนีได้) และ'$1$1'ความต้องการที่จะเป็นเครื่องหมายคำพูดเดี่ยวดังนั้นพวกเขาจึงถูกแทนที่ด้วย regex ตัวแปรแทนที่จะถูกใช้เป็นตัวแปร PowerShell (ซึ่งจะเกิดขึ้นหากเป็นเครื่องหมายคำพูดคู่)


1

C, 67 ไบต์

i;f(char*s,char*d){i=*s++;*d++=i;*d++=i;*s?f(i-*s?s:++s,d):(*d=0);}

โทรด้วย:

int main()
{
    char *in="AAABBBCCCCDDDD";
    char out[128];
    f(in,out);
    puts(out);
}

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