간단한 숫자 체계


19

간단한 숫자 체계에 대해 말씀 드리겠습니다. (나는이 도전을 위해 만듦)

이 시스템은 기능을 포함 (), [], {},와 <>.

1. ()

()인수를 지정하지, 그것은에 평가합니다 0.

()하나 이상의 인수가 제공 되면 인수의 합계로 평가됩니다.

2. []

[]인수를 지정하지, 그것은에 평가합니다 -1.

[]하나 이상의 인수가 제공 되면 첫 번째 인수에서 다른 인수의 합계를 뺀 값으로 평가됩니다.

삼. {}

{}인수를 지정하지, 그것은에 평가합니다 1.

{}하나 이상의 인수가 제공 되면 해당 인수의 곱으로 평가됩니다.

4. <>

<>인수를 지정하지, 그것은에 평가합니다 1.

<>하나 이상의 인수가 제공 되면 첫 번째 인수 정수를 다른 인수의 곱으로 나눈 값으로 평가됩니다.

당신의 작업

이 간단한 숫자 시스템에 유효한 숫자 (괄호가 균형을 이루고 0으로 나누지 않음 등)가 포함 된 문자열이 주어진 경우 해당 값을 인쇄하십시오.

테스트 사례

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

이것은 이므로 바이트 수가 가장 적은 코드가 이깁니다.


13
나는 이것에 대한 훌륭한 이름을 가지고 있습니다.
ETHproductions

4
@ETHproductions 아니오
Oliver Ni


2
나누기 부동 나누기 또는 정수 나누기입니까?
xnor

1
@Oliver 피연산자 중 하나 또는 모두가 음수 일 때 정수 나누기가 어떻게 작동해야합니까? 의 4 개 예상되는 결과 무엇인가 5/3, 5/-3, -5/3-5/-3?
Martin Ender

답변:


2

Dyalog APL , 94 바이트

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

사용 ⎕IO←0

본 절의 )]}>스택을 취하는 함수 호출과 그것을 삭제 상단 프레임 상에 동작을 적용하고, 그 다음 프레임에 결과를 추가 (모나드 운영자가 o그것을 위해 사용된다 이항 연산자 u핸들 더 복잡한 경우 -÷)

([{<스택에 프레임을 추가하는 코드로 대체 ( (⊂⍬),)

하나의 빈 프레임 ( ⊂⍬) 의 초기 스택과 함께 결과 표현식 (반전, APL의 실행 순서와 일치)을 실행합니다.


5

하스켈 357 306 277 251 228 224 188 185 180 바이트

명시 적 스택이있는 토큰 기반 파서. (%)토큰 스택 및 문자를 가져 와서 (opcode, defaultnumber) 또는 (0, number)를 ({[<푸시하거나 최상위 숫자와 하나의 opcode를 팝하고에 대한 답변을 푸시합니다 )}]>. opcode는 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):s다섯 번째 줄에?
Christian Sievers

물론 @ChristianSievers!
Angs

의 정의를 전환하면 두 번째 경우처럼 !할 수 있습니다 (s:_)!_=d s. 또한 x<-p$d<$>init a,y<-d$last a의 마지막 경우에 바인딩 할 수 있다고 생각합니다 %.
Zgarb

@Zgarb 감사합니다! 평가를 더욱 통일 할 수있는 방법을 찾았습니다.
Angs

1
세 번째 줄에서 및에 %parens 를 놓을 수 있습니다 . _:bg 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, 우리는의 인덱스 찾기 a에를 ([<으로부터 문자를 얻을 +-/해당 인덱스를 사용하여. 결과가 (그 의미를 정의되지 않은 경우 a였다 {), 우리는에 결과를 켭니다 *. 마지막으로, 우리는 공간을 차지하고 b결과 와 결합 합니다.

경우 b의 길이 = 0, 우리는의 인덱스 찾기 a에를 ([<으로부터 문자를 얻을 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),. 펄은 쉼표로 끝납니다. 앞서 우리가 기능을 정의 a, b, c, d와 같은 효과를 가지고있는 (), [], {}, <>우리가 구현하고있는 언어와 구조; 모든 입력이 올바르게 구문 분석되도록하기 위해 포함 된 마지막 인수 (끝의 0)를 각각 무시하고 헤드와 테일이 개별적으로 처리되는 기능적 프로그래밍에서 일반적으로 보이는 구현을 사용하여 작동합니다. 때문에 b(e,f,g,0)수단 e-f-g, 즉 반면, 특별히 첫 번째 인자를 취급 a취급 인수 대칭 ( a(e,f,g,0)수단 e+f+g), 우리가 구현a재귀 적으로 그리고 b전화를 통해 a. cd유사한 관계를 가지고있다. 이 네 가지 함수는 모두 매우 유사하므로 별도로 구현하지 않고 런타임에 생성합니다. 4 개의 함수 모두에 적용되는 템플릿을 문자열로 저장 한 다음 문자를 템플릿으로 대체하여 함수를 생성합니다.

Perl /은 부동 소수점 나누기를 수행하므로 구현 {}도 마찬가지입니다. 나는 이것이 자체적으로 문제가 아니거나 -Minteger(모든 산술 연산이 정수 연산 인 언어 변형을 선택하는) 자유 롭다고 가정합니다. 그렇지 않으면 Perl에서 정수 나누기를 작성하는 데 여분의 바이트를 소비해야하기 때문에, 문제의 근본적인 문제가 아닌 것 같습니다. (나는 당신이 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 년; 24 바이트 절약에 도움
이되는 것은 이번이 처음입니다 strtok!

고장

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는 여기에 사람을 때리지 않습니다. 그러나 재미 주셔서 감사합니다!
Titus

2

ES6 (자바 스크립트) 250, 171, 154, 149147 바이트

순수한 자바 스크립트 버전.

"메타 프로그래밍"(여기의 대부분의 다른 답변과 마찬가지로)은 입력 프로그램 텍스트를 여러 개의 직접 텍스트 대체를 적용하여 (즉, 프로그램 구조를 그대로 유지) 해당 Javascript 프로그램으로 변환합니다.

아마 더 골프를 칠 수 있습니다.

업데이트 (v2.1)

  • 빼기 2 바이트 (3 진 표현식에서 제거 된 괄호)
  • 결과 추출을 위해 변수를 사용하고 추가 "[]"를 제거하여 5 바이트를 더 줄였습니다.

업데이트 (v2)

ES 어레이에서 보류중인 쉼표는 완전히 유효하므로 전체 쉼표 정규화 코드를 제거 할 수 있습니다. 또한 알파벳 조회 최적화에 대한 @Titus의 훌륭한 조언을 따랐습니다.

업데이트 (v1)

중복 된 "대체"별칭이 제거되었습니다.

업데이트 (v1)

  • 더 나은 알파벳을 사용하십시오 : () => 1+ [] => 0 {} => 2 * <> => 2 / (각 문자는 값 또는 연산자로 직접 재사용 될 수 있습니다)

  • reduce ()를 replace ()로 대체했습니다 (알파벳 매핑)

  • 일정한 인라인, 오픈 및 클로징 브래킷 처리를 한 단계로 병합

골프 (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변수를 기억 하고 세 번째 문자열 리터럴에서 연산자를 가져올 수 있습니다.
Titus

2

하스켈, 184177172161160159151148145 바이트

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남은 값의 곱으로 한 번 사용하는 것과 같지 않기 때문에 잘못된 것으로 보입니다 . 이제을 사용하여 및에 quot대해 동일한 결과를 얻습니다 .<{}([][])[]><{}{([][])[]}>

훌륭하고 읽기 쉬운 코드를 보려면 첫 번째 버전을 살펴보십시오. 중급 버전에는 모든 종류의 훌륭하고 위협적인 코드가 포함되어 있으며이 버전을 이해하는 데 도움이됩니다.


명시 적 튜플 대신 정의 (!)=(,)하고 사용하여 몇 바이트를 절약 할 수 있다고 생각합니다 !.
Zgarb

당신이 정의하는 경우 m xd x같은 1#x0#x, 당신은 사건을 병합 할 수 있습니다 m[x]d[x]내가 저장 생각 하나에 일부는 너무 바이트.
Zgarb

@Zgarb 감사합니다! 나는 !트릭이 지불하지 않는 마지막 쌍을 거의 놓쳤다 . 두 번째 제안은 사악합니다. 거의 읽을 수있는 코드가 있습니다 ... 영리한!
Christian Sievers

훗, 난 그냥 정의 실현 s%(c:i)=(s?c,i)s?')'=sum s당신이 반복 제거 할 수 있기 때문에 등을하는 것이 훨씬 짧아집니다 i들. .. 잠깐만 요, 아마도 s%(_:i)사건 때문에 효과가 없을 것입니다 .
Zgarb

1
에 역 따옴표를 잃게 elem하고 div좀 더 바이트를 저장해야하는.
Zgarb

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)

설명 : regexp는 처리되지 않은 첫 번째 닫는 대괄호를 찾고 해당하는 여는 대괄호와 그 사이의 인수와 일치합니다. 인수는 분할 슬프게 (동작에 따라 감소 '('와 '['에 대한 최적의 쌍 아니다 +하고 -), 또는 다음 인수가없는 경우에 적합한 값은 값 자로 다시 정합이 최적 인 (계산 결과는 다른 결과와 구분하기 위해 선행 공백으로 대체되고, 더 이상 변경 사항이 없을 때까지 재귀 적으로 호출되어 결과 값을 반환합니다. 예:

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

f ( "([] [])") => 0 (2 대신)
zeppelin

f ( "[]") => 0, "[]"는 모든 실패한 테스트의 일부이므로 다른 테스트도 실패합니다 ( 응답에 테스트 코드를 제공 할 수 있음 ).
zeppelin

@zeppelin 죄송합니다. 골프가 잘못되었습니다. 이전 버전으로 되돌 렸지만 슬프게도 몇 바이트가 소요됩니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.