93
\$\begingroup\$

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>

\$\endgroup\$
  • 2
    \$\begingroup\$ How 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? \$\endgroup\$ – Value Ink Jun 19 '17 at 20:20
  • 2
    \$\begingroup\$ @ValueInk Yes, I think counting the n is the fairest option. \$\endgroup\$ – Laikoni Jun 19 '17 at 20:34
  • 1
    \$\begingroup\$ I really wish there was a brainfuck solution to this challenge. \$\endgroup\$ – Peter1807 Jun 21 '17 at 12:16
  • 10
    \$\begingroup\$ +1 for The score of your submission is the cost of your code \$\endgroup\$ – luizfzs Jun 22 '17 at 15:21
  • 1
    \$\begingroup\$ cost 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 \$\endgroup\$ – undergroundmonorail Jan 19 '18 at 19:33

83 Answers 83

2
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ You might be able to change this to use one of the many binary-encoded brainfuck dialects that exist to lower your score... \$\endgroup\$ – Esolanging Fruit Jan 19 '18 at 5:22
  • \$\begingroup\$ CompressedFuck looks promising. \$\endgroup\$ – Esolanging Fruit Jan 19 '18 at 5:26
  • 2
    \$\begingroup\$ @EsolangingFruit That's like saying switching to Jelly may save some bytes on your Java answer... :P \$\endgroup\$ – Conor O'Brien Jan 19 '18 at 22:45
  • 2
    \$\begingroup\$ @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. \$\endgroup\$ – Esolanging Fruit Jan 20 '18 at 0:17
2
\$\begingroup\$

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)
\$\endgroup\$
  • \$\begingroup\$ You can do Ṡṁ# instead of (Σ´×= for a score of 7. \$\endgroup\$ – Zgarb Mar 17 '18 at 11:37
2
\$\begingroup\$

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

\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to PPCG! In this challenge the score of your submission is the cost of your code, which I think is 1459. \$\endgroup\$ – Laikoni Mar 15 '18 at 13:26
  • \$\begingroup\$ Edited. Thanks for pointing that out \$\endgroup\$ – dragonite44 Mar 15 '18 at 13:32
  • 2
    \$\begingroup\$ This also means you can improve your score quite a bit by choosing characters as variable names which are not already contained in other keywords. \$\endgroup\$ – Laikoni Mar 15 '18 at 13:34
  • 2
    \$\begingroup\$ You're still using a lot of variable names that are characters used elsewhere. jkqvxz and most capitals are unused and would improve the score. \$\endgroup\$ – Ørjan Johansen Mar 16 '18 at 10:19
2
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – Kevin Cruijssen Mar 21 '18 at 15:00
  • \$\begingroup\$ @KevinCruijssen Thanks, Changed! \$\endgroup\$ – sonrad10 Mar 21 '18 at 15:11
  • 1
    \$\begingroup\$ Try it online! link \$\endgroup\$ – Ørjan Johansen Mar 21 '18 at 17:51
2
\$\begingroup\$

Japt -x, 9 7 points

å+ ®èZÌ

Try it

\$\endgroup\$
  • 2
    \$\begingroup\$ Not that hard to optimise for score when you can solve it using entirely unique characters, huh :P \$\endgroup\$ – ETHproductions Jan 22 '18 at 15:45
2
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

Clojure, score 96

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

Five spaces and pairs of brackets...

\$\endgroup\$
1
\$\begingroup\$

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

\$\endgroup\$
1
\$\begingroup\$

J, score 23

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

Try it online!

\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
  • 1
    \$\begingroup\$ Same method, score 11: 1⊥{+/⍳≢⍵}⌸⍞ \$\endgroup\$ – Adám Jun 19 '17 at 17:55
  • \$\begingroup\$ @Adám Thanks, the 1⊥ trick is really neat \$\endgroup\$ – Kritixi Lithos Jun 20 '17 at 8:36
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – Laikoni Jun 20 '17 at 14:44
1
\$\begingroup\$

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!

\$\endgroup\$
  • \$\begingroup\$ You could probably save a point by ditching the semicolon. Couldn't test it as it doesn't seem to work with TIO. \$\endgroup\$ – Tom Carpenter Jun 21 '17 at 22:05
  • \$\begingroup\$ @TomCarpenter Without ; doesn't work. however such a lambda cab be used in arrayfun. \$\endgroup\$ – rahnema1 Jun 22 '17 at 2:55
1
\$\begingroup\$

AWK, 39 bytes, Score 54

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

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Changing S to some unused character reduces the score by two. \$\endgroup\$ – Laikoni Jun 21 '17 at 21:45
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ – Laikoni Jun 22 '17 at 21:33
  • \$\begingroup\$ @Laikoni Thanks! I forgot to add a short explanation, my bad. I will do it later, in case anyone is interested. \$\endgroup\$ – Filipe Santos Jun 22 '17 at 22:17
  • \$\begingroup\$ 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. \$\endgroup\$ – Laikoni Jun 23 '17 at 6:03
  • \$\begingroup\$ 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. \$\endgroup\$ – Filipe Santos Jun 23 '17 at 11:17
1
\$\begingroup\$

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 
\$\endgroup\$
1
\$\begingroup\$

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 ^)
\$\endgroup\$
1
\$\begingroup\$

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)

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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.
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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>

\$\endgroup\$
1
\$\begingroup\$

Python 3, score 89 85

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

Try it online!

\$\endgroup\$
  • \$\begingroup\$ @ETHproductions thanks a lot. \$\endgroup\$ – ovs Jan 22 '18 at 18:59
1
+500
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ In this challenge, the score of your submission is the cost of your code which I think is 75. \$\endgroup\$ – Giuseppe Mar 15 '18 at 14:18
1
\$\begingroup\$

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

\$\endgroup\$
1
\$\begingroup\$

Ruby, score: 38

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

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.