ユニークは安い


93

特定の文字列のコストを決定する関数またはプログラムを記述します。ここで、

  • 各文字のコストは、文字列のこの時点までに文字が発生した回数と等しくなります。
  • 文字列のコストは、文字のコストの合計です。

の入力のabaacab場合、コストは次のように計算されます。

a b a a c a b
1   2 3   4    occurrence of a
  1         2  occurrence of b
        1      occurrence of c
1+1+2+3+1+4+2 = 14

したがって、文字列のコストabaacabは14です。

ルール

  • 提出のスコアは、上記定義されたコードのコストです。つまり、提出が独自のソースコードで実行され、スコアが低いほど優れています。
  • 送信は、印刷可能なASCII文字に加えて、送信で使用されるすべての文字を含む文字列で機能する必要があります。
  • 文字は大文字と小文字が区別されます。つまりaA異なる文字です。

テストケース

input -> output
"abaacab" -> 14
"Programming Puzzles & Code Golf" -> 47
"" -> 0
"       " -> 28
"abcdefg" -> 7
"aA" -> 2

リーダーボード


2
-nPerl などのプログラムフラグはスコアにどのようにカウントされますか?それは伝統的に1バイトとしてカウントされるため、標準の間の編集距離perl -eperl -ne1であるが、この挑戦のため、意志n重複をカウントする目的のカウント?
バリューインク

2
はい@ValueInk、私はカウントだと思うn最も公平オプションです。
ライコニ

1
私はこの挑戦に頭脳の解決があったことを本当に望む。
Peter1807

10
以下のための+1 ご提出のスコアは、あなたのコードのコストである
luizfzs

1
キャラクターのコストは次のようhow often this character has already occurred in the stringに定義されhow many times the character has occurred up to this pointます。最初の使用のコストが0ではなく1であることが明確になるように変更するでしょう
地下

回答:


83

MATL、スコア4

&=Rz

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

説明

'ABBA'例として入力を検討してください。

&=   % Implicit input. Matrix of all equality comparisons
     % STACK: [1 0 0 1;
               0 1 1 0;
               0 1 1 0;
               1 0 0 1]
R    % Upper triangular part
     % STACK: [1 0 0 1;
               0 1 1 0;
               0 0 1 0;
               0 0 0 1]
z    % Number of nonzeros. Implicitly display
     % STACK: 6

14
あなたは線形代数の教授ですか?
魔法のタコUr

4
@carusocomputing実際にはモバイル通信の教授。行列を使用するための私の傾向は、MATLABでのプログラミングの年から来ている
ルイス・Mendo

きちんとした!Matlabはその領域で大きいですか?私は実際にGSMまたはそれに類するものを調べたことがありません。
魔法のタコUr

2
この素晴らしいソリューションであなたを賞賛するために、私はこのコミュニティに参加しました!
-Wboy

1
@carusocomputing Matlabは、エンジニアリング全般で非常に一般的なツール/言語です。線形計算、信号処理などの数値計算が得意です。そして、それは非常に使いやすいですインタプリタ言語であること
ルイスMendo

17

Python、スコア49

lambda S:sum(1+S.count(C)for[C]in	S)/2

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

の後にタブがありますin

スコアの内訳:

  • 27個のユニークな文字に対して+27
  • 8つのダブル文字で+16: ()Camnou
  • 3つの文字の1つに対して+6: S

13
バイトを保存するには、スペースの代わりにタブを使用します。
mbomb007

1
@ mbomb007同じ考えを持っていた:
xnor

1
@ mbomb007ああ、それは天才的なトリックです:
ETHproductions

14
@ mbomb007それはただのタブ対ゴルフのコード内のスペース戦争
エリックアウトゴルファー

2
フォームフィード(Python構文で空白も許可されています)を使用することをお勧めしますが、置き換える空白はこれ以上ありません。
user2357112

8

T-SQL、スコア775 579!580

declaRe @ char(876),@x int,@v int=0Select @=q+CHAR(9)from z X:seleCT @x=len(@),@=REPLACE(@,LEFT(@,1),''),@v+=(@x-LEN(@))*(@x-LEN(@)+1)/2IF LEN(@)>0GOTO X prINT @v-1

編集:いくつかの変数を削除し、少し圧縮しました。@22個ではなく16 個のシンボルで、それだけで117ポイントものスコアが減少します。

ナイスコンテスト、総文字数以外の何かのために最適化する要件が好きです。

入力は、IOルールに従って、既存のテーブルzの varcharフィールドqを介して行われます。この入力テーブルを含むデータベースは、大文字と小文字を区別する照合に設定する必要があります

フォーマット済み:

declaRe @ char(876), @x int, @v int=0
Select @=q+CHAR(9)from z
X:
    seleCT @x=len(@)
          ,@=REPLACE(@,LEFT(@,1),'')
          ,@v+=(@x-LEN(@))*(@x-LEN(@)+1)/2
IF LEN(@)>0 GOTO X
prINT @v-1

SQLキーワードでは大文字と小文字が区別されないため、大文字と小文字を混在させて重複文字の数を最小限に抑えました(aaAAaaaaよりも良い/低いスコアを生成します)。

メインループは、最初の文字のすべてのインスタンスを除去する前後の長さを比較します。その差n *(n + 1)/ 2が積算合計に加算されます。

SQL LEN()関数は、うっとうしく末尾のスペースを無視するため、制御文字を追加し、最後に1を引く必要がありました。

編集:1ポイントの大文字と小文字を変更することで1減った2ポイント(引用符を引用することに関する問題)による自分のスコアの計算ミスを修正しましたR。また、まったく異なる戦略に取り組んでおり、それを独自の回答として投稿します。


3
最初は、あなたのスコアは579! ≈ 8.22 x 10^1349
エンジニアトースト

8

C(GCC) 、スコア: 113  103 100   96  91

@ ugoren、@ CalculatorFeline、@ gastropner、@ l4m2、および@ JS1のヒントに感謝します。

g(char*s){int y[238]={};while(*s)*y-=--y[*s++];*y/=1;}

ゼロの配列を初期化し、文字列内の文字のASCII値をその配列へのインデックスとして使用して、文字列内の各文字のインスタンス数を追跡します。

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


3
提案:のように、キーワードに使用されていない変数名を使用してzxc
CalculatorFeline

@CalculatorFelineがchar含まれていcます...
ニール

3
また、127要素の配列(\x7f印刷不可)のみが必要なので、説明を追加してください。
電卓

1
:後期パーティーに、これは96でなければなりませんz;g(char*s){int y[238]={z=0};while(*s)z+=--y[*s++];z/=~0;}
gastropner

1
g(char*s){int y[238]={};while(*s)*y+=--y[*s++];*y/=~0;}
l4m2

7

JavaScript(ES6)、スコア81 78

@Arnauldのおかげで3ポイント節約

s=>s.replace(d=/./g,z=>q+=d[z]=-~d[z],q=0)&&q

私のオリジナルのスコア81再帰ソリューション:

f=([c,...s],d={})=>c?(d[c]=-~d[c])+f(s,d):0



7

網膜、スコア34

s(O`.
M&!`^|(?<=(.))\1*
.

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

説明

s(O`.

入力内のすべての文字をソートして、同一の文字を1つの実行にグループ化することから始めます。はs(、すべてのステージで単一行モードをアクティブにします(つまり、.改行を一致させます)。

M&!s`^|(?<=(.))\1*

目標は、n文字の実行をT n文字(n番目の三角形の数)に変えることです。これは、この文字の出現のスコアだからです。そのためには、重複する一致を見つけます。具体的には、各I[1、n]は、我々は、するつもりI-1マッチ中に文字が。フラグが重複しているため、これらすべての一致が取得されます&。これにより、一致からn *(n-1)/ 2 = T n-1 = T n -n文字が得られます。しかし、試合のステージがされている改行、とこれらに参加するn個のために改行をn個一致します。問題は1つだけです。最後の一致の後に改行はありませんので、出力の全体的な文字数は必要な数より1つ少なくなります。入力の先頭も一致させることでこれを修正します。これにより、少なくとも1つの一致がある場合に単一の先行改行が得られます。

.

最後に、文字列に含まれる文字数をカウントします。


6

ハスケル、スコア52 51

f(a:b)=1+sum[1|c<-b,c==a]+f b;f _=0

fとの間にタブがあり_ます。

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

空の文字列の値は0です。文字列sの値aは、最初の文字でありb、文字列の残りの部分は1にain の出現bとbの再帰呼び出しを加えたものです。


5

J、スコア16

1#.,@(*+/\"1)&=

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

説明

1#.,@(*+/\"1)&=
              =  Self-classify: bit matrix of equality between input
                 and its unique elements.
     (      )&   Apply verb in parentheses to it:
       +/\         running sums
          "1       of each row
      *            multiplied with original matrix.
                 This causes the i'th 1 on each row to be replaced by i.
   ,@            Flatten the resulting matrix
1#.              and interpret as a base-1 number, computing its sum.

合計の1#.代わりに使用すると+/@、いくつかのポイントが節約され、モナドのコンテキストの&代わりに使用@して、もう1つ節約できます。繰り返される1と1ポイント余分に費用がかかりますが、私はそれを取り除くことができませんでした。


「後で」四半期を待つ
CalculatorFeline

2
10時間後の@CalculatorFelineはまだ後です。:P
ズガルブ

今それをセスキセミデーにしましょう。
電卓

私は個人的に使用し、このフォーマットを多分あなたはそれを使用したい、コードセクションでの正確なバイト数を反映させるためにTIOの答えを
コナー・オブライエン

5

R、スコア:67 83 95 128

-61 Giuseppeからのヒントのおかげ

function(x,y=table(utf8ToInt(x)))y%*%{y+1}/2

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

文字列はを使用utf8ToIntして分割され、各ASCII値がカウントされtableます。結果は%*%、それ自体+ 1で行列乗算を実行して計算され、最終的に半分になります。


table代わりに使用しrleます。を削除することもできますsort(そして[[1]]の結果にインデックスを付ける必要はありませんstrsplit
ジュゼッペ

@ジュゼッペありがとうございます。私はテーブルについても考えていませんでした、すぐに取り入れます。
MickyT

2
私はあなたの代わりに別の変数名を使用することにより、さらにいくつかのバイトを保存することができると思うn(それは中なのでfunction2回)し、また変更(n+1){n+1}
ジュゼッペ・

スコア:67。これに関するいくつかのバリエーションにより、スコアをさらに減らすことが可能になる場合があります。
ジュゼッペ

@ジュゼッペ...私はそれをもう一度読んでいたはずです。おっと
MickyT


4

Pyth、スコア6

isaacgのおかげで1バイト。

+F/V._

テストスイート。

使い方

+F/V._
+F/V._QQ  implicit input
  /V      vectorize count: for each element in the first argument,
                           count the number of occurrences of the
                           second argument:
    ._Q       all prefixes of input
       Q      input
+F        fold (reduce) on +, base case 0.

s+0はと同じ+Fです。
isaacg

良い!できることはusaShHGrScQ1 8Z16です。説明を追加できますか?
デジタル外傷

1
@DigitalTrauma説明を追加しました。
リーキー修道女

s/LQスコア4です。これは、チャレンジより後の機能を使用していますか?
デイブ



4

C、60バイト、スコア108 95

g(char*s){int y[256]={},z=0;while(*s)z-=--y[*s++];return z;}

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

通常、インクリメント前後の演算子はコードゴルフに適していますが、この課題で本当に痛いです!

編集:正のカウントを追加するのではなく、負のカウントを減算することにより、スコア全体を保存しました。交換for()while()同様にセミコロンを排除しました。



3

C#(.NET Core)、スコア∞(つまり、209)

b=>b.Distinct().Select(z=>{var w=b.Count(p=>p==z);return w*(w+1)/2;}).Sum()

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

スコアには以下が含まれます。

using System.Linq;

しばらく経っreturn w*(w+1)/2ていますが、return-~w*w/2(スコア196)に変更できます。編集:あなたは149のスコアのために私のJava 8の答えのポートを作成することができます:オンラインで試してみてください using System.Linq;b=>{int[]x=new int[256];return\nb.Select(z=>++x[z]).Sum();}
ケビンCruijssen

1
@KevinCruijssen:あなたの解決策を111点まで下げました:b=>{var x=new int[256];return\nb.Sum(z=>++x[z]);}
raznagul

@raznagul(*半年前の応答着信*109 2番目のスペースをタブに変更した場合。;)オンラインで試してください。
ケビンクルーイッセン


3

ああ、私はこの質問に十分早く気づかなかった。
リーキー修道女

@LeakyNun psのあなたはいつも忍者じゃない、でも誰もがある
エリックOutgolfer

本当に?そうは思いません。
電卓

スコア5:ĠJ€ẎS
Leaky Nun

@LeakyNun約束どおり...ええ、クレジットはあります:)
エリック・ザ・アウトゴルファー

3

PowerShell、スコア64

$z=@{}
$ARGS|% getE*|%{$u+=($Z.$_+=1)};$U

(スコアは単一の改行改行に基づいています。これはWindows標準ではありませんが、PSで動作します)。

PS C:\> D:\unique-is-cheap.ps1 (gc D:\unique-is-cheap.ps1 -raw)
64
  • ハッシュテーブルカウンター @{}
  • 文字を反復処理します。$argsパラメータの配列です-この場合、入力文字列は単一の項目配列になります。|%アイテムに対してforeachループを実行し、getE*ショートカットを使用してGetEnumerator()文字列メソッドに一致し、それを呼び出して文字列を文字ストリームに変換します。
  • |%文字をループし、ハッシュテーブルエントリをインクリメントし、それを積算合計に追加します。($x+=1)括弧付きのフォームは、変数を変更し、使用する新しい値を出力します。
  • 積算合計を出力します。

(最初に書いたとき$c=@{};$t=0;[char[]]"$args"|%{$c[$_]++;$t+=$c[$_]};$t、スコアは128でしたが、それほど下がらないように感じました。64に半減するのはとても楽しいです)。


1
増分を
いじることで


3

ジュリア0.6、45バイト、スコア:77

MATLソリューションに触発された:

f(w)=sum(UpperTriangular([z==j for z=w,j=w]))

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

カウントを使用したあまりきれいではないソリューション:

ジュリア0.6、スコア:82

F(w)=sum(l->[l+1]l/2,count(x->x==i,w)for i=Set(w))

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

得点とヒントを指摘してくれたGuiseppeに感謝します。これらのコメントは私をロードするのに役立ちました。


1
あなたの提出のスコアはあなたのコードのコストであり、それは135だと思います
ジュゼッペ

1
ジュリアはよくわかりませんが、変数名を切り替えて括弧のセットを削除すると、スコアを110に減らすことができると思います。単一要素のベクトルを返すことが許可されている場合は、に置き換え(x+1)[x+1]スコアをさらに減らすことができます。
ジュゼッペ

2番目のスペースをタブまたは改行:スコア104に変更することにより、スコアを保存できます。そして、@ Giuseppeを使用する[x+1]代わりに使用(x+1)すると、スコアが98に低下します。
ケビンクルーッセン

3

ジャワ10、スコア:149 138 137 134 133 130 103 102 101 100

バイト:72 73 74 75 64 62 61バイトは増えますが、スコアは下がります。:D

x->{int j=0,q[]=new int[256];for(var    C:x)j+=++q[C];return
j;}

@Nevayのおかげで-28スコア(および-11バイト)。@OlivierGrégoireの
おかげで、-1スコア(および-2バイト)。 Java 8をJava 10に変換して、-1スコア(および-1バイト)。

説明:

ここで試してみてください。

x->{                     // Method with character-array parameter and integer return-type
  int j=0,               //  Result-integer, starting at 0
      q[]=new int[256];  //  Integer-array with 256 times 0
  for(var   C:x)         //  Loop over the characters of the input array
    j+=++q[C];           //   Raise the value in the array by 1,
                         //   and then add it to the result-integer
  return                 //  Return 
  j;}                    //         the result

1
and (133)~を使用する場合は削除できます。j=0return-j;
ネベイ

1
103:x->{int[]q=new int[256];return\nx.chars().map(v->++q[v]).sum();}
ネベイ

1
@Nevay 103、実際jには、ureturncontains u)の代わりに使用し、スペースの代わりに改行とタブを使用します。編集:へへ、あなたは私がこのコメントをした時に編集した。:)
ケビンクルーイッセン

3

F#、スコア120 118

let j z=Seq.countBy id z|>Seq.sumBy(fun x->List.sum[0..snd x])

-2 Kevin Cruijssenに感謝します

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

string入力としてaを取ります。Seq.countBy各個別の文字とそのカウント(idアイデンティティ関数)をペアにするので、'a' = 4, 'b' = 2などのコレクションになります。

Seq.sumByすべての文字のカウントを取り、からのすべての数字を合計し0、その文字のカウントに。したがって'a' = 4、コレクションが0, 1, 2, 3, 4合計される場合はになります10。次にSeq.sumBy、これらの合計を合計します。


2
あなたは、変更することによって、2によってあなたのスコアを下げることが可能let qlet jするので、qすでに両方で使用されていますSeq
ケビンクルーッセン


2

網膜、スコア68 45 43

s`(.)(?<=((\1)|.)+)
$#3$*
1

オンラインでお試しください!リンクにはスコアが表示されます。編集:先読みの代わりに重複する一致を使用して20バイトを保存し、sフラグを1回だけ適用する必要があるようにステージをグループ化してさらに3バイトを保存した@MartinEnderに感謝します。三角形の数を異なる方法で計算することにより、さらに2バイトを節約し、ソートの必要性を回避しました。



2

Perl 5スコア91 83

-pスプリットのpのために2を追加するフラグを使用します。

$x=$_;$b+=++$a{$_}for(split//,$x);$_=$b

PPCGへようこそ!
ライコニ

1
あなたの答えをベースにして、ヒントページからいくつかのテクニックを適用して、スコアを31まで下げることができましたオンラインで試してみてください!$` is automatically 印刷ed after each call so we can use that to store the score and 中のすべての文字のリストを返しますG` /./ $_よりも安いです、split//
ドムヘイスティングス

私はこれが古い挑戦であることを知っています、しかし、あなたはさらにスコアを切ることができます:オンラインでそれを試してください!
Xcali

2

オクターブ、39バイト、スコア69

@(a)sum((b=hist(a,unique(1*a))).^2+b)/2

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

オクターブには別の答えがありますが、これは完全に私自身のものであり、異なるアプローチです。さらに、得点が少なくなります:)。

アプローチは、ヒストグラム関数を使用して達成される各一意の文字のカウント(b)を最初に見つけることに要約されます。次に、各要素について、式を使用して1からbの合計を計算し(b*(b+1))/2ます。次に、個々の合計がすべて最終スコアに合計されます。

テストでは、多くのブラケットが必要であるため、スコアリングにおいてブラケットは本当にコストがかかるようです。開始/終了ブラケットの数を最小化するために質問を再配置することにより、約88の初期スコアから最適化されました-したがって、個別ではなく最終合計で/ 2を実行し、式を次のように変更しました(b^2+b)/2必要なブラケットが少ないため。


1
残念ながら、これは空の文字列で失敗するようですerror: hist: subscript indices must be either positive integers less than 2^31 or logicals
。– Laikoni

2

Common Lisp、スコア286 232 222

(loop with w =(fill(make-list 128)0)as z across(read)sum(incf(elt w(char-code z))))

Common Lispの組み込み演算子の冗長な構文による高価値のスコア。

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

改変されていないコード:

(loop with w = (fill (make-list 128) 0)  ; create a list to count characters
   as z across (read)                   ; for each character of input
   sum (incf (elt w (char-code z))))     ; increase count in list and sum

2

Mathematica、スコア54

Total[#(#+1)/2&@Counts@Characters@#]&

入力

["abcdefg"]

hftfに感謝


Total[#(#+1)/2&@Counts@Characters@#]&スコア54
hftf
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.