{カーリー番号};


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つの以上セミコロン)または{{};}(不要空ブレース基)が呼び出される不適切カーリー番号。これらは上記の文法に従い、通常の方法で評価できますが、より短い表現も可能です(上記の例、{{;}}および{;}それぞれ)。

チャレンジ

文字列を入出力するプログラムまたは関数を作成します。文字列が非負の10進整数である場合、その整数の適切な(可能な限り短い)Curly表現を出力または返します。文字列がカーリー数の場合、その10進表現を出力/返します。

入力は、STDIN、コマンドライン引数、または関数パラメーターを介して受け取ることができます。それはしなければならない文字列です。つまり、Curly数値の文字列を受け入れ、10進数の整数を受け入れる関数を作成することはできません。

出力は、STDOUTに出力するか、関数から返すことができます。関数、必要に応じて整数を返したり、すべての状況で文字列を返したりする場合があります。

プログラムは、不正な入力(フォーマット規則に違反するカーリー数、浮動小数点数、負の整数、ランダムテキスト)を処理する必要はなく、不適切なカーリー数を処理する必要はありません(以下を参照)。入力は、印刷可能なASCII文字のみで構成されます。

得点

バイト単位の最短コードが優先されます。プログラムが次の両方を実行できる場合:

  1. 不適切なカーリー数を正しく処理し、
  2. カーリー番号が与えられた場合、そうでない余分な文字は無視します {};

次に、スコアから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

@ user902383一致しない中括弧は発生しないと想定できます。
DLosc

2
Retinaソリューションを作成するつもりでしたが、Curly文字列(20バイトのみ)を処理した後、正整数-> Curlyも処理する必要があることに気付きました。
mbomb007

@DLoscええ、勝てないので、時間を費やすつもりはありません。
mbomb007

Pythソリューションが既に最短CJamソリューションよりも22%短くなり、具体的にこの質問に意味mbomb007 I、@ ボーナスの対象。とにかく、それは「いや、でも楽しいし、賛成票を集めることができる」と言っている修辞的な質問でした。ただし、「楽しい」部分に同意しない場合は、問題ありません。
DLosc

回答:


15

Pyth、35 32バイト-10%= 28.8

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

オンラインで試す:デモンストレーションまたはテストスイート

編集:判明したように、私は誤って不適切なカーリー番号も処理できます。まったく計画されていませんでした。;-)

説明:

コードには2つの式があります。1つ目は数値をカーリー番号に変換し、2つ目はカーリー番号を通常の数値に変換します。.xどの式が印刷されるかを処理します。最初の式を印刷しようとします。入力に数字以外がある場合、最初の式は失敗します(例外を介して)。.x例外をキャッチし、2番目の例外を出力します。

.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に感謝します!あなたは言うことができる...彼は本当に...バイト...私のコードのうち... *自己5 *


4
PPCGへようこそ!コードには多くの不要なprintステートメントとコメントが含まれています。変数名が長すぎるため、空白を削除できます。Pyrhonでのゴルフのヒントも読むことをお勧めします
デニス

素晴らしいリソース、ありがとう!このコードに適切な変更を加え、それがどの程度の効果をもたらすかを確認します。このサイトの誰かになりたい場合は、CJamまたはPythを学ぶか、自分の言語を書く必要があります。
テイラーロペス

3
@iAmMortos 必ずしもではありません。楽しいと思うならやってください。そうでなければPythonを使い続けてください。:)
DLosc

2
1):通常、ゴルフは3つの段階で行われ、あなたのプログラムを作るあなたが通常行うのと同じようすなわち、ノーデバッグ文、無効な入力、最小限の出力)2)を処理する必要はありません(可能な限り最小限として、可能な限り削除は:空白、変数の名前を変更valueするvなど)、3)賢いゴルフをする:これは、デニスのリンクを見る必要があるポイントです。これをどれだけ減らすことができるか楽しみです!
-Sanchises

1
コミュニティでこんなに温かい歓迎を受けたことはありません。笑、私はここが好きだと思います。
テイラーロペス

4

CJam、87バイト 80.1スコア(89バイト-10%ボーナス)

2バイトずつ増加しながら、ボーナスの対象となる更新バージョン:

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

オンラインで試す

初めてCJamで再帰を使用しました!全体が長く見えるかもしれませんが、2つの完全に別個の変換が合計されます。

4より小さい数値をCurlyに変換するために、まったく別のケースを使用しました。おそらくそれを回避することは可能ですが、特別な場合の処理​​を再帰関数に組み込むことは完全に簡単ではありません。また、余分なもの{}を後処理ステップとして追加しても、少し短くなる可能性がある場合は再試行する必要がありますが、実際にはそれほど良く見えませんでした。


あなたのスコアは80.1ではありませんか?
PurkkaKoodari

4
@ Pietu1998ありがとう。だけでなく、私の解決策は、明らかに私も...基本的な算術で失敗し、長すぎる
レトKoradi

3

C#、173-10%= 155.7 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;
}

foreachループでcharの代わりにvarを使用すると、1バイトを保存できます。
raznagul

@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

-r10%のボーナスを請求する前に使用するために1つ追加しました;それが正しいことを願っています)

/;/{
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

完全版は、上記のほとんどが10進数と単項の間の変換であることを示しています。

#!/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

残念ながら、この質問では明示的に10進数が必要であると言われているため、変換が面倒です。
トビーSpeight

あなたは正しいです。単項式を除外することは私の意図ではなかったので、私には少し驚いています。まあ、今質問を変更するには遅すぎると思います。+1を再確認します。
DLosc

2

Perl、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進(ベース4)表記であることがわかります。Perlが四元をネイティブにサポートしていないため、少し妨げられていますが、幸いなことに、各四元はバイナリの2ビットであり、バイナリの読み書きができます。したがって、次のものがあります。

  1. カーリーを10進数に:各カーリー数字を2桁の2進数に変換し、連結して10進数に変換します
  2. 10進数からカーリー:数値をバイナリで印刷し(偶数桁を強制)、各ビットペアをカーリーに変換します。

拡張版

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です。
エリックアウトゴルファー

@ErikKonstantopoulos私の実際のコードはテストスニペットの先頭に投稿されました。今、それも答えの一番上にあります。スコアについて(それはバイトにする必要があります)、私はいつも面白い測定半分(以下)バイトを感じるとまでrouniding好む
edc65

edc65:ええ、でも切り上げは悪いことです!したがって、94.5 <95のスコアは小さくなります。これは、おそらくより多くの提出を上回ることを意味します。また、「スニペットの上部」はコードを表示する場所ではありません。
エリックアウトゴルファー

1

ルビー、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(185 170バイト-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はカーリーを解決します。
カーリーの生成方法は異なります。

テスト

テストファイルにはボーナスケースも含まれています

$ 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%ボーナスの後に来ると思います。
エリックアウトゴルファー

興味深い観察。それが今あるべきかどうかはわかりませんが、理にかなっているので、とにかくそれを変更しました。終了スコアが変わるわけではありません。
LukStorms

1

網膜69 64バイト

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

テストスイートをお試しください


説明

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

最も内側の括弧を;sに分解します。中括弧がなくなるまでループします。

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

10進数と単項の間の変換 ;

+`(;+)\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バイトに修正されました。
アーノルドパーマー

@DLosc私は通常、それほど悪くないことを誓います。修正し、少し競争力を高めるために少しゴルフをしました。
アーノルドパーマー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.