簡単な番号体系


19

簡単な番号体系についてお話ししましょう。(この挑戦のためだけに作り上げました)

このシステムは、機能が含まれています()[]{}、と<>

1。 ()

いつ ()引数が指定されていないは、と評価され0ます。

いつ ()1つ以上の引数が与えられた、引数の合計に評価されます。

2。 []

いつ []引数が指定されていないは、と評価され-1ます。

いつ [] 1つ以上の引数が与えられ、それは第一引数マイナス他の引数の合計に評価されます。

3。 {}

いつ {}引数が指定されていないは、と評価され1ます。

いつ {} 1つ以上の引数が与えられ、それは、これらの引数の積に評価されます。

4。 <>

いつ <>引数が指定されていないは、と評価され1ます。

いつ <> 1つ以上の引数が与えられ、それは、他の引数の積で割った最初の引数の整数に評価します。

あなたのタスク

この単純な数値システムで有効な数値を含む文字列(つまり、角括弧のバランスが取れていること、0による除算がないことなど)が指定されている場合、その値を出力します。

テストケース

() -> 0
(()()) -> 0
([][]) -> -2
({}<>) -> 2
({}[]) -> 0
[] -> -1
[[][]] -> 0
[()<>] -> -1
{()} -> 0
{([]<>)} -> 0

これはであるため、バイト数が最も少ないコードが優先されることに注意してください。


13
私はこれに素晴らしい名前を持っています。それは完全に作り上げたもので、他のどこからも得られませんでした:ブレインフレーク!
ETHproductions

4
@ETHproductionsいいえ
オリバーNi


2
除算は浮動小数点除算ですか、整数除算ですか?
-xnor

1
@Oliverオペランドの一方または両方が負の場合、整数除算はどのように機能しますか?何のための4つの期待される結果は5/35/-3-5/3-5/-3
マーティンエンダー

回答:


2

Dyalog APL、94 バイト

o←{(⊂(1⊃⍵),⍺⍺⊃⍵),2↓⍵}⋄u←{(⊃⍵,⍺⍺1)⍺⍺⍵⍵/1↓⍵}⋄⍎⍕'+/o' '-u+o' '×/o' '÷u×o' '(⊂⍬),'[')]}>'⍳⌽⍞],'⊂⍬'

使用する ⎕IO←0

置き換え)]}>スタックを取る関数呼び出しとは、それを削除し、その上部フレームに操作を適用し、そして(単項演算子は、その次のフレームに結果を追加しo、そのために使用され、二項演算子uハンドルのより複雑なケース-÷

([{<スタックにフレームを追加するコードに置き換えます((⊂⍬),

1つの空のフレーム(⊂⍬)の初期スタックで、結果の式を(APLの実行順序と一致するように逆に)実行します


5

ハスケル、357 306 277 251 228 224 188 185 180バイト

明示的なスタックを持つトークンベースのパーサー。(%)トークンスタックと文字を受け取り、(opcode、defaultnumber)または(0、number)を({[<プッシュするか、最上位の数字と1つのオペコードをポップして、応答をプッシュします)}]>。オペコードは、ASCII列挙型ハックによってエンコードされます。

@ChristianSieversの素晴らしい回答に感謝私がいくつかのアイデアを借り。

ワンライナー!

s%c|elem c"([<{",g<-div(fromEnum c)25=(g,[0,0,1,-1,1]!!g):s|(a,(o,n):b)<-span((==0).fst)s=(0,[foldr1(flip$[(+),quot,(-),(*)]!!(o-1))$snd<$>a,n]!!(0^length a)):b
snd.head.foldl(%)[]

エラー処理が少なくなりました!使用法:

*Main> map (snd.head.foldl(%)[]) ["()","(()())","([][])","({}<>)","({}[])","[]","[[][]]","[()<>]","{()}","{([]<>)}"]
[0,0,-2,2,0,-1,0,-1,0,0]

14 + 3バイトを節約してくれてありがとう@ChristianSievers!

いくつかの+4バイトを保存してくれてありがとう@Zgarb!


1
(0,[0,0,1,-1,1]!!o):s5行目はどうですか?
クリスチャンジーバーズ

@ChristianSieversもちろん!
アング

の定義を切り替えて、2番目のケースとして!実行できるようにします(s:_)!_=d s。また、x<-p$d<$>init a,y<-d$last aの最後のケースでバインドできると思います%
ズガーブ

@Zgarbありがとう!評価をさらに統合する方法を見つけました。
アンス

1
3行目に%あなたの周りの括弧をドロップすることができます_:bし、g c
-Zgarb

3

パイソン2、292の 265 248 235 223 206 204バイト

r=reduce
s=input()
for n in')]}>':s=s.replace(n,'),')
for a in'(*x:sum(x)','[a=-1,*x:a-sum(x)','{*x:r(int.__mul__,x,1)','<a=1,*x:r(int.__div__,x,a)':s=s.replace(a[0],'(lambda %s)('%a[1:])
print eval(s)[0]

すべてのブラケットを、ブラケットが行うことを行うラムダで置き換え、結果のPythonコードを評価します。のような引用符で囲まれた入力が必要'[<><>([]{})]'です。

このプログラムは、の各文字列の最初の文字としてブラケットのタイプを保存し、残りの部分forはキーワードの後のすべてを保存しlambdaます。次に、最初の文字を使用して置換します。残りはのようなラムダに結合され(lambda*x:sum(x))()ます。

Ideoneでお試しください!


3

PEG.js(ES6)、132バイト

x=a:[([{<]b:x*[)\]}>]{var x='([<'.indexOf(a)
b.length^1||b.push(0)
return~~eval(b.length?b.join(('+-/'[x]||'*')+' '):~-('10'[x]||2))}

今すぐ修正する必要があります。

説明

より読みやすい:

x=a:[([{<]
  b:x*
  [)\]}>]
{
  var x='([<'.indexOf(a)
  b.length^1||b.push(0)
  return ~~eval(
    b.length?
      b.join(('+-/'[x]||'*')+' ')
    :~-('10'[x]||2))
  )
}

PEG.jsは、解析用に特別に作成されたJavascriptの拡張バージョンです。非常に厳しいので、使用する必要がありましたvar。さらに、文字列の内側に括弧があるバグがあるようで、コードが大幅に肥大化しました。

最初に、rule xに一致するa複数の式を含む場合と含まない場合があるすべてのブラケットに一致するルールを定義しますx

ルールxに一致するたびに、長さが1のb場合、内部一致の配列に0をプッシュしますb

bの長さが> 0の場合、ain のインデックスを見つけ、そのインデックスを使用して([<文字を取得+-/します。結果は(意味定義されていない場合aでした{)、その後、我々はに結果を回します*。最後に、スペースを追加して参加しますbし、結果にします。

bの長さ= 0の場合、ain のインデックスを見つけ、そのインデックスを使用して([<文字を取得10します。結果は(意味未定義の場合aだった{<)、その後、我々は最後に、我々は単にデクリメント2に結果を回します。

最後に、式を評価して結果をフロアリングできます。


3

Perl、113 + 2 = 115バイト

-lp(2バイトのペナルティ)で実行します。

/\W/,eval"sub $`\{\$#_?(shift)$&&$'1}"for qw'a+a:1- b-a:- c*c: d/c:';y/([{</a-d/;s/\W/0),/g;s/\pL\K/(/g;$_=eval

より読みやすく(注:構文的に許可されていない場所にコメントを入れているため、この「より読みやすいバージョン」は実際には実行されません):

              # -p option: read a line of input into $_ at program start
              # -l option: remove the final newline whenever reading
do {          # for each element of a list, given later:
  /\W/;       # place an initial identifier in $`, the next character in
              # $&, and the rest of the element in $'
  eval qq{    # then evaluate the following template, with substitutions:
    sub $` {  # define a subroutine named $`, that does this:
      \$#_ ?  # if there is more than one argument                   
      (shift) # then return the first argument $&-ed with
      $& &$'  # the result of a recursive call with the tail of the arguments
              # else (the "else" is a colon taken from $', not the template)
      1       # return (the remainder of $' applied to) 1
    }
  }
} for qw'     # specify the list by splitting the following on whitespace:        
  a+a:1-      # a(head,tail) = len(tail>1) ? head+a(tail) : 1-1
  b-a:-       # b(head,tail) = len(tail>1) ? head-a(tail) : -1
  c*c:        # c(head,tail) = len(tail>1) ? head*c(tail) : 1
  d/c:        # d(head,tail) = len(tail>1) ? head/c(tail) : 1
';
y/([{</a-d/;  # replace ( [ { < with a b c d in $_
s/\W/0),/g;   # replace whitespace, punctuation in $_ with the string "0),"
s/\pL\K/(/g;  # place a ( after (\K) each letter (\pL) in $_
$_=eval       # evaluate $_ as a Perl program, storing the result back in $_
              # -p option: print $_ to the user at program end
              # -l option: output a newline whenever printing

基本的な考え方は、テキスト処理を介して入力を[()<>]Perlプログラムのように変換することですb(a(0),d(0),0),。Perlは末尾のコンマで十分です。以前、我々は関数を定義しabcdと同じ効果を持っている()[]{}<>私たちが実装しようとしている言語から構築します。これらはそれぞれ、最後の引数(最後の0)を無視します。これは、すべての入力が正しく解析され、頭と尾が別々に処理される関数型プログラミングでよく見られる実装を使用して機能するために含まれます。のでb(e,f,g,0)手段e-f-g、つまりは、特別にその最初の引数を扱うのに対してa対称的に扱い、その引数(a(e,f,g,0)手段e+f+g)、我々は実装しますa再帰的にb呼び出しaます。cそして、d同様の関係を有しています。これら4つの関数はすべて非常に似ているため、個別に実装するのではなく、実行時に生成します。文字列内の4つの関数すべてに適用されるテンプレートを保存し、テンプレートに文字を代入して関数を生成します。

Perl /は浮動小数点除算を行うため、実装された{}ものも行います。これはそれ自体では問題ではない、または-Minteger(すべての算術演算が整数演算である言語バリアントを選択する)のいずれかが無料であると仮定しています。それは問題の根本的な原因ではないようです。(4バイトの変更(shift)に費やす必要があると思いますが、int+(shift)これはテストしていません。)


2

オクターブ、215の 206 198バイト

S='sum(x(:))-sum(x(2:end))';Y='(@(x)isempty(x)';c=']) ';[~,~,u]=unique(['()<>[]{}',input('')]);eval([{'sum([',c,[Y,'+fix((',S,')/prod(x(2:end))))(['],c,[Y,'*-1+',S,'*2)(['],c,'prod([',c}{u(9:end)}])

オンラインで試す


2

PHP、315の 300 285 258 250 244バイト

for($s=$argv[1];$r=!$r;)foreach(["(+)1","[-]0","{*}2","</>2]as$p)if(preg_match("#$e$p[0]([-_\d]*)$e$p[2]#",$s,$m)){if(""==$v=strtok($m[1],_))$v=$p[3]-1;while(""<$n=strtok(_))eval("\$v$p[1]=$n;");$s=strtr($s,[$m[$r=0]=>_.$v]);}echo substr($s,1);

部分式をアンダースコア+値に置き換えます。反復が置換を行わなかった場合、ループが中断します。

私がCに初めて会ってから19年、PHPで17年間働いた。
これはstrtok理にかなっている初めてです... 24バイトを節約するのに役立ちます!

壊す

for($s=$argv[1];    // take input from argument
    $r=!$r;)        // toggle $r; loop until no replacement has taken place
    foreach(["(+)1","[-]0","{*}2","</>2]as$p) // loop through operations
        if(preg_match("#$e$p[0]([-_\d]*)$e$p[2]#",$s,$m))   // find a match
        {
            if(""==$v=strtok($m[1],_))  // init $v with first token from sub-match
                $v=$p[3]-1;             // if no token, init with default value
            while(""<$n=strtok(_))      // loop through tokens
                eval("\$v$p[1]=$n;");       // operate
            $s=strtr($s,[$m[$r=0]=>_.$v]);  // reset $r; replace match with underscore+value
        }
echo substr($s,1);  // print result

@Oliverはここで誰かをbe打しません。しかし、楽しみに感謝します!
タイタス

2

ES6(Javascript)、 250171154149、147バイト

純粋なJavascriptバージョン。

「メタプログラミング」(ここでの他のほとんどの回答と同様)は、多数の直接テキスト置換を適用する(つまり、プログラム構造をそのまま保持する)ことにより、入力プログラムテキストを対応するJavascriptプログラムに変換します。

おそらくさらにゴルフすることができます。

更新(v2.1)

  • マイナス2バイト(3項式の括弧を削除)
  • 結果の抽出に変数を使用し、余分な「[]」を取り除くことにより、さらに5バイト削った

更新(v2)

ES配列内の保留中のコンマは完全に有効であるため、コンマ正規化コード全体を削除できることに気付きました。また、アルファベット検索の最適化に関する@Titusの優れたアドバイスに従いました。

更新(v1)

重複する「置換」エイリアスを削除しました。

更新(v1)

  • より良いアルファベットを使用してください:()=> 1+ [] => 0 {} => 2 * <> => 2 /(各文字は値または演算子として直接再利用できます)

  • reduce()をreplace()に置き換えました(アルファベットマッピング)

  • 一定のインライン化、オープンおよびクローズのブラケット処理を1つのステップに統合

ゴルフ(v2.1)

s=>eval("o="+s.replace(/./g,r=>"2+1-3*3/"["()[]{}<>".indexOf(r)]).replace(/\d\D?|\D/g,r=>r[1]?r[0]-2+",":r*1?'([':`].reduce((r,a)=>r${r}a)),`)+"o

ゴルフ(v1)

(s,A="(2)+[1]-{3}*<3>/")=>eval(s[R="replace"](/./g,r=>A[A.indexOf(r)+1])[R](/\d\D?|\D/g,r=>r[1]?r[0]-2+",":(r[0]*1?'([':`].reduce((r,a)=>r${r}a)),`))[R](/,(\])|,$/g,"$1"))    

ゴルフ(v0)

([...s],A="(a)b[c]d{e}f<g>h",R="replace")=>eval(s.reduce((r,c)=>r+=A[A.indexOf(c)+1],'')[R](/ab|cd|ef|gh/g,r=>({d:-1,b:'0'}[r[1]]||1) + ',')[R](/[aceg]/g,"([")[R](/[bdfh]/g,r=>`].reduce((r,a)=>r${"+*-/"["bfdh".indexOf(r)]}a)),`)[R](/,(\])|,$/g,"$1"))

説明(v0)

//BEGIN 

//s - input text, A - alphabet, R - "String.replace()" alias
E=([...s],A="(a)b[c]d{e}f<g>h",R="replace")=>eval(

//Replace input alphabet by a more friendly one, to avoid too much escaping and quoting
// () - ab, [] -cd, {} - ef, <> - gh
s.reduce((r,c)=>r+=A[A.indexOf(c)+1],'')

//Replace no-arg invocations with a corresponding constant value
// () => 0, [] => -1, {} => 1, <> => 1      
[R](/ab|cd|ef|gh/g,r=>({d:-1,b:'0'}[r[1]]||1) + ',')

//Replace opening brackets with "(["
[R](/[aceg]/g,"([")

//Replace closing brackets with "].reduce(...)),"
//An arithmetic operation to apply (+-*/) is chosen based on the bracket type 
//and is substituted into the template 
[R](/[bdfh]/g,r=>`].reduce((r,a)=>r${"+*-/"["bfdh".indexOf(r)]}a)),`)

//Strip excessive commas
[R](/,(\])|,$/g,"$1")
);

//END: eval() the result


Example:
E("{([]<>()<>{})(<><>)}")
=> eval("([([-1,1,0,1,1].reduce((r,a)=>r+a)),([1,1].reduce((r,a)=>r+a))].reduce((r,a)=>r*a))")
=> 4

テスト

E=([...s],A="(a)b[c]d{e}f<g>h",R="replace")=>eval(s.reduce((r,c)=>r+=A[A.indexOf(c)+1],'')[R](/ab|cd|ef|gh/g,r=>({d:-1,b:'0'}[r[1]]||1) + ',')[R](/[aceg]/g,"([")[R](/[bdfh]/g,r=>`].reduce((r,a)=>r${"+*-/"["bfdh".indexOf(r)]}a)),`)[R](/,(\])|,$/g,"$1"))

T=(s,a)=>{
    console.log(s,r=E(s),r==a?"OK":"NOT OK");
}

T("()",0)
T("(()())",0) 
T("([][])",-2)
T("({}<>)",2) 
T("({}[])",0) 
T("[]",-1)
T("[[][]]",0) 
T("[()<>]",-1) 
T("{()}",0) 
T("{([]<>)}",0)

テスト出力

() 0 OK
(()()) 0 OK
([][]) -2 OK
({}<>) 2 OK
({}[]) 0 OK
[] -1 OK
[[][]] 0 OK
[()<>] -1 OK
{()} 0 OK
{([]<>)} 0 OK

1
v0バージョンはs.reduce((r,c)=>r+="abcdefgh"["()[]{}<>".indexOf(c)],'')(-5)で対応できますか?その場合indexOf、変数に記憶し、3番目の文字列リテラルから演算子を取得できます。
タイタス

2

Haskell、184179172161160159151148145バイト

s%(c:i)|elem c")}]>"=([1?(*),sum,1?quot,(-1)?(-)]!!mod(fromEnum c)5$s,i)|(r,j)<-[]%i=(s++[r])%j
[v]%e=(v,e)
(v?_)[]=v
(_?o)s=foldl1 o s
fst.([]%)

Haskellによる入力のスレッド化、再帰下降。いつものように、最後の行は定義ではありませんが、問題を解決する機能を示しています。そのため、テストするには、ファイルの最後の行以外の行を入れてロードし、次のようにします。

*Main> fst.([]%) $ "{([][][])([][])}"
6

インスピレーションと多くの詳細なヒントを提供してくれた@Zgarb、および彼のソリューションとさらなるヒントからインスピレーションを得た@Angsに感謝します。

負の整数での除算の動作方法は指定されていません。とにかく、繰り返し使用するのdivは間違っているように見えdivます。これは、残りの値の積で1回使用するのと同じではないからです。今使用してquot、私はのために同じ結果を得る<{}([][])[]><{}{([][])[]}>

素晴らしく、ほとんど読みやすいコードについては、最初のバージョンをご覧ください。中間バージョンには、すてきで威圧的なあらゆる種類のコードが含まれており、このバージョンの理解に役立ちます。


明示的なタプルの代わりに定義(!)=(,)して使用することで、数バイトを節約できると思います!
-Zgarb

あなたが定義した場合m xd xなど1#x0#x、あなたはケースをマージすることができますm[x]し、d[x]私は節約を考える1の中にいくつかはあまりにもバイト。
ズガーブ

@Zgarbありがとう!私は最後のペアを逃しそうになりましたが、それなしでは!トリックは報われません。あなたの2番目の提案は悪です、そこには私のほとんど読みやすいコードがあります...賢い!
クリスチャンシーバーズ

ふむ、私はちょうど定義することを実現s%(c:i)=(s?c,i)し、s?')'=sum sあなたが繰り返しを取り除くことができますので、などは、はるかに短くなりますi秒。..待ってください、それはおそらくs%(_:i)ケースのために動作しません。
ズガルブ

1
とのバッククォートを失うelemdiv、さらにバイトが節約されます。
ズガルブ

1

JavaScript(ES6)、いいえeval、156バイト

f=s=>s==(s=s.replace(/(.) ?([- \d]*)[\]})>]/,(_,c,s)=>` `+(s?s.split` `.reduce((l,r)=>c<`<`?l- -r:c<`[`?l/r|0:c<`{`?l-r:l*r):c==`[`?-1:c==`(`?0:1)))?+s:f(s)

説明:正規表現は、最初の未処理の閉じ括弧を検出し、(おそらく)対応する開き括弧とその間の引数と一致します。引数は、分割及び操作に応じて減少させた(悲しい「(」と「[」、最適のためのペアでないある+-再び値に文字のマッチングが最適以下である)、または引数がない場合、適切な値が算出されます(その後、結果は先頭のスペースに置き換えられ、他の結果と分離されます。その後、関数は変更がなくなるまで再帰的に呼び出します。その場合、結果の値が返されます。例:

[()<>]
[ 0<>]
[ 0 1]
 -1

f( "([] [])") => 0(2ではなく)
zeppelin

他のいくつかのテストも失敗しています(私の答えのテストコードを試してみてください)。おそらく、f( "[]")=> 0です。 "[]"はすべての失敗したテストの一部です。
ツェッペリン

@zeppelinおっと、それはいくつかの悪いゴルフが原因でした。以前のバージョンに戻しましたが、残念ながら数バイトかかります。
ニール
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.