文字列を削除する


39

多くの言語には、重複を取り除く、またはリストまたは文字列を「重複排除」または「一意化」する組み込みの方法があります。あまり一般的ではないタスクは、文字列を「削除」することです。つまり、表示されるすべての文字について、最初の2つの出現が保持されます。

削除する必要がある文字にラベルが付けられている例を次に示します^

aaabcbccdbabdcd
  ^    ^ ^^^ ^^
aabcbcdd

あなたの仕事は、まさにこの操作を実装することです。

ルール

入力は単一の、場合によっては空の文字列です。ASCII範囲の小文字のみが含まれていると想定できます。

出力は、文字列に少なくとも2回出現したすべての文字が削除された単一の文字列である必要があります(したがって、左端の2つの出現は保持されます)。

文字列の代わりに、文字のリスト(またはシングルトン文字列)を使用できますが、形式は入力と出力の間で一貫している必要があります。

プログラムまたは関数を作成し、入力を受け取り出力を提供する当社の標準的な方法を使用できます。

任意のプログラミング言語を使用できますが、これらの抜け穴はデフォルトでは禁止されています。

これはであるため、バイト単位で測定された最短の有効な回答が勝ちます。

テストケース

行の各ペアは1つのテストケースであり、入力の後に出力が続きます。



xxxxx
xx
abcabc
abcabc
abcdabcaba
abcdabc
abacbadcba
abacbdc
aaabcbccdbabdcd
aabcbcdd

リーダーボード

この投稿の下部にあるスタックスニペットは、a)言語ごとの最短ソリューションのリストとして、b)全体的なリーダーボードとして、回答からリーダーボードを生成します。

回答が表示されるようにするには、次のマークダウンテンプレートを使用して、見出しから回答を開始してください。

## Language Name, N bytes

N提出物のサイズはどこですか。スコアを改善する場合、古いスコアを打つことで見出しに残すことができます。例えば:

## Ruby, <s>104</s> <s>101</s> 96 bytes

ヘッダーに複数の数字を含める場合(たとえば、スコアが2つのファイルの合計であるか、インタープリターフラグペナルティーを個別にリストする場合)、実際のスコアがヘッダーの最後の数字であることを確認します。

## Perl, 43 + 3 (-p flag) = 45 bytes

言語名をリンクにして、スニペットに表示することもできます。

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


5
シングルトン文字列... stringletons?
dkudriavtsev

回答:



15

JavaScript(ES6)、42 48

なんと6バイトを節約した編集 @thx @Neil

s=>s.replace(k=/./g,c=>(k[c]+=c)[11]?'':c)

説明:オブジェクトのプロパティ 'a' ... 'z'を使用して、k各文字の情報を保存します(この場合、オブジェクトkはバイトを保存するための正規表現です)。これらのプロパティは最初はundefinedです。JavaScriptでに番号を追加するundefined与えるNaN(非常に賢明)が、文字列「X」を追加与える"undefinedX"-長さ10(愚か)の文字列。文字を追加すると、長い文字列が得られます。特定の文字について取得された文字列が11を超える場合、その文字は出力にコピーされません。

テスト

F=
s=>s.replace(k=/./g,c=>(k[c]+=c)[11]?'':c)

test=`

xxxxx
xx
abcabc
abcabc
abcdabcaba
abcdabc
abacbadcba
abacbdc
aaabcbccdbabdcd
aabcbcdd`.split`\n`
for(i=0;i<test.length;)
  a=test[i++],b=test[i++],r=F(a),
  console.log(r==b?'OK':'KO',a,'->',r,b)


厳密に言えば、空の行はテストケースの1つです。
ニール

@Neil okは空の文字列テストを追加しました
edc65

配列の入力と出力に切り替えると、.filterを使用してさらに12文字を保存できます。 v=>v.filter(x=>!(v[x]+=x)[11])。「未定義」ハックに関する称賛。
-Grax32

@Grax thanxですが、あまりにも違います。自分で投稿する必要があります
-edc65

14

Python 2、48バイト

lambda s:reduce(lambda r,c:r+c*(r.count(c)<2),s)

c[r.count(c)/2:]は、と同じ長さの代替c*(r.count(c)<2)です。


49バイト:

r=''
for c in input():r+=c*(r.count(c)<2)
print r

12

網膜、17バイト

(.)(?<=\1.*\1.+)

オンラインでお試しください!

単純な正規表現の置換-文字が既に2回出現した場合に一致し、削除します。


また、ループ、およびで繰り返しグループを{2}試しまし。どちらも18バイトです。
コビ

1
最近追加された機能を使用して14を取得しました。;)
マーティン・エンダー

私は何かがあることを知っていました。おそらくそれではなく、限界を見ました。もう一度確認します。
コビ

3
ああ、私はマーティンの答えを見つけたと思う。以前に試していたときに問題が発生しました。複数行の入力で重複排除がどのように機能するかを考慮していなかったからだと思います。スポイラー(5とあたりラインモードを有効にするために追加バイト):retina.tryitonline.net/...
FryAmTheEggman

@FryAmTheEggman-いいですね、これは見つかりませんでした。回答を自由に追加してください-これは私の回答とはあまりにも異なると思います:P。ありがとう!
コビ

6

Brachylog、25バイト

.v|s.g:.z:1a
:2fl<3
he~t?

オンラインでお試しください!または、すべてのテストケースを確認します

説明

これs - Subsetは、より大きなサブセットと最初に統合されるため、たとえば、before "aaa"を試みるため"aa"に機能し"a"ます。

  • 主な述語:

      .v         input = Output = ""
    |          Or
      s.         Output is an ordered subset of the input
      g:.z       Zip each character of the output with the output itself
      :1a        Apply predicate 1 on each element of the zip
    
  • 述語1:すべての文字が2回までしか表示されないことを確認します。入力=[String:Char]

    :2f        Find all valid outputs of predicate 2 (i.e. one output per occurence
                   of the char)
    l<3        There are less than 3 occurences
    
  • 述部2:キャラクターの出現を取得します。入力=[String:Char]

    he         Take a character of the string in the input
      ~t?      That character is the char of the input
    

6

> <>、22バイト

i:0(?;::9g:}2(?o{1+$9p

オンラインでお試しください!コードボックスを使用して、これまでのカウントを追跡します。

i                       Read a char c of input
 :0(?;                  Halt if EOF
      :                 Make a copy - stack has [c c] at the top
       :9g              Get count stored at (c, 9)
          :}            Copy the count and move to bottom of stack
            2(?o        If the count is less than 2, output c
                {1+     Move the count back to the top of the stack and increment
                   $9p  Update cell at (c, 9)
                        [Instruction pointer moves to start as ><> is toroidal]

6

J、20 15バイト

#~(3>[+/@:={:)\

これは、文字列を受け取って返す単項関数を定義します。ここで試してみてください。使用法:

   f =: #~(3>[+/@:={:)\
   f 'abaacbb'
abacb

説明

他のソリューションが使用しているアルゴリズムと同じアルゴリズムに切り替えました。

#~(3>[+/@:={:)\  Input is y.
  (          )\  For each prefix of y:
          =        compute the equality vector
     [     {:      of the prefix and its last element, and
      +/@:         take its sum. Now we have a vector r such that y[i] has its
                   r[i]'th occurrence at position i.
   3>              Mark those coordinates where r[i] < 3.
#~               Remove the non-marked characters from y.

6

Haskell、40 39バイト

foldl(\s c->s++[c|filter(==c)s<=[c]])""

使用例:foldl(\s c->s++[c|filter(==c)s<=[c]])"" "aaabcbccdbabdcd"- > "aabcbcdd"

これまでcのすべてcのsの文字列が辞書編集的にシングルトン文字列以下である場合、次の文字を保持します[c]

編集:@xnorはリストの内包表記からに切り替えて1バイトを保存しましたfilter。ありがとう!


代わりにfilter(==c)s<=[c]バイトを保存することもできます。
xnor


5

C、57バイト

f()文字列を使用して呼び出して、削除します。関数はそのパラメーターを変更します。for-loop宣言のため、C99が必要です。

f(char*p){for(char*s=p,m[256]={0};*s=*p;s+=++m[*p++]<3);}

sの最初のステートメントにの宣言を入れられませんforか?
マーティンエンダー

C99ではできます。ゴルフC89との互換性を保ちたいので、私はそうしなかった。
owacoder

5

JavaScript(ES6)、35バイト

s=>s.filter(c=>(s[c]=(s[c]|0)+1)<3)

入力として文字の配列を取り、重複排除された配列を返します。


いいね c=>(s[c]=-~s[c])<3数バイト節約することができます。
ETHproductions

入力として配列を使用できることを逃し、を使用して関数を記述していましたmap。ゴルフは本質的にあなたのように見えました。主な違いは割り当てです。これを切り替えると、数バイト節約されます。s.filter(c=>(s[c]=s[c]+1|0)<3)33バイトを試してください。編集:おっと、私の上のコメントを見逃した、それはさらに良いです:)
1

4

PowerShell v2 +、31バイト

$args-replace'(.)(?<=\1.*\1.+)'

PowerShell 演算子でカプセル化されたKobiのRetina answerと同じ正規表現を使用し-replaceます。両方がバックグラウンドで.NETフレーバー正規表現を使用しているため機能します。

または、正規表現なし、56バイト

$b=,0*200;-join([char[]]$args[0]|%{"$_"*($b[$_]++-lt2)})

sが$b事前に入力されたヘルパー配列を作成します0。入力文字列$args[0]char-array としてキャストし、ループにパイプします|%{...}。各反復は、ヘルパー配列の適切なポイントがより小さい(つまり、このcharを2回まだ見たことがない)場合にのみ(暗黙的にここにキャストされる)ブール値を掛け$_た文字列として現在の文字を出力します。結果として得られる文字列のコレクションは、括弧にカプセル化され、一緒に編集されて単一の出力文字列を形成します。それはパイプラインに残り、出力は暗黙的です。"$_"$TRUE12-join


正規表現は無敵です。:)ハッシュテーブルは、正規表現のないバリアントの配列よりも優れています:$b=@{};-join($args|% t*y|?{++$b.$_-lt3})
mazzy

1
@mazzy正規表現とコードを含まないバリアントの場合、PowerShell 2よりも新しいバージョンである必要があります。そのため、この答えは変更せずに保持します。ただし、別の回答としてコードを投稿できます!
AdmBorkBork

ハッシュテーブルはバージョン3.0に表示されましたか?OK。ありがとう。
mazzy

4

Mathematica、39バイト

Fold[If[Count@##<2,Append@##,#]&,{},#]&

匿名関数。入力として文字リストを受け取り、出力として重複排除リストを返します。リストを折り返し、3つの要素を拒否する方法を使用しますが、それほど複雑ではありません。



4

MATL、8バイト

t&=Rs3<)

オンラインでお試しください!

説明

t      % Input string implicitly. Push another copy
&=     % Matrix of all pairwise equality comparisons of string elements
R      % Keep only upper triangular part, making the rest of the entries zero
s      % Sum of each column. This gives a vector with number of occurrences
       % of the current character up to the current position
3<     % True for entries that are less than 3
)      % Use as logical index into initial copy of the input. Display implicitly

inputを仮定する'aaababbc'と、スタックには示されたステートメントの後に次が含まれます。

  • t

    'aaababbc'
    'aaababbc'
    
  • t&=

    'aaababbc'
    [ 1 1 1 0 1 0 0 0;
      1 1 1 0 1 0 0 0;
      1 1 1 0 1 0 0 0;
      0 0 0 1 0 1 1 0;
      1 1 1 0 1 0 0 0;
      0 0 0 1 0 1 1 0;
      0 0 0 1 0 1 1 0;
      0 0 0 0 0 0 0 1 ]
    
  • t&=R

    'aaababbc'
    [ 1 1 1 0 1 0 0 0;
      0 1 1 0 1 0 0 0;
      0 0 1 0 1 0 0 0;
      0 0 0 1 0 1 1 0;
      0 0 0 0 1 0 0 0;
      0 0 0 0 0 1 1 0;
      0 0 0 0 0 0 1 0;
      0 0 0 0 0 0 0 1 ]
    
  • t&=Rs

    'aaababbc'
    [ 1 2 3 1 4 2 3 1 ]
    
  • t&=Rs3<

    'aaababbc'
    [ true true false true false true false true ]
    
  • t&=Rs3<)

    'aabbc'
    

4

網膜、14バイト

D`(.)(?<=\1.*)

すべてのテストケースを確認します。%行単位モードを有効にします)

新しい「重複排除」ステージを使用して、Kobiのアプローチに比べて数バイトを節約します。重複排除は、正規表現に一致するすべてのリストを収集し、最初を除くすべてを空の文字列で置き換えます。正規表現は、文字列にすでに1回出現する文字と一致します。つまり、最初の2つが保持されます。



3

K、18バイト

  g:{x{?x@<x}@,/2#'=x}
  g "abc"
"abc"
  g "aaabcbccdbabdcd"
"aabcbcdd"

  /k4 request test vectors from internet
  R:"GET /raw/ftHe0bpE HTTP/1.0\r\nHost: pastebin.com\r\n\r\n"
  t:+0N 2#t@1_&|\(0=#:)'t:1_"\r\n"\:`:http://pastebin.com:80 R 

  /k4 no internet? use a file called "t.txt" in current directory
  t:+0N 2#0:`:t.txt

  /k6?
  t:+0N 2#0:"t.txt"

  /visually inspect test cases
  g't[0]
(();"xx";"abcabc";"abcdabc";"abacbdc";"aabcbcdd")

  /do all tests pass?
  |/ t[1] {$[0=#x;0=#y;x~y]}' g't[0]
1b

K4は無料でダウンロードできます。K6は開発中です。KDBをダウンロードした場合は、バックスラッシュを使用してKにアクセスできます

これを分解するのが一番簡単かもしれませんが、最初にいくつかの構文:をにg:x設定gxます。{x+1}引数xをとる関数です。Kでは、関数の最初の引数はx(2番目はy3番目でz、4番目は必要ありません)です。

今:

x:"aaabcbccdbabdcd"

=x以下を生成するグループxを意味します。

"abcd"!(0 1 2 10;3 5 9 11;4 6 7 13;8 12 14)

2#'それぞれが生成する2つの(from)を意味します

"abcd"!(0 1;3 5;4 6;8 12)

ご覧のとおり、これらは各文字の最初の2つの一致のオフセットです。図2は、一般化することができます。

,/参加することを意味し、しばしばレイズと呼ばれます。辞書の値だけを取得します。したがって、以下を,/"abcd"!(0 1;3 5;4 6;8 12)生成します。

0 1 3 5 4 6 8 12

これをソートする必要があります。{x@<x}@Kプログラマはしばしば見イディオム(Qは、それを呼び出しているASCと言う)、グレードアップxでxが。それをバラバラにする:

  <0 1 3 5 4 6 8 12
0 1 2 4 3 5 6 7

元の配列から取得したいソート済み配列のインデックスを返しました。x@yyでxを意味するため、並べ替えのインデックスを使用して配列にインデックスを付けます(意味がある場合)。

  {x@<x}@0 1 3 5 4 6 8 12
0 1 3 4 5 6 8 12

これを元の配列に単純にインデックス付けします。我々は可能性が言うx@ここでは、しかしKは、私たちがここを利用することができ、本当に強力な概念をサポートしています。機能のアプリケーションがインデックスです。つまりa[0]、のゼロ番目のスロットを検索しaたり、0を呼び出した関数に適用したりできますa@以前に必要だった理由は、xsがysよりも小さい{x@<x}ことをx<y意味するためです。Kの演算子は、APLからのダイアディック形式(2つの引数)とモナド形式(1つの引数)を持っています。Qにはこの「アンビバレンス」はありません。


PPCGへようこそ!素晴らしい最初の答え。:)
マーティンエンダー

いくつか質問があります。1. K4はリンク先の言語(Q / kdb +)と同じ言語ですか?2.入力で関数を呼び出す方法、またはtestVectors.txtの項目をどのようにフォーマットする必要があるかを示していただけますか?
デニス

@デニス1.はい。:彼らは質問に表示されるQからK. 2.だけを取得するためにプレスバックスラッシュpastebin.com/ftHe0bpE:例コールg"aaabcbccdbabdcd"
geocar

はい、ありがとう。ファイル部分を機能させることはできませんでしたg"..."が、トリックは行います。残念ながら、aabbcc入力に対してコードが返されますabc
デニス

@Dennisあなたは何か間違ったことをしたかもしれません:{x{?x@<x}@,/2#'=x}"abc"間違いなく戻ります"abc""aabbcc"あなたが?明確に見逃した場合、それは戻ります。
ジオカー


2

Java 8ラムダ、90文字

i->{int[]o=new int[128];String r="";for(char c:i.toCharArray())if(++o[c]<3)r+=c;return r;}

ゴルフされていないバージョン:

public class Q86503 {

    static String detriplicate(String input) {
        int[] occurences = new int[128];
        String result = "";
        for (char c : input.toCharArray()) {
            if (++occurences[c] < 3) {
                result += c;
            }
        }
        return result;
    }
}

すべてのASCII文字の配列を作成します。文字が発生すると、対応するカウンターが増加します。2を超える場合、文字は結果の文字列に追加されません。非常に簡単、非常に短い;)


2

Perl 6、27バイト

{.comb.grep({++%.{$_} <3})}

説明:

{.comb.grep({++%.{$_} <3})}
{                         } # a function
 .comb                      # get all the characters in the argument
      .grep({           })  # filter
               %.           # an anonymous hash (shared between calls to grep)
             ++  {$_}       # increment the value at the current key (current letter).
                            # if the key doesn't exist, it defaults to 0 (then gets incremented)
                      <3    # return True if it wasn't seen 3 times

(注:Perl 6は、姉妹のPerl 5ほど「ゴルフ指向」ではありません...ですから、はい、その前のスペース<が必要です。これ%.{}は匿名ハッシュです)。



2

SmileBASIC、77 72 69 68バイト

DIM R[#Y]READ S$WHILE""<S$Q=ASC(S$)INC R[Q]?SHIFT(S$)*(R[Q]<3);
WEND

説明:

DIM R[128] 'array to store letter frequencies
READ S$ 'get input string
WHILE""<S$ 'much shorter than LEN(S$)
 Q=ASC(S$) 'get ascii value of first character in S$
 INC R[Q]
 ?SHIFT(S$)*(R[Q]<3); 'remove the first character of S$, and print it if there are less than 3 occurrences.
WEND

ppcgへようこそ!素敵な最初の投稿!
Rɪᴋᴇʀ

1

Common Lisp、127

(lambda(s)(map()(lambda(x)(flet((p(b)(1+(position x s :start b))))(setf s(remove x s :start(p(p 0))))))(remove-duplicates s))s)

プリティプリント

(lambda (s)
  (map nil
       (lambda (x)
         (flet ((p (b)
                  (1+ (position x s :start b))))
           (setf s (remove x s :start (p (p 0))))))
       (remove-duplicates s))
  s)

1

Q、52バイト

q)f2:{x asc raze{distinct 2#where x}each x~'/:distinct x}
q)f2 each testList
"xx"
"abcabc"
"abcdabc"
"abacbdc"
"aabcbcdd"
q)

1

K、27バイト

    f:{x{x@<x}@,/{?2#&x}'x~'/:?x}
    testList:("xxxxx";"abcabc";"abcdabcaba";"abacbadcba";"aaabcbccdbabdcd")
    f'testList
("xx";"abcabc";"abcdabc";"abacbdc";"aabcbcdd")

1

ルビー79 62 57バイト

これはかなり扱いにくいですが、現時点でこれほどゴルフができるかどうかはわかりません。ゴルフの提案は大歓迎です。オンラインでお試しください!

編集: Value Inkのおかげで、三重の文字を削除するゴルファーの方法を提案して-17バイト。.uniqメソッドの削除から-5バイト。

->s{s.chars.map{|a|s[s.rindex a]=""while s.count(a)>2};s}

ゴルフをしていない:

def g(s)
 s.chars.each do |a|
  while s.count(a) > 2
   i = s.rindex(a)
   s[i] = ""
  end
 end
 return s
end

62バイト:->s{s.chars.uniq.map{|a|s[s.rindex a]=""while s.count(a)>2};s}
値インク

1

JavaScript、30バイト

v=>v.filter(x=>!(v[x]+=x)[11])

@ edc65がカウント用に考え出したが、配列フィルターを使用した方法を使用します。最初に文字が表示されると、オブジェクトの値は「未定義」に文字を加えたものになります(「undefinedx」など)。次にオブジェクト値が「undefinedxx」になったとき。

その後、v [x] [11]はtrueを返し、not演算子と組み合わせるとfalseを返します。これは、すでに2回出現した文字がフィルターされることを意味します。


0

Javascript(外部ライブラリを使用)(80バイト)

これは良いものでした!勝てなかったけど楽しかった

n=>{a={};return _.From(n).Where(x=>{b=a[x]?a[x]++:a[x]=1;return b<2}).Write("")}

libへのリンク:https : //github.com/mvegh1/Enumerable/

コードの説明:メソッドは文字列を受け取り、ライブラリはそれをchar配列として解析します。Where句は、「a」ハッシュマップで現在のcharの存在をチェックする複雑なフィルタリング述語です。存在する場合、カウンタをインクリメントし、そうでない場合は1に設定します。2未満の場合、述語(および現在の文字)は成功し、そうでない場合は失敗します

ここに画像の説明を入力してください


aの使用を避けることができreturnますが、関数を括弧内の式のコンマ区切りリストにすることはできますn=>(a={},_From(n)....)。最後の式は戻り値です。あなたではWhere機能、あなたは中間を排除することができb、完全に譲渡または増分の結果と比較することにより、: x=>(a[x]?a[x]++:a[x]=1)<2
-apsillers

最後に、文字列分割の省略記号を使用filterし、join:を使用すると、外部ライブラリの使用をまったく回避できます(バイトを節約できます)[...n].filter(...).join("")。に変更Whereするときにtrue / falseロジックを反転しますfilter
apsillers

ああ、いい観測だ!後であなたの提案を詳しく見てみましょう
applejacks01

0

Clojure、72バイト

#(apply str(reduce(fn[r c](if(<(count(filter #{c}r))2)(conj r c)r))[]%))

非常に多くのバイト...


0

パスカル(FPC)、103バイト

var a:array['a'..'z']of word;c:char;begin repeat read(c);inc(a[c]);if a[c]<3then write(c)until eof end.

オンラインでお試しください!

説明:

var a:array['a'..'z']of word; //used for counting occurences of characters in the input
                              //array indices are accessed by chars
    c:char;
begin
  repeat
    read(c);                  //read a character from input
    inc(a[c]);                //increment the count of that character (its number in array)
    if a[c]<3 then write(c)   //if this is character's 1st or 2nd occurence, output it
  until eof                   //go back to reading if input is not read completely
end.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.