独特就是便宜


93

编写确定给定字符串成本的函数或程序,其中

  • 每个字符的成本等于字符在字符串中到目前为止发生了多少次,并且
  • 字符串的成本是其字符成本的总和。

对于的输入abaacab,成本计算如下:

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

因此,字符串的成本为abaacab14。

规则

  • 您提交的分数是你的代码的成本如上定义,那就是你的提交上自己的源代码的运行,具有较低的分数更好。
  • 您的提交应适用于包含可打印ASCII字符以及提交中使用的所有字符的字符串。
  • 文字是大小写敏感的,这是aA不同的字符。

测试用例

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

排行榜


2
诸如-nPerl的程序标志如何计入分数?传统上,它计数为1个字节,因为标准perl -e和之间的编辑距离perl -ne为1,但是对于这一挑战,n计数是否会用于计数重复项?
价值墨水

2
@ValueInk是的,我认为对进行计数n是最公平的选择。
Laikoni

1
我真的希望有一个解决这个难题的办法。
Peter1807

10
+1代表提交的分数就是代码的成本
luizfzs

1
角色的费用定义为how often this character has already occurred in the string,我可能会更改为how many times the character has occurred up to this point更清楚地表明第一次使用的费用为1,而不是0
地下

Answers:


83

MATL,得分4

&=Rz

在线尝试!

说明

以输入'ABBA'为例。

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

14
您是线性代数教授吗?
Magic Octopus Urn

4
@carusocomputing实际上是一位移动通信教授。我使用矩阵的趋势来自在Matlab中多年的编程工作
Luis Mendo

整齐!Matlab在那个地区大吗?我从未真正研究过GSM或类似技术。
Magic Octopus Urn

2
我加入这个社区只是为了向您推荐这个出色的解决方案!
Wboy

1
通常,@ carusocomputing Matlab是工程中非常常用的工具/语言。它擅长数值计算:线性代数,信号处理等。而且作为一种解释语言,它非常易于使用
Luis Mendo

17

Python,得分49

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

在线尝试!

后面有一个标签in

分数细分:

  • +27表示27个独特字符
  • +16表示8个双字符: ()Camnou
  • +6表示1个三字符: S

13
使用制表符而不是空格来保存字节。
mbomb007'6

1
@ mbomb007只是有相同的想法:-)
xnor

1
@ mbomb007哈哈,这是个天才的把戏:-)
ETHproductions

14
@ mbomb007只是高尔夫代码中的选项卡与空间之战
Erik the Outgolfer

2
我本来建议使用换页(Python语法中也允许使用空格),但是您没有其他要替换的空格。
user2357112 '17

8

T-SQL,得分775579!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

编辑:删除了几个变量,压缩了一些。减少到16个@符号而不是22 个符号,这本身使我的得分降低了117点!

不错的比赛,除了总字符数外,我喜欢对某些内容进行优化的要求。

根据我们的IO规则,输入是通过预先存在的表z中的 varchar字段q进行的。包含此输入表的数据库必须设置为区分大小写的排序规则

格式:

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

SQL关键字不区分大小写,所以我用大小写混合,以尽量减少重复的字母(计数AAAA产生比一个更好的/降低分数AAAA)。

主循环比较剥离第一个字符的所有实例前后的长度。差值n *(n + 1)/ 2被加到运行总计中。

SQL LEN()函数烦人地忽略了尾随空格,因此我不得不附加一个控制字符并在末尾减去1。

编辑:修正了我自己的分数错误计算2分(带引号的问题),通过更改1的大小写减少了1的错误R。我还将制定一种完全不同的策略,将其作为自己的答案。


3
起初我以为你的成绩是579! ≈ 8.22 x 10^1349
Engineer Toast

8

C(GCC) ,得分: 113  103 100   96  91

感谢@ ugoren,@ CalculatorFeline,@ gastropner,@ l4m2和@ JS1的提示。

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

初始化一个零数组,然后使用字符串中字符的ASCII值作为该数组的索引,以跟踪字符串中每个字符的实例数。

在线尝试!


3
建议:使用未在关键字中使用的变量名,比如zxc
CalculatorFeline

@CalculatorFeline char包括c...
尼尔(Neil)

3
此外,您只需要127个元素的数组(\x7f不可打印),请添加说明。
CalculatorFeline

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

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

7

JavaScript(ES6),得分81 78

@Arnauld节省了3分

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

我原来的得分81递归解决方案:

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



7

视网膜得分34

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

在线尝试!

说明

s(O`.

我们首先对输入中的所有字符进行排序,以便将相同的字符分组为一个单次运行。该s(激活所有阶段的单线模式(即使.匹配换行符)。

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

目标是将n个字符转换为T n个字符(第n个三角数),因为这是该字符出现的分数。为此,我们找到了重叠的匹配项。特别是,对于每一个[1,N] ,我们将包括I-1在比赛中的字符。由于标志重叠,我们得到了所有这些匹配项&。仅从比赛中就得出n *(n-1)/ 2 = T n-1 = T n -n个字符。但是比赛阶段会将这些与换行符一起使用,换行符为n 换行符火柴。只有一个问题。最后一场比赛之后将没有换行符,因此输出中的字符总数比我们需要的少了一个。我们也通过匹配输入的开头来解决此问题,如果至少存在其他匹配项,则这将给我们提供单个前导换行符。

.

最后,我们只计算字符串中有多少个字符。


6

Haskell,得分52 51

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

f和之间有一个标签_

在线尝试!

空字符串的值为0。字符串s的值(其中a是第一个字符,b字符串的其余部分为1)加上ain 的出现b以及使用b的递归调用。


5

Ĵ,得分16

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

在线尝试!

说明

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

1#.代替+/@总和可以节省一些点,&也可以代替@单子节省更多。重复的操作使1我付出了额外的一点,但我一直无法摆脱。


“稍后” 等待一个四分之一天
CalculatorFeline

2
@CalculatorFeline 10小时后仍然是更晚。:P
Zgarb

让我们现在就开始吧。
CalculatorFeline

我个人使用这种格式的TIO的答案,以反映该代码段准确的字节数,也许你会想用它
康纳尔奥布莱恩

5

R,得分:67 83 95 128

-61感谢Giuseppe的重要提示

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

在线尝试!

使用拆分字符串,utf8ToInt并计算每个ascii值table。通过对%*%自身+1 进行矩阵乘法,最后将结果对半,计算出结果。


table代替rle; 您也可以摆脱sort(也不必索引[[1]]的结果strsplit
朱塞佩

@Giuseppe非常感谢。我什至没有想到表,很快就会合并。
MickyT

2
我认为您可以通过使用其他变量名称代替n(因为它是function两次)来节省更多字节,并且还可以更改(n+1){n+1}
Giuseppe

得分:67。在此方面的一些变化可能使得可以进一步降低分数。
朱塞佩

@Giuseppe ...我应该重新阅读它。哎呦
MickyT


4

佩斯得分6

1字节感谢isaacg。

+F/V._

测试套件。

这个怎么运作

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

s+0与相同+F
isaacg

好!我能做的最好的是usaShHGrScQ1 8Z16岁。您能添加一个解释吗?
Digital Trauma'6

1
@DigitalTrauma我添加了一个解释。
Leaky Nun

s/LQ是得分4,这是否使用了挑战后的功能?
戴夫


4

果冻,得分7

ċЀQRFS

说明:

   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)

在线尝试!


2
欢迎来到PPCG!
Laikoni '18

4

C,60字节,得分108 95

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

在线尝试!

通常,递增前后的运算符非常适合于代码编程,但是在这一挑战中他们确实受伤了!

编辑:通过减去负数而不是增加正数,我节省了一大堆分数。更换for()while()淘汰分号为好。



3

C#(.NET Core),得分∞(我的意思是,209)

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

在线尝试!

分数包括:

using System.Linq;

我知道已经有一段时间了,但是您可以更改return w*(w+1)/2return-~w*w/2(得分196)。编辑:您可以为我的Java 8答案创建一个端口,得分为149using System.Linq;b=>{int[]x=new int[256];return\nb.Select(z=>++x[z]).Sum();} 在线尝试。
凯文·克鲁伊森

1
@KevinCruijssen:我的解决方案得分为111:b=>{var x=new int[256];return\nb.Sum(z=>++x[z]);}
raznagul

@raznagul(*半年前响应传入*109(如果将第二个空格更改为选项卡)。;)在线尝试。
凯文·克鲁伊森

1
@KevinCruijssen(另一半岁的响应传入)使用交互式编译器49,我认为它永远不会低于48。我发现奇怪的是,C#答案越多,它们似乎总是变得更具可读性。在线尝试!
某人


3

PowerShell,得分64

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

(分数基于单个换行符,这不是Windows标准,但可以在PS中使用)。

PS C:\> D:\unique-is-cheap.ps1 (gc D:\unique-is-cheap.ps1 -raw)
64
  • 哈希表柜台 @{}
  • 遍历字母;$args是一个参数数组-在这种情况下,输入字符串使它成为单个项目数组;|%在项目上进行foreach循环,并使用getE*快捷方式匹配GetEnumerator()string方法并调用它以将字符串转换为字符流。
  • |%遍历字符并增加其哈希表条目,将其添加到运行总计中。($x+=1)带有parens 的表单既修改变量,又输出新值供使用。
  • 输出运行总计。

(当我第一次写它时,它$c=@{};$t=0;[char[]]"$args"|%{$c[$_]++;$t+=$c[$_]};$t的分数是128,感觉不会降低很多。将其减半到64是非常令人愉快的)。


1
61 pts / 38字节,弄乱了增量
Veskah


3

朱莉娅0.6,45个字节,得分:77

受到MATL解决方案的启发:

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

在线尝试!

一个不太漂亮的解决方案,使用计数:

朱莉娅0.6,得分:82

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

在线尝试!

感谢Guiseppe指出得分和提示。这些评论帮助我加载。


1
您提交的分数是代码的成本,我认为这是135。–
Giuseppe

1
我不太了解Julia,但我认为您可以通过切换一些变量名并删除一组括号将分数降低到110。如果允许返回单元素向量,则可以替换(x+1)[x+1]以进一步降低分数。
朱塞佩

您可以通过将第二个空格更改为制表符或换行符来保存分数:score 104。@Giuseppe提示使用[x+1]而不是(x+1)将其降低到98分
凯文·克鲁伊森

3

爪哇10,分数:149 138 137 134 133 130 103 102 101 100

字节:72 73 74 75 64 62 61字节增加,但是得分降低。:D

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

感谢@Nevay,得分-28(和-11字节)。
由于@OlivierGrégoire,得分为-1(和-2字节)。
通过将Java 8转换为Java 10来获得-1分(和-1个字节)。

说明:

在这里尝试。

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

1
~如果使用j=0和,则可以删除return-j;(133)。
Nevay

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

1
@Nevay 103实际上,当我使用j代替ureturncontains u)和换行符和制表符代替空格时。编辑:呵呵,我发表评论时,您已经正确编辑了。:)
Kevin Cruijssen

3

F#,得分120 118

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

-2感谢Kevin Cruijssen

在线尝试!

以a string作为输入。Seq.countBy将每个不同的字符与其计数配对(id是身份函数),因此最终得到一个类似'a' = 4, 'b' = 2etc 的集合。

Seq.sumBy取计数每一个字母和总结所有的数字0到计数那封信。因此,如果'a' = 4将集合加0, 1, 2, 3, 4在一起就是10。然后Seq.sumBy将所有这些总计。


2
您可以通过将更let q改为来将分数降低2 let j,因为q两者都已使用Seq
凯文·克鲁伊森

2

APL(Dyalog),得分15

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

在线尝试!

 获取文字输入

∘.=⍨ 自我平等表

+\ 累计总和

1 1⍉ 对角线(将两个维度折叠为一维)

+/ 和


2

视网膜得分68 45 43

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

在线尝试!链接显示得分。编辑:感谢@MartinEnder,他使用重叠匹配而不是超前方式节省了20个字节,并且通过对阶段进行分组又节省了三个字节,因此该s标志只需要应用一次。通过不同地计算三角数,节省了另外两个字节,从而避免了排序。



2

Perl 5得分91 83

使用-p因p拆分而加2 的标志。

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

欢迎来到PPCG!
Laikoni

1
以您的答案为基础并从提示页面应用一些技巧,我设法将您的分数降低到31:在线尝试!$` is automatically print ed after each call so we can use that to store the score and /./ g`返回所有字符的列表,该列表$_比便宜split//
Dom Hastings

我知道这是一个古老的挑战,但是您可以进一步降低分数:在线尝试!
Xcali

2

八度,39字节,得分69

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

在线尝试!

虽然还有另一个八度音阶答案,但这完全是我自己的,并且是另一种方法,而且得分更低:)。

该方法归结为首先找到每个唯一字符的计数(b),这是使用直方图函数实现的。然后,对于每个元素,我们使用公式计算1到b的总和(b*(b+1))/2。然后将各个总和加到最终分数中。

在测试中,方括号似乎在得分上确实很昂贵,因为需要很多。我通过重新安排问题以最大程度地减少了开括号的数量,从最初的88分左右进行了优化-因此,我们现在对最终总数而不是单独进行/ 2运算,并且将公式修改为(b^2+b)/2因为这需要更少的括号。


1
不幸的是,这似乎在空字符串上失败:error: hist: subscript indices must be either positive integers less than 2^31 or logicals
Laikoni

2

Common Lisp的,得分286 232 222

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

Common Lisp内置运算符的冗长语法带来的高分。

在线尝试!

取消编码:

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

2

Mathematica,得分54

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

输入

[“ abcdefg”]

感谢hftf


Total[#(#+1)/2&@Counts@Characters@#]&得分
54。– hftf
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.