{卷数};


33

在深奥的编程语言Curly中,程序仅由花括号{}和分号组成;。尽管使用了不起眼的工具集,但是Curly的文字可以表示任何非负整数。但是,对于初学者来说,格式有点难读,所以让我们写一些代码为我们做转换。

数字格式

卷曲数是根据以下规则构造的:

  1. 添加分号会将数字加1。
  2. 用大括号括起来的数字乘以4。
  3. 花括号组可以嵌套但不能串联。大括号必须正确匹配。
  4. 一组花括号外的分号必须在之后,而不是之前。
  5. 为避免在分析时产生歧义,数字必须始终以大括号开头。

一些例子:

{;;}     2*4 = 8
{{;};};  (1*4+1)*4+1 = 21
{};;;    0*4+3 = 3

(请注意,规则5表示数字0到3必须以一对空的花括号开头。)

还有一些无效的例子:

{{;}{;;}}  Curly brace groups side-by-side, not nested
{;}}       Unmatched brace
{;{;}}     Semicolon before curly-brace group
;;;        Number does not start with curly brace

这是卷曲数字的BNF语法:

<number> ::= "{" <inner> "}" <semis>
<inner>  ::= <semis>
           | <number>
<semis>  ::= ";" <semis>
           | ""

{;;;;}(连续超过3个分号)或{{};}(不必要的空括号组)之类的数字称为不正确的 Curly数字。他们遵守上面的语法,并且可以以通常的方式进行评价,但它们也能够缩短表示的(对于上述实例中,{{;}}{;}分别地)。

挑战

编写一个输入或接收字符串的程序或函数。如果字符串是非负十进制整数,则输出/返回该整数的正确(即,最短的)卷曲表示形式。如果字符串是Curly数字,则输出/返回其十进制表示形式。

可以通过STDIN,命令行参数或函数参数接收输入。它必须是一个字符串。也就是说,您可能无法编写一个函数,该函数接受用于Curly数字的字符串,但接受用于十进制数字的整数。

输出可以打印到STDOUT或从函数返回。一个功能可能在适当的时候返回整数,或者在所有情况下都可以返回字符串。

您的程序不必处理错误的输入(违反格式规则的弯曲数字,浮点数,负整数,随机文本),并且它不需要需要处理不当卷毛号(见下文)。输入将仅包含可打印的ASCII字符。

计分

以字节为单位的最短代码获胜。如果您的程序可以执行以下两项操作

  1. 正确处理不正确的Curly数字,并且
  2. 当给定一个Curly数字时,请忽略所有多余的字符 {};

然后从您的分数中减去10%。(即使有奖励,整数输入也不会有多余的字符。)

测试用例

Input       Output
{;;}        8
{{;};};     21
{};;;       3
{{{{;}}};}  260
{}          0
4           {;}
17          {{;}};
1           {};
0           {}
96          {{{;};;}}

对于奖金:

{};;;;;     5
{{;;;;};;}  72
c{u;r;l}y;! 9
42{;} ;;;;  8

注意:尚未实现Curly。但是,如果这个问题解决得当,我可能会进一步发展。


如果没有匹配的括号,应该如何处理大小写?还是我认为它永远不会发生?
user902383 2015年

@ user902383您可以假设不匹配的花括号将永远不会发生。
DLosc 2015年

2
我打算制作一个Retina解决方案,但是在使它处理Curly字符串(仅20个字节)之后,我意识到它还需要处理正整数-> Curly,所以我放弃了。
mbomb007'9

@DLosc是的,它不会赢,所以我不会花时间。
mbomb007'9

@ mbomb007我的意思是专门针对这个问题,Pyth解决方案已经比最短的CJam解决方案短22%,并且有资格获得奖金。无论如何,这是一个口头上的问题,试图说:“不,但是它仍然很有趣并且获得了一些赞誉。” 但是,如果您不同意“有趣”部分,那很好。
DLosc

Answers:


15

Pyth,35 32字节-10%= 28.8

.x.U+jb`HZ*R\;.[Z2jsz4i/R\;cz\}4

在线尝试:演示测试套件

编辑:事实证明,我不小心也可以处理不正确的Curly Number。根本没有计划。;-)

说明:

代码中有两个表达式。第一个将一个数字转换为一个Curly Number,第二个一个将一个Curly Number转换为一个常规数字。.x句柄,哪个表达式被打印出来。它将尝试打印第一个表达式。如果输入中有任何非数字,则第一个表达式失败(通过Exception)。.x捕获异常并打印第二个异常。

.U+jb`HZ*R\;.[Z2jsz4   # number to Curly Number
                 sz    read the input and converts it to an int
                j  4   convert to base 4
            .[Z2       pad zeros on the left, until length is >= 2
        *R\;           convert each digit to ";"s
                       lets call this list of ";"s Y
.U                     reduce this list, start with b=Y[0], 
                       Z iterates over Y[1], Y[2], ..., 
                       update b in each step with:
   jb`H                   put b into curly brackets
  +    Z                  and append Z

i/R\;cz\}4             # Curly Number to regular number
     cz\}              split the input by "}"
 /R\;                  count the ";"s in each string
i        4             convert this list from base 4 to base 10

2
在西部:(我有这个确切的解决方案,除了我忘记了最快的枪.[Z2,是必要的
orlp

12

CJam,51 47 44 41字节

r_'{-_@={i4bYUe[';f*{{}s@*\+}*}{'}/:,4b}?

在线尝试:样品运行 | 测试套件

怎么运行的

r        e# Read a token from STDIN.
_'{-     e# Remove all left curly brackets from a copy of the token.
_@       e# Copy the modified token and rotate the original on top of it.
=        e# Check for equality.
{        e# If the strings were equal:
  i4b    e#   Convert to integer, then to base 4.
  YUe[   e#   Left-pad the resulting array with zeroes to a length of 2.
  ';f*   e#   Replace each digit with that many semicolons.
  {      e#   For each string of semicolons but the first:
    {}s  e#     Push the string "{}".
    @    e#     Rotate the first string or the result of the previous 
         e#     iteration on top of the stack.
    *    e#     Join, i.e., surround the string with curly brackets.
    \+   e#     Append the current string of semicolons to the result.
  }*     e#
}{       e# Else:
  '}/    e#   Split the modified input at right curly brackets.
  :,     e#   Replace each run of 0 to 3 semicolons by its length.
  4b     e#   Convert from base 4 to integer.
}?       e#

7

Python 2,167个字节-10%= 150.3

d=lambda x:("{"+d(x//4)+"}"if x>3 else"")+";"*(x%4)
c=lambda n:"{}"*(int(n)<4)+d(int(n))if n.isdigit()else reduce(lambda x,y:x*4+y,[x.count(";")for x in n.split("}")])

在此实现中,c是满足要求的功能。如果输入为非负整数,则返回一个字符串;如果输入为卷曲数,则返回一个整数。


6

Python 266字节-10%= 1268.1 326.7 239.4字节

男孩我不是一个代码高尔夫球手尚未= /,但10%的帮出了很多的时候我的成绩依然超过1000!

我在这里有一个完整的(和冗长的)代码版本它将识别卷积数字的有效性,并提供一个循环接口以输入数字进行测试。

(评论只是为了澄清)

实际查看此代码

def c(t):                           # curly to int function
 v=0                                #  int value of input
 for a in t:                        #  for each character of input
  if a==';':v+=1                    #   if you find a ';', add one to total
  if a=='}':v*=4                    #   if you find a '}', multiply total by 4
 print v                            #  print value
def i(t):                           # int to curly function
 v=int(t);f,b="{}"if v<4 else"",""  #  get integer value. initialize front (f) and back (b) strings
 while 1:                           #  loop until stopped
  r,v=v%4,int(v/4)                  #   get remainder of v/4 and int value of v/4
  if r>0:b=';'*r+b                  #   if remainder exists, prepend that many ';' to back string
  if v>0:f=f+'{';b='}'+b            #   if remaining value > 4, append '{' to front and prepend '}' to back
  if v<4:b=';'*v+b;break            #   if remaining value < 4, prepend that many ';' to back string and break
 print f+b                          #  print result
t=raw_input()                       # get raw input
try:int(t);i(t)                     # use try block to determine which function to call
except:c(t)                         # 

感谢Erik Konstantopoulos大大减少了字节!你可以说...他真的从我的代码中拿走了一个...字节...自我五*


4
欢迎来到PPCG!您的代码包含许多不需要的print语句和注释,您的变量名太长,可以消除一些空格。我还建议阅读《皮翁高尔夫技巧》
丹尼斯

很棒的资源,谢谢!我将对此代码进行适当的更改,然后看它能使我走多远。看起来如果我想成为这个网站上的任何人,我要么需要学习CJam或Pyth,要么编写自己的语言。
泰勒·洛佩兹

3
@iAmMortos 不一定。如果发现它令人愉快,请执行;否则,请坚持使用Python。:)
DLosc 2015年

2
通常,打高尔夫球分为三个步骤:1)使您的程序像平时一样正常运行,并尽可能地减少(例如,没有调试语句,不需要处理无效输入,减少输出)2)尽可能多地删除:空格,重命名变量(valuev等),3)做聪明高尔夫的东西:这是你需要看看丹尼斯的链接点。我很想知道您能削减多少!
Sanchises

1
我从未在社区受到如此热烈的欢迎。大声笑,我想我喜欢这里。
泰勒·洛佩兹

4

CJam,87字节 80.1得分(89字节-10%奖金)

在增加2个字节的同时有资格获得奖励的更新版本:

l_'{#){VX@{";{}"#)" _@+\ 4* 4/"S/=~}/;}{i_4<{"{}"\';*}{{4md\_{F'{\+'}+}{;L}?\';*+}:F~}?}?

在线尝试

我第一次在CJam中使用递归!整个过程看起来很冗长,但是两个完全独立的转换加起来。

我使用了一个完全独立的案例将小于4的数字转换为Curly。可能可以避免这种情况,但是将特殊情况处理合并到递归函数中并不是一件容易的事。并添加额外的内容{}作为后处理步骤看起来并没有什么好看的,即使我可能会再短一点再尝试。


您的分数不会是80.1吗?
PurkkaKoodari 2015年

4
@ Pietu1998谢谢。我的解决方案不仅太长,而且显然我在基本算术上也失败了……
Reto Koradi

3

C#,173-10%= 155.7 173-10 171.0,177.3

这不进行验证,仅查找;}字符。它假设所有{字符都在任何;字符之前。我发现最难的事情是不插入{}在Curly数字中间。

换行符和缩进为清楚起见:

string C(string a,int b=0){
    int n;
    if(int.TryParse(a,out n))
        a=(n>=b?"{"+C(""+n/4,4)+"}":"")+";;;".Remove(n%4);
    else
        foreach(int c in a)
            a=""+(c==59?++n:c==125?n*=4:n);
    return a;
}

您可以在vareach循环中使用var而不是char来保存一个字节。
raznagul 2015年

@DLosc,对不起,我对#1奖金感到困惑。我虽然适用于输出而不是输入。
Hand-E-Food

2

Java 326字节-10%= 294字节

它是用Java编写的完整程序,

public class a{static String c(long a,int v){if(a==0)return v==0?"{}":"";String x="";for(int i=0;i<a%4;i++)x+=";";return "{"+c(a/4,v+1)+"}"+x;}public static void main(String[]c){try{System.out.println(c(Long.parseLong(c[0]),0));}catch(Exception e){System.out.println(c[0].chars().reduce(0,(a,b)->b==';'?a+1:b=='}'?a*4:a));}}}

我敢肯定它可以短很多,但是我现在没有太多时间来优化它


@DLosc该死的,正确的,以为我可以用java :(
user902383

还:Java上的常见优化是避免使用public before类
masterX244

更换public static void main(String[]c){static{
das_j

2

GNU sed,330 326 - 10(%)= 293.4

(我-r在申请奖金10%之前添加了一个供使用;我希望这是正确的)

/;/{
s/[^};]//g
:c
s/(;*)\}/\1\1\1\1/
tc
:d
/;/{
s/;;;;;/v/g
s/vv/x/g
/[;v]/!s/\b/0/2
s/;;/b/g
s/bb/4/
s/b;/3/
s/v;/6/
s/vb/7/
s/v3/8/
s/v4/9/
y/;bvx/125;/
td
}
n
}
:u
s/\b9/;8/
s/\b8/;7/
s/\b7/;6/
s/\b6/;5/
s/\b5/;4/
s/\b4/;3/
s/\b3/;2/
s/\b2/;1/
s/\b1/;0/
s/\b0//
/[^;]/s/;/&&&&&&&&&&/g
tu
:v
s/;;;;/v/g
s/v+/{&}/
y/v/;/
tv

完整版显示上述内容大部分是十进制和一进制之间的转换:

#!/bin/sed -rf

/;/{

# Delete non-Curly characters
s/[^};]//g

# Curly to unary
:c
s/(;*)\}/\1\1\1\1/
tc

# unary to decimal
:d
/;/{
s/;;;;;/v/g
s/vv/x/g
/[;v]/!s/\b/0/2
s/;;/b/g
s/bb/4/
s/b;/3/
s/v;/6/
s/vb/7/
s/v3/8/
s/v4/9/
y/;bvx/125;/
td
}

# done
n

}


# Decimal to unary
:u
s/\b9/;8/
s/\b8/;7/
s/\b7/;6/
s/\b6/;5/
s/\b5/;4/
s/\b4/;3/
s/\b3/;2/
s/\b2/;1/
s/\b1/;0/
s/\b0//
/[^;]/s/;/&&&&&&&&&&/g
tu

# Unary to Curly
:v
s/;;;;/v/g
s/v+/{&}/
y/v/;/
tv

不幸的是,这个问题明确表示必须使用十进制,这就是为什么要麻烦转换的原因。
Toby Speight 2015年

您是对的,这对我来说有点令人惊讶,因为排除一元不是我的意图。哦,好吧,现在更改问题为时已晚。先生,我重申+1。
DLosc

2

佩尔(183) 177

这可能不是最短的Perl答案,但是我认为发布(输入$_,输出为返回值)足够有趣:

sub f{if(/}/){s/[{}]/00/g;oct'0b'.s/00(;+)/sprintf'%02b',length$1/ger}else{$_=sprintf'%064b',$_;s/../oct"0b$&"/ge;s/^0+(?!$)//;$_='{'x length.$_;s/\d/'}'.';'x$&/ge;s/\Q{{}/{/r}}

我们观察到Curly只是四元(基数为4)表示法。Perl缺乏对四元数的本机支持,这使我们稍受阻碍,但是幸运的是,每个四元数都是二进制的两位,并且我们可以读写二进制。因此,我们有以下内容:

  1. 卷曲为小数:将每个卷曲数字转换为2个二进制数字,并置并转换为十进制
  2. 十进制到卷曲:以二进制形式打印数字(强制偶数个数字),然后将每个位对转换为卷曲。

扩展版

sub f
{
    if (/}/) {
        s/[{}]/00/g;     # digits are now 00 00; 00;; 00;;;
                         # and opening braces become harmless leading zeros
        s/00(;+)/sprintf'%02b',length $1/ge;
                         # convert semicolons to binary, leaving zeros alone
        oct "0b$_"       # now to decimal
    } else {
        $_=sprintf'%064b',$_;   # decimal to binary
        s/../oct"0b$&"/ge;      # bit-pair to quaternit
        s/^0+(?!$)//;           #/remove leading zeros
        $_='{'x length.$_;      # prefix enough opening braces
        s/\d/'}'.';'x$&/ge;     #/digit to semicolons
        s/{{}/{/r               # first empty brace, unless $_ <= {};;;
    }
}

1

JavaScript(ES6),95(105-10%)

f=(n,r='{}')=>-1-n?(n>3?'{'+f(n>>2,'')+'}':r)+';'.repeat(n&3):n.replace(/[;}]/g,c=>c>';'?n*=4:++n,n=0)&&n

测试下面的代码段

f=(n,r='{}')=>-1-n?(n>3?'{'+f(n>>2,'')+'}':r)+';'.repeat(n&3)
:n.replace(/[;}]/g,c=>c>';'?n*=4:++n,n=0)&&n

// Test
function out(x) { O.innerHTML=x+'\n'+O.innerHTML; }

function go() { out(I.value + ' --> ' + f(I.value)) }

;[ 
  ['{;;}', 8]
, ['{{;};};', 21 ]
, ['{};;;', 3 ]
, ['{{{{;}}};}', 260 ]
, ['{}', 0 ]
, [ 4, '{;}' ]
, [ 17, '{{;}};' ]
, [ 1,'{};' ]
, [ 0, '{}' ]
, [ 96, '{{{;};;}}' ]
, ['{};;;;;', 5 ]
, ['{{;;;;};;}' , 72 ]
, ['c{u;r;l}y;!', 9 ]
, ['42{;} ;;;;', 8 ]
].forEach(t => {
  r=f(t[0])
  k=t[1]
  out('Test ' +(r==k?'OK':'Fail')+'\nInput:  '+t[0]+'\nResult: '+r+'\nCheck:  '+k+'\n')
})
Custom test <input id=I><button onclick='go()'>-></button>
<pre id=O></pre>


您能发布您的实际代码吗?另外,您的分数是94.5。
暴走者埃里克(Erik the Outgolfer)'16年

@ErikKonstantopoulos我的实际代码发布在测试代码的顶部。现在,它也是最重要的答案。关于分数(应该以字节为单位),我总是觉得很有趣(测量一半(或更少)字节),而喜欢轮流向上
edc65 '16

edc65:是的,但是四舍五入对您不利!94.5 <95,因此得分较小,这意味着它可能胜过更多提交。另外,“代码段顶部”也不是显示代码的地方。
暴民埃里克(Erik the Outgolfer)

1

露比(Ruby)126.9 129.6(144-10%)

使用递归将十进制转换为卷曲形式。取消对忽略字符以外的字符的检查会/[;{}]/增加分数0.4

f=->s{s=~/^\d+$/?(n=s.to_i
"{#{n<1?'':f[(n/4).to_s].gsub('{}','')}}#{?;*(n%4)}"):eval(s.tr("^{;}","").gsub(/./){|c|c<?A?"+1":c>?|?")*4":"+(0"})}

现在已修复。感谢您报告错误;分数已更新。
价值墨水

1

Perl 5,154(185170字节-10%+1罚款)

$e=$/;if($_=~/{/){s/[^{};]//g;s/;/+1/g;s/{/+4*(/g;s/}/+0)/g;$b=eval}else{$r=$_;$b=$r<4?"{}":"";while($r>0){if($r%4>0){$r--;$e=";$e"}else{$b.="{";$e="}$e";$r/=4}}}$_=$b.$e

正则表达式和eval解决curlies。
产生冰壶的方式有所不同。

测试

测试文件还包含奖金案例

$ cat curlytestcases.txt
{}
{};
{};;
{};;;
{;;}
{{;};};
{{{{;}}};}
0
1
2
3
4
17
96
{};;;;;
42{;} ;;;;
c{u;r;l}y;!
{{;;;;};;}

$ cat curlytestcases.txt |perl -p curlies.pl
0
1
2
3
8
21
260
{}
{};
{};;
{};;;
{;}
{{;}};
{{{;};;}}
5
8
9
72

增加了-p的-1惩罚。$ b = $ r <2?“ {}”:“”; 添加了0和1的例外。是测试中的输入。
LukStorms

需要一些时间来测试它。现在已修复。:)
LukStorms

我认为+ 1%的罚款是在-10%的奖金之后。
暴民埃里克(Erik the Outgolfer)

有趣的观察。不知道现在是否应该这样,但是这很有意义,所以我还是改了。不是说它改变了最终得分。
LukStorms '16

1

视网膜69 64字节

+`{(;*)}
$1$1$1$1
^\d+|^(;*)
$*;$.1
+`(;+)\1\1\1
{$1}
^;|^$
{}$&

尝试测试套件


说明

+`{(;*)}
$1$1$1$1

将最里面的花括号分解为;s。循环直到没有大括号为止。

^\d+|^(;*)
$*;$.1

在十进制和一元之间转换 ;

+`(;+)\1\1\1
{$1}

找出其中最长;的4的倍数并套入花括号,循环直到不再有4+的运行。

^;|^$
{}$&

如果生成的卷曲数字以;或为空字符串开头,请添加{}在前面。


1

Python 2的 157个字节-10%= 141.3

lambda n:'{}'*(int(n)<4)+g(int(n))if n.isdigit()else sum((v==';')*4**n.count('}',i)for i,v in enumerate(n))
g=lambda n:'{%s}'%g(n/4)+';'*(n%4)if n>3else';'*n

在线尝试!

处理更多奖金案件的更加精通Python 2的答案。不想以此作为评论来弥补坏消息,所以就在这里。

它从内到外在大写数字上起作用,为找到的每个分号的总和加4 ^(字符串中剩余的大括号的数量)。如果字符串是数字,则以与提供的语法相同的方式递归创建卷曲数字。


尴尬了。我什至在其中有小于2的测试用例。固定为总共+5个字节。
阿诺德·帕尔默

@发誓我发誓我通常不会那么糟糕。固定,并打一点高尔夫球,使其更具竞争力。
阿诺德·帕尔默 Arnold Palmer)
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.