Unique is Cheap

94

13

Write a function or program that determines the cost of a given string, where

  • the cost of each character equals the number of how many times the character has occurred up to this point in the string, and
  • the cost of the string is the sum of its characters' costs.

Example

For an input of abaacab, the cost is computed as follows:

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

Thus the cost for the string abaacab is 14.

Rules

  • The score of your submission is the cost of your code as defined above, that is your submission run on its own source code, with a lower score being better.
  • Your submission should work on strings containing printable ASCII-characters, plus all characters used in your submission.
  • Characters are case-sensitive, that is a and A are different characters.

Testcases

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

Leaderboard

var QUESTION_ID=127261,OVERRIDE_USER=56433;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px} /* font fix */ body {font-family: Arial,"Helvetica Neue",Helvetica,sans-serif;} /* #language-list x-pos fix */ #answer-list {margin-right: 200px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Score</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

Laikoni

Posted 2017-06-19T16:51:53.083

Reputation: 23 676

2How do program flags such as -n for Perl count towards the score? It traditionally counts as 1 byte because the edit distance between the standard perl -e and perl -ne is 1, but for this challenge, will the n count for the purposes of counting duplicates? – Value Ink – 2017-06-19T20:20:33.707

2@ValueInk Yes, I think counting the n is the fairest option. – Laikoni – 2017-06-19T20:34:39.553

1I really wish there was a brainfuck solution to this challenge. – Peter1807 – 2017-06-21T12:16:26.207

10+1 for The score of your submission is the cost of your code – luizfzs – 2017-06-22T15:21:16.680

Is the input as char-array allowed instead of String? – Kevin Cruijssen – 2017-09-14T13:19:42.477

@KevinCruijssen Sure. – Laikoni – 2017-09-14T20:05:34.323

@Peter1807, wish granted! – Jo King – 2018-01-19T05:04:38.023

1cost of a character is defined as how often this character has already occurred in the string, i'd probably changing to how many times the character has occurred up to this point to make it clearer that the first use costs 1, not 0 – undergroundmonorail – 2018-01-19T19:33:19.470

@undergroundmonorail Thanks, I added your suggested wording. – Laikoni – 2018-01-23T19:38:12.733

Is the leaderboard supposed to be unsorted? – Ørjan Johansen – 2018-03-17T15:27:18.960

@ØrjanJohansen Do you mean the language names in the winners-by- language section? I wouldn't mind if they were sorted, though I don't really know how the snippet works as I just copied it from an other challenge. Feel free to fix it if you know how. – Laikoni – 2018-03-17T15:44:20.673

Alas, I have no idea, except that e.g. the golf you a quine leaderboard is sorted.

– Ørjan Johansen – 2018-03-17T16:38:51.423

Answers

84

MATL, score 4

&=Rz

Try it online!

Explanation

Consider input 'ABBA' as an example.

&=   % 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

Luis Mendo

Posted 2017-06-19T16:51:53.083

Reputation: 87 464

15Are you a linear algebra professor? – Magic Octopus Urn – 2017-06-20T18:53:55.843

4@carusocomputing Actually a mobile communications professor. My tendency to use matrices comes from years of programming in Matlab – Luis Mendo – 2017-06-20T18:57:14.937

Neat! Is Matlab big in that area? I've never really looked into GSM or anything like it. – Magic Octopus Urn – 2017-06-20T19:27:06.777

3I joined this community just to commend you on this brilliant solution! – Wboy – 2017-06-21T05:21:17.853

@Wboy Thanks, I feel honored :-) And welcome to PPCG! – Luis Mendo – 2017-06-21T08:27:33.077

1@carusocomputing Matlab is a very common tool/language in engineering in general. It's good at numerical computation: linear algebra, signal processing, and the like. And being an interpreted language it's very easy to use – Luis Mendo – 2017-06-21T08:29:54.380

17

Python, score 49

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

Try it online!

There's a tab after in.

Score breakdown:

  • +27 for 27 unique chars
  • +16 for 8 double chars: ()Camnou
  • +6 for 1 tripled char: S

xnor

Posted 2017-06-19T16:51:53.083

Reputation: 115 687

13Use a tab instead of a space to save a byte. – mbomb007 – 2017-06-19T17:20:47.757

1@mbomb007 Just had the same idea :-) – xnor – 2017-06-19T17:21:14.250

1@mbomb007 Hah, that's a genius trick :-) – ETHproductions – 2017-06-19T17:21:30.697

14@mbomb007 that's just tabs vs. spaces war inside golfed code – Erik the Outgolfer – 2017-06-19T17:23:32.527

1Wouldn't it be +5 for S three times? i.e. +2 for the second, and +3 for the third. – Brian J – 2017-06-19T18:50:36.680

@BrianJ I mean +3 over the raw character count, which counts 3 bytes for the 3 copies while the score counts 6. – xnor – 2017-06-19T19:04:18.757

@xnor Ah, of course. I understand the math now. – Brian J – 2017-06-19T20:54:29.743

2I was going to suggest using a form feed (which is also permitted whitespace in Python syntax), but you don't have any more whitespace to replace. – user2357112 supports Monica – 2017-06-19T23:39:48.537

Clearly form feeds are the best characters to use for indenting code. – 12Me21 – 2018-03-07T01:54:10.073

8

C (gcc), score:  113  103 100   96  91

Thanks to @ugoren, @CalculatorFeline, @gastropner, @l4m2, and @JS1 for their tips.

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

Initializes an array of zeros, then uses the ASCII values of the characters in the string as indices to that array to keep track of the number of instances of each character in the string.

Try it online!

Steadybox

Posted 2017-06-19T16:51:53.083

Reputation: 15 798

3Suggestion: Use variable names that aren't used in keywords, like z,x,c. – CalculatorFeline – 2017-06-19T17:02:21.733

@CalculatorFeline char includes c... – Neil – 2017-06-19T17:27:42.797

Oh right...well, you get the point. – CalculatorFeline – 2017-06-19T17:40:18.523

3Also, you only need a 127 element array (\x7f is not printable) and please add an explanation. – CalculatorFeline – 2017-06-19T17:42:34.673

You need return z. Replacing it with z=z might work on some platforms and without optimization. – ugoren – 2017-06-19T21:24:11.053

z-=- saves 2 points. – ugoren – 2017-06-19T21:29:19.070

Better - z+=--y and return -z. – ugoren – 2017-06-19T21:35:46.203

@ugoren It says C (gcc) for a reason. If it fails on your system, please post specs. – CalculatorFeline – 2017-06-19T21:48:08.717

Also, can confirm that this does not work on OSX fake gcc. – CalculatorFeline – 2017-06-19T21:57:40.640

Also, it seems that on my machine, you can drop the z= part. Confirmed on TIO as well. – CalculatorFeline – 2017-06-19T22:01:47.433

@CalculatorFeline Which z= do you mean? Dropping the latter instance of it doesn't work on TIO (at least for me), and dropping the former instance works but then the function can only be called once. – Steadybox – 2017-06-19T22:50:38.897

Forgot about the "must be callable multiple times" rule. Ignore. – CalculatorFeline – 2017-06-19T22:51:41.627

1Late to the party, but this should be 96: z;g(char*s){int y[238]={z=0};while(*s)z+=--y[*s++];z/=~0;} – gastropner – 2018-03-15T10:07:35.990

@gastropner Thanks! – Steadybox – 2018-03-15T10:53:11.277

1g(char*s){int y[238]={};while(*s)*y+=--y[*s++];*y/=~0;} – l4m2 – 2019-01-06T11:07:41.413

g(char*s){int y[238]={};while(*s)*y-=--y[*s++];*y/=1;} – JS1 – 2019-04-28T10:16:09.403

8

T-SQL, score 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

EDIT: Dropped a couple of variables, compacted a bit. Down to 16 @ symbols instead of 22, that by itself reduces my score by a whopping 117 points!

Nice contest, I like the requirement to optimize for something besides total character count.

Input is via varchar field q in pre-existing table z, per our IO rules. The database containing this input table must be set to a case-sensitive collation.

Formatted:

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 keywords aren't case sensitive, so I used mixed case to minimize the count of duplicate letters (aaAA generates a better/lower score than aaaa).

The main loop compares the length before and after stripping all instances of the first character out. That difference n*(n+1)/2 is added to a running total.

The SQL LEN() function annoyingly ignores trailing spaces, so I had to append a control character and subtract 1 at the end.

EDIT: Fixed a miscalculation of my own score by 2 points (issue with quoting quotes), reduced by 1 by changing casing of one R. Also working on a completely different strategy, I'll be posting that as its own answer.

BradC

Posted 2017-06-19T16:51:53.083

Reputation: 6 099

3At first I thought your score was 579! ≈ 8.22 x 10^1349 – Engineer Toast – 2017-07-17T12:54:20.463

7

Jelly, score 6

;\ċ"⁸S

Try it online!

Leaky Nun

Posted 2017-06-19T16:51:53.083

Reputation: 45 011

7

JavaScript (ES6), score 81 78

Saved 3 points thanks to @Arnauld

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

My original score-81 recursive solution:

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

ETHproductions

Posted 2017-06-19T16:51:53.083

Reputation: 47 880

7

Haskell, score 42

f l=sum[1|c<-l,d<-c:l,d==c]/2

Try it online!

Anonymizing \l-> gives the same score.

xnor

Posted 2017-06-19T16:51:53.083

Reputation: 115 687

7

Retina, score 34

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

Try it online!

Explanation

s(O`.

We start by sorting all the characters in the input so that identical characters are grouped together into a single run. The s( activates singleline mode for all stages (i.e. makes . match linefeeds).

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

The goal is to turn a run of n characters into Tn characters (the nth triangular number) because that's the score of the occurrences of this character. To do so, we find overlapping matches. In particular, for each i in [1,n], we're going to include i-1 characters in the match. We get all those matches due to the overlapping flag &. That gives us n*(n-1)/2 = Tn-1 = Tn - n characters just from the matches. But the match stage will join these with linefeeds, which are n linefeeds for n matches. There's only one problem. There won't be a linefeed after the last match, so the overall number of characters in the output is one less than we need. We fix this by also matching the beginning of the input, which gives us a single leading linefeed if there is at least one other match.

.

Finally, we just count how many characters there are in the string.

Martin Ender

Posted 2017-06-19T16:51:53.083

Reputation: 184 808

6

Haskell, score 52 51

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

There's a tab between f and _.

Try it online!

The value of the empty string is 0. The value of the string s, where a is the first char and b the rest of the string is 1 plus the occurrences of a in b plus a recursive call with b.

nimi

Posted 2017-06-19T16:51:53.083

Reputation: 34 639

5

J, score 16

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

Try it online!

Explanation

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.

Using 1#. instead of +/@ for the sum saved a few points, and & could be used instead of @ in a monadic context to save one more. The repeated 1 costs me one extra point, but I haven't been able to get rid of it.

Zgarb

Posted 2017-06-19T16:51:53.083

Reputation: 39 083

"later" waits a quarterday – CalculatorFeline – 2017-06-20T01:56:00.870

2@CalculatorFeline 10 hours later is still later. :P – Zgarb – 2017-06-20T06:35:51.950

Let's make it a sesquisemiday now. – CalculatorFeline – 2017-06-20T15:24:22.363

I personally use this format for TIO answers in order to reflect an accurate byte count in the code section, maybe you would want to use it

– Conor O'Brien – 2017-06-21T22:29:42.557

5

R, score: 67 83 95 128

-61 thanks to top tips from Giuseppe

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

Try it online!

The string is split using utf8ToInt and each ascii value is counted table. The the result is calculated using doing a matrix multiplication %*% over that at itself + 1 and finally halfed.

MickyT

Posted 2017-06-19T16:51:53.083

Reputation: 11 735

use table instead of rle; you can get rid of the sort as well (and you don't have to index [[1]] into the result of strsplit) – Giuseppe – 2017-06-19T20:36:41.537

@Giuseppe Thanks a lot. I didn't even think of table, will incorporate soon. – MickyT – 2017-06-19T20:44:46.140

2I think you can save a few more bytes by using a different variable name instead of n (since it's in function twice) and also changing (n+1) to {n+1} – Giuseppe – 2017-06-19T21:02:06.883

score:67. Some variation on this might make it possible to reduce the score further. – Giuseppe – 2018-01-18T17:54:31.777

@Giuseppe ... I should have re read it . whoops – MickyT – 2018-01-18T18:51:32.933

4

05AB1E, score 6

{γ€gLO

Try it online!

Erik the Outgolfer

Posted 2017-06-19T16:51:53.083

Reputation: 38 134

4

Pyth, score 6

1 byte thanks to isaacg.

+F/V._

Test suite.

How it works

+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.

Leaky Nun

Posted 2017-06-19T16:51:53.083

Reputation: 45 011

s+0 is the same as +F. – isaacg – 2017-06-19T19:27:50.633

Good! The best I could do is usaShHGrScQ1 8Z for 16. Can you add an explanation? – Digital Trauma – 2017-06-19T22:27:13.493

1@DigitalTrauma I've added an explanation. – Leaky Nun – 2017-06-20T03:47:47.433

s/LQ is score 4, does this use features that postdates the challenge? – Dave – 2018-01-19T03:31:22.740

4

J, score: 14 12 11

$+/@,2!1#.=

Try it online!

FrownyFrog

Posted 2017-06-19T16:51:53.083

Reputation: 3 112

Clever use of $. – cole – 2018-01-18T20:31:18.420

Nice. Slight 11 byte variation: 1#.2!1+1#.= – Jonah – 2019-04-28T05:12:07.437

@Jonah Reusing glyphs results in a penalty – FrownyFrog – 2019-04-28T12:24:12.613

ah, missed that part. – Jonah – 2019-04-28T14:32:52.713

4

Jelly, score of 7

ċЀQRFS

Explanation:

   Q    get unique letters
ċЀ     count the occurences of each letter in the original string
    R   [1..n] for n in list of frequencies
     F  flatten list
      S sum
        (implicit output)

Try it online!

ellie

Posted 2017-06-19T16:51:53.083

Reputation: 131

2Welcome to PPCG! – Laikoni – 2018-01-23T01:31:54.137

4

C, 60 bytes, score 108 95

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

Try it online!

Usually pre- and post-increment operators are great for code golf, but they really hurt on this challenge!

EDIT: By subtracting negative counts instead of adding positive ones, I saved a whole bunch of score. Replacing for() with while() eliminated a semicolon as well.

ErikF

Posted 2017-06-19T16:51:53.083

Reputation: 2 149

3

Jelly, score 5

ĠJ€ẎS

Try it online!

Thanks to Leaky Nun for -2 (previously on his answer)

Erik the Outgolfer

Posted 2017-06-19T16:51:53.083

Reputation: 38 134

Ahhh I didn't notice this question fast enough. – Leaky Nun – 2017-06-19T17:00:33.417

@LeakyNun p.s. you're not always a ninja, nor anyone is – Erik the Outgolfer – 2017-06-19T17:01:22.580

Really? I don't think so. – CalculatorFeline – 2017-06-19T17:03:10.040

Score 5: ĠJ€ẎS

– Leaky Nun – 2017-06-19T17:30:22.947

@LeakyNun As promised...yeah, the credit is there :) – Erik the Outgolfer – 2017-06-19T17:36:35.300

3

Perl 6, score  61 56 53 46  44

(1 X..*.comb.Bag.values).flat.sum

Try it

{sum flat 1 X.. .comb.Bag.values}

Try it

{sum flat 1 X.. values(.comb.Bag)}

Try it

{[+] flat	1	X.. values(.comb.Bag)}

Try it

{[+] flat	1	X.. values(bag
.comb)}

Try it

Brad Gilbert b2gills

Posted 2017-06-19T16:51:53.083

Reputation: 12 713

3

C# (.NET Core), score ∞ (I mean, 209)

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

Try it online!

The score includes the following:

using System.Linq;

Charlie

Posted 2017-06-19T16:51:53.083

Reputation: 11 448

I know it's been a while, but you can change return w*(w+1)/2 to return-~w*w/2 (score 196). EDIT: You can create a port of my Java 8 answer for a score of 149: using System.Linq;b=>{int[]x=new int[256];return\nb.Select(z=>++x[z]).Sum();} Try it online.

– Kevin Cruijssen – 2018-01-22T13:24:39.097

1@KevinCruijssen: I got your solution down to a score of 111: b=>{var x=new int[256];return\nb.Sum(z=>++x[z]);} – raznagul – 2018-03-15T11:07:39.560

@raznagul (half year old response incoming) 109 if you change the second space to a tab. ;) Try it online.

– Kevin Cruijssen – 2018-09-21T15:26:27.250

1

@KevinCruijssen (another half year old response incoming) 49 with the interactive compiler, and I think it won't ever get below 48. I find it odd how the more golfed C# answers get, the more readable they always seem to become. Try it online!

– my pronoun is monicareinstate – 2019-04-28T04:47:41.230

3

PowerShell, score 64

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

(Score is based on a single linefeed newline, which isn't Windows standard but does work in PS).

PS C:\> D:\unique-is-cheap.ps1 (gc D:\unique-is-cheap.ps1 -raw)
64
  • Hashtable counter @{}
  • Iterate through the letters; $args is an array of parameters - in this case the input string makes it a single item array; |% does a foreach loop over the items, and uses the getE* shortcut to match the GetEnumerator() string method and call it to turn the string into a character stream.
  • |% loop over the characters and increment their hashtable entry, add it to a running total. The ($x+=1) form with parens both modifies the variable and outputs the new value for use.
  • Output the running total.

(When I first wrote it, it was $c=@{};$t=0;[char[]]"$args"|%{$c[$_]++;$t+=$c[$_]};$t with a score of 128, and felt like it wouldn't go much lower. Halving it to 64 is quite pleasing).

TessellatingHeckler

Posted 2017-06-19T16:51:53.083

Reputation: 2 412

161 pts/ 38 bytes by messing with the increment – Veskah – 2019-01-03T04:34:03.037

59 pts/36 bytes – mazzy – 2019-04-29T07:29:52.697

3

Java 10, score: 149 138 137 134 133 130 103 102 101 100

(Bytes: 72 73 74 75 64 62 61) Bytes go up, but score goes down. :D

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

-28 score (and -11 bytes) thanks to @Nevay.
-1 score (and -2 bytes) thanks to @OlivierGrégoire.
-1 score (and -1 byte) by converting Java 8 to Java 10.

Explanation:

Try it here.

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

Kevin Cruijssen

Posted 2017-06-19T16:51:53.083

Reputation: 67 575

1You can remove the ~ if you use j=0 and return-j; (133). – Nevay – 2017-09-14T13:23:23.227

1103: x->{int[]q=new int[256];return\nx.chars().map(v->++q[v]).sum();} – Nevay – 2017-09-14T13:34:52.453

1@Nevay 103 actually, when I use j instead of u (return contains u) and a new-line and tab instead of the spaces. EDIT: Hehe, you've edited right when I made this comment. :) – Kevin Cruijssen – 2017-09-14T13:34:56.453

3

Julia 0.6, 45 bytes, Score: 77

Inspired by the MATL solution:

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

Try it online!

A less pretty solution, using counts:

Julia 0.6, score: 82

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

Try it online!

Thanks to Guiseppe for pointing out the scoring and for tips. These comments helped me loads.

niczky12

Posted 2017-06-19T16:51:53.083

Reputation: 301

1The score of your submission is the cost of your code, which I think is 135. – Giuseppe – 2018-03-14T15:45:46.837

1

I don't know Julia very well but I think you can reduce the score to 110 by switching some variable names and removing a set of parentheses. If returning a single-element vector is allowed, then you can replace (x+1) with [x+1] to further reduce the score.

– Giuseppe – 2018-03-14T17:09:32.450

You can save a score by changing the second space to a tab or new-line: score 104. And @Giuseppe tip of using [x+1] instead of (x+1) lowers it to a score of 98.

– Kevin Cruijssen – 2018-03-15T09:32:27.053

3

F#, score 120 118

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

-2 thanks to Kevin Cruijssen!

Try it online!

Takes a string as an input. Seq.countBy pairs each distinct character with its count (id is the identity function) so you end up with a collection like 'a' = 4, 'b' = 2 etc.

The Seq.sumBy takes the count for every letter and sums all the numbers from 0 to the count for that letter. So if 'a' = 4 the collection would be 0, 1, 2, 3, 4 which summed together is 10. Then Seq.sumBy sums all those totals.

Ciaran_McCarthy

Posted 2017-06-19T16:51:53.083

Reputation: 689

2You can lower your score by 2 by changing let q to let j, since the q is already used in both Seq. – Kevin Cruijssen – 2018-09-21T15:17:47.047

2

APL (Dyalog), score 15

+/1 1⍉+\∘.=⍨⍞

Try it online!

 get text input

∘.=⍨ equality table with self

+\ cumulative sum across

1 1⍉ diagonal (lit. collapse both dimensions into dimension one)

+/ sum

Adám

Posted 2017-06-19T16:51:53.083

Reputation: 37 779

2

Retina, score 68 45 43

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

Try it online! Link shows score. Edit: Thanks to @MartinEnder who saved 20 bytes by using overlapping matches instead of lookaheads and a further three bytes by grouping the stages so that the s flag only needs to be applied once. Saved a further two bytes by calculating the triangular number differently, avoiding the need for a sort.

Neil

Posted 2017-06-19T16:51:53.083

Reputation: 95 035

2

Mathematica, score 54

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

input

["abcdefg"]

thanks to hftf

J42161217

Posted 2017-06-19T16:51:53.083

Reputation: 15 931

Total[#(#+1)/2&@Counts@Characters@#]& scores 54. – hftf – 2017-09-19T14:48:23.690

2

Common Lisp, score 286 232 222

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

High-valued score due to the wordy syntax of builtin operators of Common Lisp.

Try it online!

The ungolfed code:

(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

Renzo

Posted 2017-06-19T16:51:53.083

Reputation: 2 260

2

PHP, 45 bytes, Score 78

WHILE($x=ORD($argn[$v++]))$y+=$$x-=-1;echo$y;

Try it online!

PHP, 46 bytes, Score 79 Bytes

WHILE(~$xy=$argn[$vz++])$su-=-$$xy+=1;echo$su;

Try it online!

PHP, 56 bytes, Score 92

FOREAch(COUNT_CHARS($argn)as$z)WHILE($z)$y+=$z--;echo$y;

Try it online!

Jörg Hülsermann

Posted 2017-06-19T16:51:53.083

Reputation: 13 026

2

Perl 5 score 91 83

Uses the -p flag which adds 2 because of the p in split.

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

user1937198

Posted 2017-06-19T16:51:53.083

Reputation: 121

Welcome to PPCG! – Laikoni – 2017-06-20T21:22:35.303

1

Using your answer as a base and applying some techniques from the tips page, I managed to get your score down to 31: Try it online!. $\ is automatically printed after each call so we can use that to store the score and /./g returns a list of all chars in $_, which is cheaper than split//.

– Dom Hastings – 2017-07-17T15:16:45.500

I know this is an old challenge, but you can cut the score even further: Try it online!

– Xcali – 2018-03-13T14:41:56.107

2

Octave, 39 bytes, Score 69

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

Try it online!

While there is another Octave answer, this one is entirely my own and a different approach, plus it scores less :).

The approach boils down to first finding the count (b) of each unique character, which is achieved using the histogram function. Then for each element we calculate the sum of 1 to b which is done using the formula (b*(b+1))/2. Then the individual sums are all summed into the final score.

In testing it seems brackets are really costly in the scoring because many are needed. I've optimised down from an initial score of about 88 by rearranging the questions to minimise the number of open/close brackets - hence we now do the /2 on the final total rather than individually, and also I've modified the formula to (b^2+b)/2 as that requires fewer brackets.

Tom Carpenter

Posted 2017-06-19T16:51:53.083

Reputation: 3 990

1Unfortunately this appears to fail on the empty string: error: hist: subscript indices must be either positive integers less than 2^31 or logicals – Laikoni – 2017-06-21T22:29:20.920

2

brainfuck, score 897

,[<<[[->+>-<<]>>[<]<[<]<[<]<[+<<]>>>>[>]>[->+>+<<]>[-<+>]<<<]<+[->>+<<]>>>[->+<]>[>]>,]<<[<]<

Try it online!

Ends on the cell with the correct value. Assumes a cell size larger than the score of the string, otherwise it'll wrap (got a little suspicious when the interpreter said the score was 188).

Jo King

Posted 2017-06-19T16:51:53.083

Reputation: 38 234

You might be able to change this to use one of the many binary-encoded brainfuck dialects that exist to lower your score... – Esolanging Fruit – 2018-01-19T05:22:01.387

CompressedFuck looks promising. – Esolanging Fruit – 2018-01-19T05:26:39.573

2@EsolangingFruit That's like saying switching to Jelly may save some bytes on your Java answer... :P – Conor O'Brien – 2018-01-19T22:45:03.543

2@ConorO'Brien I'd argue that it's more akin to switching from a version of Jelly which must begin with the header module Main where: import Jelly.Types; import Jelly.Builtins. The problem being solved is the same, it's just more competitive. But I do see your point - switching languages is essentially switching competitions, so it's not really fair to ask someone to do that. – Esolanging Fruit – 2018-01-20T00:17:23.900

2

Japt -x, 9 7 points

å+ ®èZÌ

Try it

Shaggy

Posted 2017-06-19T16:51:53.083

Reputation: 24 623

2Not that hard to optimise for score when you can solve it using entirely unique characters, huh :P – ETHproductions – 2018-01-22T15:45:35.753

2

SNOBOL4 (CSNOBOL4), score: 681

	s	=iNPUT
	Y	_table()
d	S	LEN(1) . x REM . S	:F(b)
	Y<X>	=y<X> + 1	:(D)
b	Z	_convert(Y,'aRrAy')
N	j	=J + 1
	G	_z[j,2]	:f(q)
	o	=o + g * G + g	:(N)
q	OUtpuT	_O / 2
end

Try it online!

looks a bit scary, but SNOBOL matches identifiers case-insensitively, which dropped the score by around 100 points. Note that it requires a single line of input, so I've replaced \n with ; in the input field (which is still valid SNOBOL).

The SNOBOL4 implementation on TIO allows for an additional 16 point golf, as = and _ are both allowable as the assignment operator. How neat!

Giuseppe

Posted 2017-06-19T16:51:53.083

Reputation: 21 077

2

Rust, 265 255 bytes. Score: 1459 1161

fn main(){let mut z=String::new();std::io::stdin().read_line(&mut z);let Z=z.trim_right_matches(|x|x=='\r'||x=='\n');let mut q:Vec<u8>=Z.bytes().collect();q.sort();let(mut k,mut W,mut j)=(0,0u8,0);for Y in&q{if*Y==W{j+=1}else{j=1;W=*Y}k+=j}print!("{}",k)}

Ungolfed

fn main() {
    let mut input_string = String::new();
    std::io::stdin().read_line(&mut input_string);
    let trimmed = input_string
        .trim_right_matches(|c| c == '\r' || c == '\n');
    let mut chars: Vec<u8> = trimmed.bytes().collect();
    chars.sort();
    let (mut total_score, mut last_char, mut last_score) = (0, 0u8, 0);
    for letter in &chars {
        if *letter == last_char {
            last_score += 1;
        } else {
            last_score = 1;
            last_char = *letter;
        }
        total_score += last_score;
    }
    print!("{}", total_score);
}

Edit: improved answer by renaming variables and altering code

dragonite44

Posted 2017-06-19T16:51:53.083

Reputation: 91

1Welcome to PPCG! In this challenge the score of your submission is the cost of your code, which I think is 1459. – Laikoni – 2018-03-15T13:26:16.713

Edited. Thanks for pointing that out – dragonite44 – 2018-03-15T13:32:55.633

2This also means you can improve your score quite a bit by choosing characters as variable names which are not already contained in other keywords. – Laikoni – 2018-03-15T13:34:57.967

2You're still using a lot of variable names that are characters used elsewhere. jkqvxz and most capitals are unused and would improve the score. – Ørjan Johansen – 2018-03-16T10:19:54.300

2

Husk, Score 9

½§+L(Σ´×=

Try it online!

Explanation:

This calculates the score as sum_i (n_i^2 + n_i)/2, where i is indexed arbitrarily across unique character types and n_i is the number of characters of type i in the input. But since sum_i n_i is the length of the input, this reduces to (1/2) * (L + sum_i n_i^2)

Code breakdown:

o ½ (§ + L (o Σ (´ (× =)))        --With parentheses and two implicit compositions
                   (× =)          --1 or 0 for each equality check between elements of its first and second arguments
                (´ (× =))         --argdup, 1 or 0 for each equality check between elements of its only argument
           (o Σ (´ (× =))         --# of equalities between pairs (this will give sum_i n_i^2)
         L                        --length
    (§ + L (o Σ (´ (× =)))        --length + sum_i n_i^2
o ½ (§ + L (o Σ (´ (× =)))        --1/2 * (length + sum_i n_i^2)

Sophia Lechner

Posted 2017-06-19T16:51:53.083

Reputation: 1 200

You can do Ṡṁ# instead of (Σ´×= for a score of 7. – Zgarb – 2018-03-17T11:37:14.583

2

Python 2. Score:142 115

def     f(a):
        x=0
        for y in set(a):z=a.count(y);x+=.5*z*-~z
        print x

EDIT:-27 thanks to @Kevin Cruijssen

sonrad10

Posted 2017-06-19T16:51:53.083

Reputation: 535

By changing the indentations and the space between def f(a) to tabs you lower your score to 126. In addition, you can change (z+1) to -~z to lower it more to 117. And you can remove the 0 in 0.5 to lower it to 115. Try it online.

– Kevin Cruijssen – 2018-03-21T15:00:31.227

@KevinCruijssen Thanks, Changed! – sonrad10 – 2018-03-21T15:11:06.713

1Try it online! link – Ørjan Johansen – 2018-03-21T17:51:01.423

1

Python 3, score 89 85

lambda	y:sum(y[:x+1].count(v)for	x,v in enumerate(y))

Try it online!

ovs

Posted 2017-06-19T16:51:53.083

Reputation: 21 408

@ETHproductions thanks a lot. – ovs – 2018-01-22T18:59:12.750

1

APL (Dyalog), score 27 18 11

Reduced score by 7 thanks to @Adám by using a tradfn and using 1⊥ to sum the frequencies

1⊥{+/⍳≢⍵}⌸⍞

Try it online!

user41805

Posted 2017-06-19T16:51:53.083

Reputation: 16 320

1

Same method, score 11: 1⊥{+/⍳≢⍵}⌸⍞

– Adám – 2017-06-19T17:55:43.097

@Adám Thanks, the 1⊥ trick is really neat – user41805 – 2017-06-20T08:36:31.380

1

Python 2, score 83

lambda z:sum((2*z.count(x)+1)**2/8for x in set(z))

Try it online

1/8 (1 + 2 n)^2 -1/8 is the same as n (n+1) / 2. Floor division removes the need to subtract 1/8.

mbomb007

Posted 2017-06-19T16:51:53.083

Reputation: 21 944

1

Octave , score 77 31 bytes

*same as @LuisMendo 's MATL answer.

@(a)nnz(triu(a==a'))

Try it online!

Previous answer:

@(d,g=accumarray(+d',1)-(0:254))sum(g(g>0));

Try it online!

rahnema1

Posted 2017-06-19T16:51:53.083

Reputation: 5 435

You could probably save a point by ditching the semicolon. Couldn't test it as it doesn't seem to work with TIO. – Tom Carpenter – 2017-06-21T22:05:39.827

@TomCarpenter Without ; doesn't work. however such a lambda cab be used in arrayfun. – rahnema1 – 2017-06-22T02:55:53.743

1

J, score 23

$-:@+[:+/,/@(=/~)

Try it online!

Leaky Nun

Posted 2017-06-19T16:51:53.083

Reputation: 45 011

1

Clojure, score 96

#(apply +(for[[k j](frequencies %)](*(inc j)j 0.5)))

Five spaces and pairs of brackets...

NikoNyrh

Posted 2017-06-19T16:51:53.083

Reputation: 2 361

1

Actually, score 12

;╗╔⌠╜cRΣ⌡MΣ

Try it online!

Explanation:

;╗╔⌠╜cRΣ⌡MΣ  (implicit input: S)
;╗           save a copy of S in register 0
  ╔          uniquify S (call it A)
   ⌠╜cRΣ⌡M   for each unique character in A:
    ╜c         count the number of occurrences in S
      R        range(1, count+1)
       Σ       sum
          Σ  sum

Repeating the Σ is two points less than using an alternative formulation with no repeated characters (i`+Y).

Mego

Posted 2017-06-19T16:51:53.083

Reputation: 32 998

1

F#, score:12641110

-154 points, thanks to @Laikoni

let x(y:bool)=System.Convert.ToInt32(y)
let rec p(k:string)q=
 let j=k.Length
 if(j=1)then(x(k.[0]=q))else p k.[0..(j-2)] q+x(k.[j-1]=q)
let rec d(a:string)=
 let z=a.Length
 if(z<2)then z else d a.[0..(z-2)]+p a (a.[z-1])

You need to call the d function. In a more readable form:

let x (y:bool)=
    System.Convert.ToInt32(y)
let rec e (c:string) b=
    let j=c.Length
    if(j=1)then
        (x(c.[0]=b))
    else 
        e c.[0..(j-2)] b+x (c.[j-1]=b)
let rec d (a:string)=
    let h=a.Length
    if(h<2)then 
        h 
    else
        d a.[0..(h-2)]+e a (a.[h-1])

Explanation

It is a recursive algorithm, the base case is, if the length of the string is less than 2 (0 or 1), the score will be the length of the string. This is because, if the length is 0 (empty string), we have no characters, so the score is 0, and if the length is 1, that means, that the string consists of only 1 character, so the score is 1.

Otherwise it trims the last character of the string, and to the score of the truncated string adds the count of the last character in the untruncated string.

The counting algorithm is also recursive. Its base case is, when the length of the string is one, then the count is 1, if the string matches with the character, and 0 otherwise. This can also be done, if we convert the bool to an int, and this results in a lower score.

Otherwise it trims the last character of the string, calculates the count of that string, and if the last character matches the character, we are calculating the count of, adds one to the count. This is again, better, if we convert that boolean to an int.

Horváth Dávid

Posted 2017-06-19T16:51:53.083

Reputation: 679

I think you can remove some white space, e.g. around the parentheses in let rec e (c:string) b=. Also using some character as variable which does not appear in keywords will improve your score, e.g. y instead of e. – Laikoni – 2017-06-20T14:44:36.913

1

AWK, 39 bytes, Score 54

BEGIN{RS="(.)"}{M+=++s[RT]}END{print M}

Try it online!

Robert Benson

Posted 2017-06-19T16:51:53.083

Reputation: 1 339

1Changing S to some unused character reduces the score by two. – Laikoni – 2017-06-21T21:45:59.990

1

FIREBIRD, score 3577

Version to calculte the score:

SELECT COALESCE(SUM(C),0)FROM(WITH RECURSIVE T AS(SELECT 1 AS I,SUBSTRING(CAST(:V AS BLOB)FROM 1 FOR 1)AS S FROM RDB$DATABASE UNION ALL SELECT I+1,SUBSTRING(CAST(:V AS BLOB)FROM I+1 FOR 1)FROM T WHERE I < CHAR_LENGTH(CAST(:V AS BLOB)))SELECT T.*,(SELECT COUNT(T2.I) FROM T T2 WHERE T2.S=T.S AND T2.I<=T.I)AS C FROM T WHERE CAST(:V AS BLOB) <> '')

Below is the idented version of the code, in case anyone want to now. I'm sorry for any mistakes, first time here actually posting!

SELECT COALESCE(SUM(C), 0)
FROM (
  WITH RECURSIVE T AS (
    SELECT 1 AS I, SUBSTRING(CAST(:V AS BLOB) FROM 1 FOR 1) AS S
    FROM RDB$DATABASE

    UNION ALL

    SELECT I+1, SUBSTRING(CAST(:V AS BLOB) FROM I+1 FOR 1)
    FROM T
    WHERE I < CHAR_LENGTH(CAST(:V AS BLOB))
  )
  SELECT T.*, (SELECT COUNT(T2.I) FROM T T2 WHERE T2.S = T.S AND T2.I <= T.I) AS C
  FROM T
  WHERE CAST(:V AS BLOB) <> ''
)

Explanation

I start my select in a system table SELECT 1 AS I, SUBSTRING(CAST(:V AS BLOB) FROM 1 FOR 1) AS S FROM RDB$DATABASE, which always has only one row. Using that only one row, I return 1 as a column I, and the character that exists in the input in the I value.

Let's say I've passed 'abaacab' as input:

╔═══╦═══╗
║ I ║ S ║
╠═══╬═══╣
║ 1 ║ a ║
╚═══╩═══╝

In the UNION ALL part, I start to increment the index from the first select, until it reaches the end of the input. So, in the example I would get this:

╔═══╦═══╗
║ I ║ S ║
╠═══╬═══╣
║ 1 ║ a ║
║ 2 ║ b ║
║ 3 ║ a ║
║ 4 ║ a ║
║ 5 ║ c ║
║ 6 ║ a ║
║ 7 ║ b ║
╚═══╩═══╝

After that, I also select the count of ocurrences from the value on S, that has already appeared in indexes below the I. So, in a column C I now have the 'cost' of that character, which I only need to SUM after to get the value.

╔═══╦═══╦═══╗
║ I ║ S ║ C ║
╠═══╬═══╬═══╣
║ 1 ║ a ║ 1 ║
║ 2 ║ b ║ 1 ║
║ 3 ║ a ║ 2 ║
║ 4 ║ a ║ 3 ║
║ 5 ║ c ║ 1 ║
║ 6 ║ a ║ 4 ║
║ 7 ║ b ║ 2 ║
╚═══╩═══╩═══╝

I used BLOB as the type from the input, to not get limited by size.

Filipe Santos

Posted 2017-06-19T16:51:53.083

Reputation: 21

Welcome to PPCG! – Laikoni – 2017-06-22T21:33:33.860

@Laikoni Thanks! I forgot to add a short explanation, my bad. I will do it later, in case anyone is interested. – Filipe Santos – 2017-06-22T22:17:10.460

I'm always interested in explanations. :) Have you checked for each space wether it can be removed or not? Some of them look unnecessary, e.g. (SUM(C), 0) or AS (SELECT, thought I don't know firebird. – Laikoni – 2017-06-23T06:03:45.267

Thanks @Laikoni, with your advice I saved some points. I've just add my explanation. If its too bad just let me know so I can try to make a better one. – Filipe Santos – 2017-06-23T11:17:39.363

1

K/Kona, score 19

+/,/1+!:'(#:)'=

Works as:

              = (implicitly take arg as input), group -> make dictionary of characters to their occurring indices
         (#:)'= count each of these 
    1+!:'(#:)'= get a list from 0->n-1 for each of these counts, add one to each 
+/,/1+!:'(#:)'= finally, reduce to single list, sum reduce this list

Example:

k)+/,/1+!:'(#:)'="+/,/1+!:'(#:)'="
19
k)+/,/1+!:'(#:)'="abaacab"
14

Legible q equivalent:

(sum/)raze 1+til count each group 

Simon Major

Posted 2017-06-19T16:51:53.083

Reputation: 401

1

Pyke, score 7

cemSss

Try it here!

c      -    count_occurrences(input)
 e     -   values(^)
  mS   -  [range(1,i+1) for i in ^]
    ss - sum(sum(i)for i in ^)

Blue

Posted 2017-06-19T16:51:53.083

Reputation: 26 661

1

Jelly, 10 9 bytes; Score 10 9

ṢŒrzẆṪRẎS

Try it online!

This is the first time I use Jelly, and I didn't want to check other people's answers because I wanted to try it myself. I probably reinvented the wheel a couple times there. Suggestions and feedback are greatly appreciated.

EDIT: -1 byte for removing ɠ and taking the input as an argument.

Explanation:

ṢŒrzẆṪRẎS           #Main Link; input abaacab
Ṣ                   #sorts input; aaaabbc
 Œr                 #run-length encode, or the number of times a character appears; a4b2c1
   z                #zip; ['abc', [4, 2, 1]]
    Ẇ               #takes every contiguous sublists
     Ṫ              #Pops the last element; [4, 2, 1]
      R             #Takes the range of every element; [[1,2,3,4],[1,2],1]
       Ẏ            #Collapses every element into a single array; [1,2,3,4,1,2,1]
        S           #Sum and implicitly print; 14.

(no idea why, but the code doesn't work without , although it gives the exact same output as z)

J. Sallé

Posted 2017-06-19T16:51:53.083

Reputation: 3 233

8 bytes, score of 8 – caird coinheringaahing – 2017-11-20T21:21:33.923

1

Japt, score 12 (+2 for -x) = 14

¬n ó¥ ËÊõÃc

Explanation

¬n ó¥ ËÊõÃc                                             "abaacab"
¬            // Split the input into an array of chars  ["a","b","a","a","c","a","b"]
 n           // Sort                                    ["a","a","a","a","b","b","c"]
   ó¥        // Partition matching items                [["a","a","a","a"],["b","b"],["c"]]
      Ë      // map; For each array:
       Ê     //   Get the length x                      [4,2,1]
        õ    //   Create a range [1...x]                [[1,2,3,4],[1,2],[1]]
         Ã   // }
          c  // Flatten                                 [1,2,3,4,1,2,1]
-x           // Sum                                     14

Try it online!

Oliver

Posted 2017-06-19T16:51:53.083

Reputation: 7 160

1

J, score 14

1#.2!1+#/.~

Try it online!

Outgolfed by the other J solution, but figured I'd post this anyways since it uses a slightly different method.

cole

Posted 2017-06-19T16:51:53.083

Reputation: 3 526

1

Attache, score 36

Sum@Map&:(Count#Last)@Prefixes

Try it online!

Explanation

Sum@Map&:(Count#Last)@Prefixes

This is a composition of 3 functions:

  • Prefixes - this simply obtains the prefixes of the input
  • Map&:(Count#Last) - This is a mapped fork. This is equivalent to arr.map { e -> e.count(e.last) } So, for each character, this counts the occurrences of that character so far.
  • Sum - this sums all of these numbers.

Conor O'Brien

Posted 2017-06-19T16:51:53.083

Reputation: 36 228

1

MS-SQL, score 308

I'm using a completely different technique from my other answer, with additional restrictions, so I'm submitting them separately:

SelEcT SUm(k)FROM(SELECT k=couNt(*)*(CoUNT(*)+1)/2froM spt_values,z WHERE type='P'AND number<len(q)GROUP BY sUBstring(q,number+1,1))L

Caveats: this must be run from the master database of a MS-SQL server set to a case-sensitive collation (mine is set to SQL_Latin1_General_CP850_BIN2).

Input is via varchar field q in pre-existing table z, per our IO rules. Formatted:

SelEcT SUm(k)
FROM
    (SELECT k=couNt(*)*(CoUNT(*)+1)/2
     froM spt_values,z 
     WHERE type='P'
     AND number<len(q)
     GROUP BY sUBstring(q,number+1,1)
    )L

The trick here is to use a "number table" to join with the input table, which allows me to separate each character into its own row, then group by matching characters, count them up, calculate the score of each, and sum them all together. All the rest is minimizing score by playing with character case, since SQL keywords are not case sensitive.

MS-SQL has a system table in the master database called spt_values with a lot of junk in it, but I restrict it to type='P', I get a nice number table with 0 through 2047.

BradC

Posted 2017-06-19T16:51:53.083

Reputation: 6 099

1

K4, score 15

Solution:

+/,/{1+!#x}'=

Example:

q)k)+/,/{1+!#x}'="Programming Puzzles & Code Golf"
47

Explanation:

+/,/{1+!#x}'= / the solution
            = / group
    {     }'  / apply lambda to each (')
         x    / implicit lambda input
        #     / count length
       !      / range 0..n
     1+       / add one
  ,/          / flatten list
+/            / sum up

Notes:

In Q this could be written as:

q)sum raze { 1 + til count x } each group "Programming Puzzles & Code Golf"
47

streetster

Posted 2017-06-19T16:51:53.083

Reputation: 3 635

1

JavaScript (ES6), 112 95 points

Came up with the original version down the pub on Friday before noticing the scoring mechanism. Golfed a few points off before ditching it in favour of more beer, but it seemed a shame to let it go to waste completely!

s=>s.map((w,x)=>s.map((y,z)=>y!=w|z<x?8:++n),n=0)|n
  • 7 points saved thanks to ETHProductions

Try it

o.innerText=(f=
s=>s.map((w,x)=>s.map((y,z)=>y!=w|z<x?8:++n),n=0)|n
)([...i.value=""+f]);oninput=_=>o.innerText=f([...i.value])
<input id=i type=number><pre id=o>


Original, 112 points

o.innerText=(f=
a=>a.reduce((x,y,z)=>x+a.filter(v=>v==y&--w<0,w=z).length,0)
)([...i.value=""+f]);oninput=_=>o.innerText=f([...i.value])
<input id=i type=number><pre id=o>

Shaggy

Posted 2017-06-19T16:51:53.083

Reputation: 24 623

1

Standard ML, 66 bytes, score 113

fun$(a::z)=1+length(List.filter(fn y=>y=a)z)+	$z|
$_=0;$o explode;

This code defines an anonymous function which is bound to the implicit result identifier it. Try it online!

Explanation

The ungolfed code looks like this:

fun f (a::z) = 1 + length (List.filter (fn y => y=a) z) + f z
  | f  _     = 0
val g = f o explode

The function g takes a string as input, converts it to a list of characters with explode, and passes it on to the function f which recurses over the list, with a being the current character and z being the remaining list. For each a the number of occurrences of a in z is computed by filtering z to contain only chars equivalent to a and taking the length of the resulting list. The result is incremented by one to account for the current occurrence of a and added to result of the recursive call of f on z.

Laikoni

Posted 2017-06-19T16:51:53.083

Reputation: 23 676

1

PHP, 44 bytes, score 78:

While($C=ORD($argn[$p++]))$s-=++$$C;EcHo-$s;

Almost Jörg´s solution, but one byte shorter.


PHP, 51 bytes, score 80

ForEach(COUNT_CHARS($argn)As$p)$z-=~$p*$p/2;echo$z;

Run as pipe with -nR or try them online

Titus

Posted 2017-06-19T16:51:53.083

Reputation: 13 814

1

Perl6/Rakudo, 45 bytes, score 66

Run with perl -ne:

say [+] bag(.comb).values.map({($_+1)*$_/2});

Uses the essential nature of a Bag (like a set with a count per member).

Step by step:

.say;                      # abaacab
say .comb;                 # (a b a a c a b)
say bag(.comb);            # Bag(a(4), b(2), c)
say bag(.comb).values;     # (2 4 1)
say bag(.comb).values.map({($_+1)*$_/2});        # (3 10 1)
say [+] bag(.comb).values.map({($_+1)*$_/2});  #14

Also note that each character's score can be calculated from its occurrences as (n+1)*n/2.

Edited because I cannot evidently read.

Phil H

Posted 2017-06-19T16:51:53.083

Reputation: 1 376

1In this challenge, the score of your submission is the cost of your code which I think is 75. – Giuseppe – 2018-03-15T14:18:55.420

1

><>, score 33

0vAB;n*<
p>i:0(?^:ag1+:}r-@a

Try it online!

28 bytes, with 2 occurrences each of a and 0, and 3 occurrences of :. AB can be replaced by any two characters which don't appear anywhere else in the code.

Works by storing the current character count in the code grid on row 10. The sum is actually a negative sum to start with, and the -1 from reaching the end of STDIN is multiplied with this to turn it back into a positive number.

Sok

Posted 2017-06-19T16:51:53.083

Reputation: 5 592

1

SHELL ( 67 bytes)

Last Solution : ( 68 bytes)

 f(){ bc<<<`echo -n "$1"|od -bAn|sed "s/\([^ ]\+\)/s+=++v\1;/g"`s;}

Old solutions :

Old Solution 1 : by creating function f (83 bytes ) :

f(){ bc<<<`echo "$1"|sed "s/./ss+=++&;/g"|sed "s/[A-Z]/\L&_/g"|sed "s/ /bb/g"`ss;}

Old Solution 2 : by creating alias f ( 81 bytes )

alias f='bc<<<`cat -|sed "s/./ss+=++&;/g"|sed "s/[A-Z]/\L&_/g"|sed "s/ /bb/g"`ss'

Explanations :
I used ( sed "s/./ss+=++&;/g" ) to replace any char a by ( ss+=++a; ); where ss is the sum to calculate, then concatenate with ss, and calculate all expression by the command bc :

echo "a" | sed "s/./ss+=++&;/g"
ss+=++a;

for a string in input :

echo "aab" | sed "s/./ss+=++&;/g"
ss+=++a;ss+=++a;ss+=++b;

step by step :

ss+=++a;    // a=1  -->  ss=1
ss+=++a;    // a=2  -->  ss=3
ss+=++b;    // b=1  -->  ss=4

for lowercase only input, the simpler function need only ( 47 bytes ) to define :

f(){ bc<<<`echo "$1"|sed "s/./ss+=++&;/g"`ss;}

to take uppercase in consideration, Without spaces ( 68 bytes) :

f(){ bc<<<`echo "$1"|sed "s/./ss+=++&;/g"|sed "s/[A-Z]/\L&_/g"`ss;}

Complete Solution ( 83 bytes):

f(){ bc<<<`echo "$1"|sed "s/./ss+=++&;/g"|sed "s/[A-Z]/\L&_/g"|sed "s/ /bb/g"`ss;}

fuction tests :

f "abaacab"
14

f "abcdefg"
7

f "       "
28

f "Aa"
2

using an alias instead the function, we can reduce code size to ( 68 bytes )

alias f='bc<<<`cat -|sed "s/./ss+=++&;/g"|sed "s/[A-Z]/\L&_/g"|sed "s/ /bb/g"`ss'

alias tests :

echo "       " | f
28

echo "Ab" | f
2

Ali ISSA

Posted 2017-06-19T16:51:53.083

Reputation: 211

1The score of your submission is the cost of your code, that is 241 for the 84-byte version and 232 for the 81 byte version. – Laikoni – 2018-03-17T15:10:25.240

Since this challenge is not scored by length, you should list the scores instead of byte counts. – Ørjan Johansen – 2018-03-23T02:37:48.353

1

Ruby, score: 38

->z{z.sum{|k|z.count(k)+1}/2}

Try it online!

Asone Tuhid

Posted 2017-06-19T16:51:53.083

Reputation: 1 944

1

R, 349

Here is my R solution bit of tidy

s=function(x) {c=0
for (i in unique(strsplit(x,"")[[1]])) {
c=c(c,sum(1:sum(charToRaw(x)==charToRaw(i))))}
sum(c)
}

Riccardo Camon

Posted 2017-06-19T16:51:53.083

Reputation: 41

3Welcome to PPCG! The point of this challenge is to make the score (the output of running your code on your code) as small as possible. This would have quite a large score! I would be more than happy to help you reduce the score. – Giuseppe – 2018-03-17T15:34:00.417

Thanks @Giuseppe will work to improve it! Cheers – Riccardo Camon – 2018-03-17T15:38:38.697

This answer still has a lot of unnecessary whitespace and long variable names it. Also, in order to be a valid solution, you'll need to provide the current byte count. (which is currently 174) – James – 2018-03-19T17:24:25.010

1

While in the counting part you use charToRaw(), better use it instead strsplit() too. Score 195

– manatwork – 2018-03-20T13:16:31.587

@manatwork thanks for your advice but it is not quite clear when you would use strsplit() – Riccardo Camon – 2018-03-21T11:27:29.467

Uhm… Never. Both functions decomposes the string into vectors of unique values per character, so I suggested to work exclusively with raws. BTW, the code I linked has the score of 195. Your currently posted code's score is 456. ☹ – manatwork – 2018-03-21T11:36:46.020

@manatwork just amended thanks working on cut it short now! – Riccardo Camon – 2018-03-21T11:55:27.117

1

C++ (gcc), Score: 209 196

98 96 bytes

#include<map>
long	F(std::string	S){int I=0;for(auto&C:S){++I;for(char&D:S)I+=C==D;}return I/2;}

C++-specific tricks:

  • #include<map> instead of #include<string>
  • Returning long instead of int to use more different characters
  • Using auto instead of char in one of the loops has the same effect
  • References (&) inside range-for save whitespace

Common tricks:

  • Evenly use both tabs and blanks
  • Upper case variables to be distinct from keyword characters

Try it online!

movatica

Posted 2017-06-19T16:51:53.083

Reputation: 635

1

JavaScript, 150 141 133

f=(g,i=[])=>g?(i[j=g.charCodeAt()]=(i[j]|0)+1)+f(g.substr(1),i):0

Ungolfed:

f=(g,i=[])=>                                                       //function declaration, a is list of appearance of characters so far.
            g?                                                     //check if string is empty
              (i[j=g.charCodeAt()]=                                //update appearance list
                                    (i[j]|0)+1)+                   //handle undefined, then increment
                                                f(g.substr(1),i)   //next character
                                                                :0 //base case for the empty string

150->141 - -6 for renaming variables to unique characters (thanks to Ørjan Johansen), and -3 for removing implicit 0 in charCodeAt.

141->133 - -8 for using actual unique variable names(thanks again to Ørjan Johansen).

Naruyoko

Posted 2017-06-19T16:51:53.083

Reputation: 459

The variable names s,a,c give you a higher score than necessary because they're used as characters in charCodeAt and subStr. – Ørjan Johansen – 2019-04-28T10:45:21.267

@Ørjan Johansen Hmm, then let's see if I can do better – Naruyoko – 2019-04-28T17:11:27.647

b and d are still not unique. I think i and j are the first vacant ones. – Ørjan Johansen – 2019-04-29T00:33:20.370

@Ørjan Johansen Oh yeah true – Naruyoko – 2019-04-29T00:50:45.077

0

Python 2, score 108

lambda S:sum(S.count(Q)*(S.count(Q)+1)/2for Q in set(S))

Still golfing :)

Daniel

Posted 2017-06-19T16:51:53.083

Reputation: 6 425

I think you missed the scoring system. – Leaky Nun – 2017-06-19T17:31:16.050

@LeakyNun Oh shoot you're right –– and that was fast – Daniel – 2017-06-19T17:31:31.800

S.count(Q)*(S.count(Q)+1)/2for Q in set(S) should be the same as (S.count(Q)+1)/2for Q in S – movatica – 2019-04-27T21:54:39.590

0

JavaScript (Firefox 30+), score 68

S=>[for(C of(T=0,S))T+=S.split(C).length]&&T/2

This uses array comprehensions which were originally planned for ES7, but were dropped late in the process. Firefox had implemented them anyway.

ETHproductions

Posted 2017-06-19T16:51:53.083

Reputation: 47 880

I thought those were ES6...? – CalculatorFeline – 2017-06-20T01:55:15.960

@CalculatorFeline No, they didn't make it in favour of map/filter with arrow functios – Bergi – 2017-06-22T00:08:24.280

*planned for ES6 – CalculatorFeline – 2017-06-22T02:26:11.093

0

QBIC, score: 128

dim x(126)[_l;||i=asc(_sA,a,1|)┘x(i)=x(i)+1][126|[x(b)|p=p+c}?p

Nice round score of 128.

Explanation

dim x(126)      Create an array of 126 elements (one for each ASCII element)
[_l;||          Read cmd line input, loop over its length
i=asc(_sA,a,1|) Read the next char's ascii value
┘               (Syntactic linebreak)
x(i)=x(i)+1     Raise the count of this ASCII char by 1
]               NEXT
[126|           Loop over the ASCII array again
[x(b)|          Read the count and start a loop that runs from 1 to that count
p=p+c           Add to running total p the loop counter
}               Close both loops
?p              PRINT p

steenbergh

Posted 2017-06-19T16:51:53.083

Reputation: 7 772

0

Ruby, score 63 60

Uses the -n flag which ends up adding 2 points due to the presence of another n within the code.

-3 points from Alexis Anderson.

i=x=0
gsub(/./){x+=$_[0,i+=1].count$&};p x

Try it online!

Value Ink

Posted 2017-06-19T16:51:53.083

Reputation: 10 608

why not use a different variable than s since s is in gsub. It would save you 3 points, I believe. – Alexis Andersen – 2017-06-21T17:06:42.520

@AlexisAndersen wow I can't believe I missed that – Value Ink – 2017-06-21T19:35:52.547

0

Swift 3, 153 bytes, score = 637

var u:(String)->Int={var d = Dictionary<Character,Int>()
for c in $0.characters{d[c] = (d[c] ?? 0) + 1}
return d.values.reduce(0,{$0 + $1 * ($1 + 1) / 2})}

Legible version plus explanation

func unique(_ string: String) -> Int {
    var dict = Dictionary<Character, Int>()
    for char in string.characters { dict[char] = (dict[char] ?? 0) + 1 }
    return dict.values.reduce(0, { $0 + $1 * ($1 + 1) / 2 })
}

My solution takes the string, iterates over the characters and tracks each unique character in a dictionary, counting the occurrences per character. Once that's done, it reduces the dictionary's values using the triangle number formula ( n(n+1) / 2 ) and returns the result.

Comments

Swift obviously isn't the best language for golfing, but it was fun to see where I could save bytes despite its rigid syntax. This is my first Swift submission - be gentle!

Archmage stands with Monica

Posted 2017-06-19T16:51:53.083

Reputation: 171

0

><> (Fish), score 133

!<01-0&i:2(:?&:?n?;&1+&:}}:3(00@@?.~~:{=&+&{$}8e+0.>.!06}~{ 

This code reads the input per character, adds a point and loops through all the read characters, adding an extra point for every equal character.

You can try it out here

Explanation

!<01-0&         // Initialize (put -1 on the stack and 0 in the register)
i:2(:?$:?n?;    // Read the next input. If it's -1, print the register and end the program.
&1+&            // Add one to the register
:}}:            // Duplicate both the input and the check value
3(00@@?.~~      // If the check value is -1, jump the instruction pointer to 0,0 (line 0)
:{=&+&          // Compare the input to the check value and add the result to the register
{$}8e+0.        // Move the checked value to the bottom of the stack and jump to 22,0 (line 4)
>.!06}~{        // Clean up the stack and jump to 0,6 (line 2)

Thijs ter Haar

Posted 2017-06-19T16:51:53.083

Reputation: 752

0

CJam, score 18

q_,{)W$<}%.e=0+:+

Try it online!

Explanation

q                  e# Read the input.
 _,                e# Copy it, get its length.
   {               e# Map over the range from 0 .. length-1:
    )              e#  Increment the current number.
     W$            e#  Push the input.
       <           e#  Get the first <current number> characters of it.
        }%         e# (end map)
          .e=      e# Count the occurrences of each character in the corresponding slice.
             0+    e# Append a 0 to the result (because you can't reduce and empty list).
               :+  e# Reduce by addition (sum).

Business Cat

Posted 2017-06-19T16:51:53.083

Reputation: 8 927

You can replace 0+:+ with 1b (convert from base 1, which handles empty list and doesn't have the duplicated character), which gets you a score of 15. – Esolanging Fruit – 2018-01-19T05:20:05.510

0

JavaScript, 49 bytes, score 88

b={};s=0;for(j in a=prompt())s+=b[a[j]]=-~b[a[j]]

C5H8NNaO4

Posted 2017-06-19T16:51:53.083

Reputation: 1 340

The score of each submission is not the byte count, but the cost of the submission, that is the program run on its own source code. This means your score is 88 instead of 49. – Laikoni – 2017-07-17T13:07:52.070

0

Factor, 2435

(o god my score)

"" over [ 2dup swap in? [ drop ] [ suffix ] if ] each { } swap swapd [ dupd 0 swap swapd swap [ over = swap [ [ 1 + ] [ ] if ] dip ] each drop swap [ suffix ] dip ] each drop [ dup 1 + * 2 / ] map sum (wrong formatting on purpose for multi-line span)

Wow, Factor is hard. Or I'm just bad. Probably a little bit of both.

Quelklef

Posted 2017-06-19T16:51:53.083

Reputation: 441

Could you tell me what needs to be added in order to test this code on Try it online?

– Laikoni – 2017-07-18T10:11:36.507

@Laikoni add the string to the beginning of the code. So, for abaacab, the code will read "abaacab" "" over [ 2dup... – Quelklef – 2017-07-23T00:26:11.860

@Laikoni Come to think of it, you'd have to add USING: kernel sequences sets math ; to the beginning, too, (they're libraries). Also, it's working on my local machine but not on TIO, and IDK why. Never used Factor on TIO. – Quelklef – 2017-07-23T00:32:06.047

0

Pyt, 6 bytes

ĐỤ⇹ɔ△Ʃ

Explanation:

              Implicit input
Đ             Duplicate top of stack
 Ụ            Get unique characters
  ⇹           Swap top two items on stack
   ɔ          Count number of times each unique character occurs in the input
    △         Calculates the total score for each character
     Ʃ        Sum count
              Implicit output

Try it online!

mudkip201

Posted 2017-06-19T16:51:53.083

Reputation: 833

0

Stax, 8 6

ç╕┌α▒'

Run and debug online!

Saved 2 points by using runs per comment by @recursive.

Explanation

Uses the unpacked version to explain.

o:GF:T+
o          Sort array
 :G        Run lengths
   F       For each run length `n`
    :T     The nth triangular number
      +    Add to accumulator
           Implicit output

Weijun Zhou

Posted 2017-06-19T16:51:53.083

Reputation: 3 396

1

run-length is good here. 6

– recursive – 2018-03-17T00:02:26.263

0

jq, score 60

(40 characters code + 3 characters command line option)

[./""|group_by(.)[]|range(length+1)]|add

Sample run:

bash-4.4$ jq -R '[./""|group_by(.)[]|range(length+1)]|add' <<< 'Programming Puzzles & Code Golf'
47

Try it online!

jq, score 63

[./""|group_by(.)[]|range(length+1)]|add+0

In case the result for empty string must be numeric 0. There are a few other solutions that use alternative representation of nothing.

manatwork

Posted 2017-06-19T16:51:53.083

Reputation: 17 865

0

Kotlin, score 93

{it.foldIndexed(0){z,q,v->q+it.take(z+1).count{it==v}}}

Try it online!

snail_

Posted 2017-06-19T16:51:53.083

Reputation: 1 982

0

Reticular, score 56

iSd:A=>ddV@c~dc$:A=+:A`L0EQ6jj+1*37_$O;

Try it online!

Wisław

Posted 2017-06-19T16:51:53.083

Reputation: 554

0

Perl 6, Score: 34

{sum [\+](^∞)[.comb.Bag{*}]}

Try it online!

Takes advantage of the unicode operator to save on characters.

Explanation

{                          }  # Anonymous code block
              .comb           # Split the input string into characters
                   .Bag{*}    # Get the count of each character
             [            ]   # And inded each into
         (^∞)                 # The infinite list of integers
     [\+]                     # Triangularly summed (0,0+1,0+1+2...)
 sum                          # And return the sum total

Jo King

Posted 2017-06-19T16:51:53.083

Reputation: 38 234

0

Zsh, 36 bytes, score 52

for	p (${(s..)1})$[j+=++a[#p]]
<<<$j

Try it online!

One tab, one space, one newline. This will fill up the debug log with "command not found". If that must be avoided, 38 bytes, score 55.

GammaFunction

Posted 2017-06-19T16:51:53.083

Reputation: 2 838

0

05AB1E (legacy), score: 4 (4 bytes)

Ù¢LO

Input as a list of characters.

Try it online or verify all test cases.

Explanation:

Ù     # Get all unique characters of the (implicit) input-list
 ¢    # For each, count the amount of times it occurs in the (implicit) input-list
  L   # Create a list of each of these counts
      # (which implicitly flattens in the legacy version of 05AB1E)
   O  # Take the sum of all those integers
      # (which is output implicitly as result)

Kevin Cruijssen

Posted 2017-06-19T16:51:53.083

Reputation: 67 575

0

Haskell, 150 133 points

(79 75 bytes)

import Data.List
c=foldr(\x->	\y->y+(x*(x+1)`div`2))0.map length.group.sort

Try it online!

  • -17 points by removing some parentheses (thanks to @Laikoni)

Sara J

Posted 2017-06-19T16:51:53.083

Reputation: 2 576

1You can drop the parenthesis around the foldr expression and just write map length instead of (map$length) for a score of 133. – Laikoni – 2019-09-05T10:15:59.300

0

Gaia, score: 11

$:uC¦ₔ┅¦_Σ

Try it online!

For some reason, _ is necessary else this spits out garbage answers. But the language is defined by its implementation, so what are ya gonna do.

$		| split into characters
 :		| dup
  u		| get unique
   C¦ₔ		| get counts of uniques into original
      ┅¦	| sequence: 1..count
        _Σ	| sum

Giuseppe

Posted 2017-06-19T16:51:53.083

Reputation: 21 077