非重複文字列


33

前書き

次の文字列を観察してみましょう。

AABBCCDDEFFGG

手紙を除いて、すべての手紙が複製されていることがわかりEます。それは、手紙E重複していないことを意味します。したがって、ここで行う必要があるのは、そのプロセスを逆にすることだけです。これにより、次の重複のない文字列が得られます。

AABBCCDDEEFFGG

もっと難しい例を見てみましょう。

AAAABBBCCCCDD

連続したBの数が不均一であることがわかりBBます。つまり、元の文字列の1つが重複していないことを意味します。この手紙の重複を取り消すだけで、次のことができます。

AAAABBBBCCCCDD


チャレンジ

空でない所与の重複除外で構成される文字列、英字のみ(どちらかのみ大文字または小文字のみ)、戻り非重複除外文字列。文字列には少なくとも1つの重複排除された文字が常に存在すると想定できます。


テストケース

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

これはであるため、バイト単位の最短の有効な送信が優先されます!


@ mbomb007はい、それはになりAABBBBます。
アドナン

1
課題を理解したかどうかはわかりません。ABBBマッピングしAABBBBないのはなぜAABBBBBBですか?
デニス

2
@Dennis文字の各グループを2つのグループに分けると、次のようになりますA BB B。ペアになっていない(したがって複製されていない)文字を複製する必要があります。その結果、AA BB BB重複しない文字列がになります。
アドナン

8
そのため、最大1つの要素を実行に追加することで、すべての文字の実行に偶数の要素が含まれるようにしますか?
マッド物理学者

1
@MadPhysicistはい、それは正しいです
アドナン・

回答:


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'


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つの要素がある場合、最初の2つのコピーを取得し、再帰呼び出しを追加します

  • 最初の2つの要素が異なる場合は2番目の要素、残りは
  • 残りだけ

要素が2つ未満(1つまたは0)の場合、リストのコピーを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バイト

[その他] [回答]のように、はるかに効率的な '$ 1 $ 1'を使用して7バイトを節約しました

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");}

ゴルフをしていない:

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バイト、正規表現なし

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

コマンドライン引数から入力を受け取ります。で実行し-rます。

正規表現? PHPでは、ほとんどの回答で使用される正規表現はすべての文字を複製します。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

スレッド内の残りのすべてと同じように正規表現を見つけて置き換えます。唯一の違いは、その\前に必要なものはすべて、同じASCII値で、高ビットが設定されている文字に置き換えることができることです。(つまり(、00101000は¨10101000になります)



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)))])))

ゴルフをしていない:

(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))

8バイトを節約してくれたxnorに感謝します!-> bithack。


これは、文字を正しい順序に保ちません。
xnor

@xnor言及してくれてありがとう!一定。
Yytsi

いいね。式はx+x%2として記述できますx&-2
XNOR

@xnor私は試しましs.count(c)&-2たが、空の文字列を返しました...:/考えはありますか?
Yytsi

1
ああ、あなたは正しいです、私は間違いを犯しました。x+1&-2すべきだと思う。偶数は自分自身に行き、オッズは偶数に切り上げられます。
XNOR

1

R、81バイト

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

stdinから文字列を読み取り、文字のベクトルにsplinし、ランレングスエンコーディング(rle)を実行します。その後、rleの各値、長さの合計、および長さmodを繰り返します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 !:  !<

別のテクニックを使用して、これをたくさんゴルフできることはかなり確かです。

入力を受け取り、現在のスタック項目と比較します。異なる場合は最初のスタック項目を2回印刷し、同じ場合は両方を印刷します。

空のときのスタックには何も出力しない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'

オンラインでお試しください!(すべてのテストケースを含む)

網膜の答えのポート。ノートの唯一のポイントは、我々が持っている$args代わりに、通常の$args[0](以降-replace、入力配列の各項目を反復処理するような、我々はインデックスoffゴルフができます)、および'$1$1'それらを正規表現で置き換えられているようなニーズは、単一引用符を可能にします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.