g | x | w | all
Bytes Lang Time Link
083JavaScript Node.js250502T063519ZSteve Be
095Juby250501T222148ZJordan
087Swift 6250501T211356ZmacOSist
006Japt x180120T102552ZShaggy
058JavaScript180122T111919ZShaggy
010APL Dyalog170619T171224Zuser4180
104Factor + grouping.extras math.unicode220220T222312Zchunes
005Husk220220T144359ZDominic
042Mathematica170619T173825ZZaMoC
141Excel VBA Immediate Window220212T170641ZAxuary
206Excel220212T170308ZAxuary
193C++ gcc190427T233410Zmovatica
010Gaia190905T171858ZGiuseppe
004BQN220117T090810Zovs
006Husk220117T083156ZNatte
008Pyth220117T075537Zhakr14
003Vyxal d220117T064546Zemanresu
087JavaScript210926T060615Zl4m2
133Haskell190904T165136ZSara J
036Zsh190904T035912ZGammaFun
04405AB1E legacy190904T075552ZKevin Cr
091C gcc170619T165726ZSteadybo
034Perl 6190427T003809ZJo King
133JavaScript190428T025051ZNaruyoko
681SNOBOL4 CSNOBOL4180123T194733ZGiuseppe
056Reticular190103T155923ZWisław
118F#180921T143628ZCiaran_M
093Kotlin180921T190054Zsnail_
100Java 10170914T125039ZKevin Cr
067SHELL180317T032755ZAli ISSA
115Python 2. Score180321T144535ZAvahW
349R180317T153203ZRiccardo
006Stax180315T081051ZWeijun Z
nanRust180315T132107Zdragonit
060C180317T194746ZErikF
038Ruby180317T142916ZAsone Tu
009Husk180316T222917ZSophia L
045Julia 0.6180314T152017Zniczky12
060jq180316T100631Zmanatwor
033><>180315T163430ZSok
045Perl6/Rakudo180315T141609ZPhil H
044PHP180315T124343ZTitus
066Standard ML180306T222514ZLaikoni
049 JavaScript170717T114143ZC5H8NNaO
007Jelly180123T012541Zellie
085Python 3170619T170405Zovs
015K4180120T084921Zmkst
308MSSQL180119T192817ZBradC
580TSQL170619T195542ZBradC
036Attache180119T140251ZConor O&
897brainfuck180119T031213ZJo King
nanJapt180118T200436ZOliver
014J180118T202850Zcole
006Pyt180118T194626Zmudkip20
067R170619T194909ZMickyT
011J180118T174857ZFrownyFr
009Jelly170918T132327ZJ. Sall&
007Pyke170915T185941ZBlue
2435Factor170718T000655ZQuelklef
019K/Kona170717T122001ZSimon Ma
222Common Lisp170619T210217ZRenzo
3577FIREBIRD170622T172836ZFilipe S
039AWK170621T180135ZRobert B
133><> Fish170622T131853ZThijs te
018CJam170622T133212ZBusiness
064PowerShell170622T064548ZTessella
153Swift 3170622T064226ZArchmage
031Octave170619T173139Zrahnema1
039Octave170621T221352ZTom Carp
060Ruby170619T202429ZValue In
083Perl 5 score170620T210902Zuser1937
1110F#170620T122006ZHorv
016J170619T194517ZZgarb
023J170619T181033ZLeaky Nu
006Pyth170619T180016ZLeaky Nu
012Actually170620T025526Zuser4594
045PHP170619T221329ZJör
043Retina170619T173701ZNeil
049Python170619T171247Zxnor
005Jelly170619T165829ZErik the
004MATL170619T183707ZLuis Men
128QBIC170619T195523Zsteenber
034Retina170619T180125ZMartin E
209C# .NET Core170619T191834ZCharlie
096Clojure170619T190629ZNikoNyrh
108Python 2170619T173102ZDaniel
068JavaScript Firefox 30+170619T185518ZETHprodu
006Jelly170619T170224ZLeaky Nu
042Haskell170619T175127Zxnor
051Haskell170619T172312Znimi
nan170619T174348ZBrad Gil
015APL Dyalog170619T173617ZAdá
083Python 2170619T171536Zmbomb007
078JavaScript ES6170619T170224ZETHprodu
00605AB1E170619T170546ZErik the

JavaScript (Node.js), score 83

a=>a.split``.reduce((x,y)=>x+(z[y]=~~z[y]+1),0,z={})

Try it online!

J-uby, score: 95

A|:sort|:slice_when+:!=|:*&(:+@|:+|s=:sum)|s

Attempt This Online!

Swift 6, score: 87

var U={X in(X+"").reduce(0){A,C
in  A+1+X.count{$0==C}}/2}

The first space (between var and U) is a Unicode non-breaking space (U+00A0); the one between X and in is a normal space; the one between A,C and in is a newline; and the one between in and A+1 is a tab.

Try it on SwiftFiddle!

Japt -x, 9 7 6 points

ü mÊcõ

Try it

JavaScript, 112 95 58 points

A=>A.map(C=>N+=A[C]=-~A[C],N=0)|N

Try it online!

APL (Dyalog), score 27 18 11 10

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

Reduced score by 1 thanks to @rabbitgrowth by using a function instead

1⊥{+/⍳≢⍵}⌸

Try it online!

Factor + grouping.extras math.unicode, score: 104

[ head-clump
[ dup
last '[
_ =
] count
] map
Σ ]

Try it online!

The whitespace is a killer. In order to lessen its impact, I alternate between spaces and newlines. Tabs aren't allowed in TIO's build of Factor or I would have used them too.

Husk, 5 bytes, score 5

ΣṁŀgO

Try it online!

Different and (so far) shorter strategy to Natte's or Sophia Lechner's Husk answers.

    O   # sort the input
   g    # and group equal adjacent values;
 ṁ      # now, for each group
  ŀ     # make a range 1..length of the group
 ṁ      # and flatten all the ranges into one list;
Σ       # then output the sum

Mathematica, score 42

Total[#^2+#].5&@*CharacterCounts

input

["abcdefg"]

thanks to hftf
thanks to att

Excel VBA Immediate Window, Score 159 141

-18 byte thank to @TaylorRaine

FOR I=1TO[len(b3)]:for J=1to i:Y=Y-(MID([B3],i,1)=mid([B3],j,1)):NEXT:next:?y

The mixed case reduces the score by 30.

Excel, Score: 206

G4 =MID(B3,SEQUENCE(LEN(B3)),1)
C3 =IF(B3<>"",SUM(EXACT(G4#,TRANSPOSE(G4#))/2)+ROWS(G4#)/2,)

Link to Spreadsheet

C++ (gcc), Score: 209 196 193

98 96 bytes

-3 thanx to l4m2

#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:

Common tricks:

Try it online!

Gaia, score: 11 10

$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. Without the _, one of the sublists generated by ┅¦is [1 2] which is converted to 12 by Σ.

$		| split into characters
 		| 
  u		| get unique
   C¦ₔ		| implicitly copy original input; get counts of uniques into original
      ┅¦	| sequence: 1..count
        _Σ	| flatten and sum

BQN, Score: 4

≠+´⊒

Run online!

The occurrence count builtin calculates the cost of each character decremented by 1. To adjust for that we can either add 1 to each cost or add the length to the sum. The latter turns out to be a byte shorter.

Husk, Score: 6

ṁoΣ#¹u

Try it online!

Explanation

ṁoΣ#¹u   translates to ṁoΣ#⁰u⁰
ṁ    u⁰  map following function on unique input and then sum
 o       composed function
   #⁰    count occurrences in input
  Σ      triangular number

Pyth, 8 bytes, Score: 9

ssSM/LQ{

Test suite

Explanation
ssSM/LQ{  | Full code
ssSM/LQ{Q | with implicit variables filled
----------+-------------------------------
     L {Q | Map over deduplicated input:
    /LQ   |  count in input
  SM      | Map: to [1...N]
 s        | Flatten
s         | Sum

ss can be replaced with s.n for an identical score with no repeat bytes, at the cost of being one byte longer.

Vyxal d, 3 bytes

Ċɾ⌊

Try it Online!

Ċ   # Counts of each element within itself
 ɾ  # Convert each value to 1...n
  ⌊ # Parse each to integer, zeroes element values
    # (d flag) take the deep sum

JavaScript, 87 score

A=([B,...C],Z=0)=>B?C.map(D=>D!=B||Z++)^A(C)-~Z:0

Try it online!

C.map(D=>D!=B||Z++) is either empty, 0, true or something with a ,, making it never show value to ^

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!

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.

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)

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!

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

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

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!

Reticular, score 56

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

Try it online!

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.

Kotlin, score 93

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

Try it online!

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

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

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

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

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

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

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.

Ruby, score: 38

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

Try it online!

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)

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.

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.

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

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.

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

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.

JavaScript, 49 bytes, score 88

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

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!

Python 3, score 89 85

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

Try it online!

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

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.

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.

Attache, score 36

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

Try it online!

Explanation

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

This is a composition of 3 functions:

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

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!

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.

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!

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.

J, score: 14 12 11

$+/@,2!1#.=

Try it online!

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)

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

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.

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 

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

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.

AWK, 39 bytes, Score 54

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

Try it online!

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

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

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

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

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!

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!

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.

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!

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

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.

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.

J, score 23

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

Try it online!

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.

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

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!

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.

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:

Jelly, score 5

ĠJ€ẎS

Try it online!

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

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

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

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.

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;

Clojure, score 96

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

Five spaces and pairs of brackets...

Python 2, score 108

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

Still golfing :)

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.

Jelly, score 6

;\ċ"⁸S

Try it online!

Haskell, score 42

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

Try it online!

Anonymizing \l-> gives the same score.

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.

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

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

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.

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

05AB1E, score 6

{γ€gLO

Try it online!