애니 픽스 표기법을 구현하십시오!


16

접두사 표기법에서 연산자는 인수 앞에 오기 때문에 연산자 next()가 재귀 적으로 호출된다고 상상할 수 있습니다 . 대괄호 표기법에서 연산자는 인수 사이를 이동하므로 간단히 구문 분석 트리로 상상할 수 있습니다. 접미사 표기법에서 연산자는 인수 뒤에 오기 때문에 스택 기반으로 상상할 수 있습니다.

접두사 표기법에서 연산자는 어디든 갈 수 있습니다 * . 연산자가 나타나고 인수가 충분하지 않은 경우 연산자는 인수가 충분할 때까지 기다립니다. 이 과제를 해결하려면 매우 기본적인 애니 픽스 평가기를 구현해야합니다. (주 anyfix 난 당신과 함께 놀 수있는 포기하는 레크리에이션 언어라고 여기 또는 체크 아웃 여기가 )

다음 명령을 지원해야합니다.

(아티스트 1)

  • 복제
  • 부정

(아티스트 2)

  • 부가
  • 곱셈
  • 평등 : 반환 0또는 1.

이 명령에 공백이 아닌 5 개의 기호를 사용하도록 선택할 수 있습니다. 데모 목적으로, "복제, ×곱셈 및 +덧셈으로 사용합니다.

리터럴의 경우 음이 아닌 정수만 지원하면되지만 통역사는 모든 정수를 포함 할 수 있어야합니다 (언어의 (합리적인) 정수 범위 내).

예를 살펴 보겠습니다 : 10+5. 스토리지는 대기열이 아닌 스택으로 작동해야합니다. 먼저 스택은에서 시작 []하고 대기열에있는 운영자 목록은에서 시작합니다 []. 그런 다음 리터럴 10을 평가하여 스택을 만듭니다 [10]. 다음으로 연산자 +가 평가되는데 두 개의 인수가 필요합니다. 그러나 스택에는 하나의 인수 만 있으므로 대기중인 연산자 목록이됩니다 ['+']. 그런 다음 리터럴 5을 평가하여 스택을 만듭니다 [10, 5]. 이 시점에서 연산자 '+'를 평가하여 스택 [15]과 대기열을 []만듭니다.

최종 결과는해야한다 [15]위해 + 10 5, 10 + 5하고 10 5 +.

더 어려운 예를 보자 : 10+". 스택과 큐는 다음과 같이 시작 []하고 []. 10스택을 만드는 첫 번째 평가 [10]됩니다. 다음으로, +인수가 충분하지 않기 때문에 스택을 변경하지 않고 대기열을 만듭니다 ['+']. 그런 다음 "평가됩니다. 이것은 즉시 실행될 수 있으므로 스택을 [10, 10]만듭니다. +스택이 [20]되고 큐 가되도록 평가할 수 있습니다 []. 최종 결과는 [20]입니다.

작업 순서는 어떻습니까?

를 보자 ×+"10 10. 스택과 큐는 다음과 같이 시작합니다 [].

  • ×: 스택이 변경되지 않고 대기열이됩니다 ['×'].
  • +: 스택이 변경되지 않고 대기열이됩니다 ['×', '+'].
  • ": 스택이 변경되지 않고 대기열이됩니다 ['×', '+', '"'].
  • 10: 스택이됩니다 [10]. ×첫 번째로 표시되므로 평가할 첫 번째 연산자 여야 하지만 "즉시 실행할 수 있고 가능한 연산자가 없으므로 평가됩니다. 스택이 [10, 10]되고 대기열이됩니다 ['×', '+']. ×이제 스택 [100]과 대기열 을 만드는 평가할 수 있습니다 ['+'].
  • 10: 스택이가 되어 평가할 [100, 10]+있습니다. 스택이 [110]되고 대기열이됩니다 [].

최종 결과는 [110]입니다.

이 데모에 사용 된 명령은 anyfix 언어의 명령과 일치합니다. 그러나 마지막 예제는 통역사의 버그로 인해 작동하지 않습니다. (면책 조항 : 귀하의 제출물은 anyfix 해석기에서 사용되지 않습니다)

도전

공백이 아닌 숫자가 아닌 문자 5 개를 선택하고 위의 사양에 따라 anyfix 인터프리터를 작성하십시오. 프로그램은 단일 배열 또는 여기에 포함 된 값을 출력 할 수 있습니다. 값 스택에는 실행이 끝날 때 단일 값만 포함되며 실행이 끝날 때 연산자 큐가 비어있게됩니다.

이것은 이므로 바이트 단위의 가장 짧은 코드가 이깁니다.

테스트 사례

이 테스트 사례의 경우 복제본은 " , 음수 -, 덧셈은 +, 곱셈은 ×같고 동등은 =입니다.

Input -> Output
1+2×3 -> 9
1"+"+ -> 4
2"××" -> 16
3"×+" -> 18
3"+×" -> 36
123"= -> 1 ("= always gives 1)
1+2=3 -> 1
1"=2+ -> 3
1-2-+ -> -3
-1-2+ -> 3 (hehe, the `-1` becomes `+1` at the `-` rather than making the `2` a `-1`)
+×"10 10 -> 200 (after the 10 is duplicated (duplication is delayed), 10 + 10 is performed and then 20 * 10, giving 200)

규칙

  • 표준 허점 적용
  • 원하는 경우 anyfix 공식 통역사를 이용하여 골프를 타실 수 있습니다. 끔찍하게 잃을 것으로 예상됩니다.

입력은 문자열로 제공되고 문자열 표현 중 하나의 배열 인 단일 정수로 출력됩니다. 입력에 공백, 숫자 및 선택한 5 자만 포함한다고 가정 할 수 있습니다.

* 사실 아니다


2
어디든 가십시오 * ™.
Jonathan Allan

평등 연산자의 결과는 무엇입니까? 0그리고 1?
Felix Palmen

1
@JonathanAllan 위 참조; 명령 립을 제거했습니다
HyperNeutrino

1
트윗 담아 가기
HyperNeutrino

1
×+"10 10테스트 사례 또는 1) 공백을 사용하고 2) 복제본 사용을 지연시키는 다른 예제를 포함해야합니다. 연산자 (전혀 놓친 두 가지 .
Arnauld

답변:


5

자바 스크립트 (ES6) 204 203 200 바이트

정수를 반환합니다.

e=>e.replace(/\d+|\S/g,v=>{for((1/v?s:v>','?u:b)[U='unshift'](v);!!u[0]/s[0]?s[U](u.pop()>'c'?s[0]:-S()):!!b[0]/s[1]?s[U](+eval(S(o=b.pop())+(o<'$'?'==':o)+S())):0;);},s=[],u=[],b=[],S=_=>s.shift())|s

사용 된 문자 :

  • +: 추가
  • *: 곱셈
  • #: 평등
  • d: 복제
  • -: 부정

테스트 사례

형식화 및 의견

e => e.replace(                     // given an expression e, for each value v matching
  /\d+|\S/g, v => {                 // a group of digits or any other non-whitespace char.
    for(                            //   this loop processes as many operators as possible
      (                             //   insert v at the beginning of the relevant stack:
        1 / v ? s : v > ',' ? u : b //     either value, unary operator or binary operator
      )[U = 'unshift'](v);          //     (s[], u[] or b[] respectively)
      !!u[0] / s[0] ?               //   if there's at least 1 value and 1 unary operator:
        s[U](                       //     unshift into s[]:
          u.pop() > 'c' ?           //       for the duplicate operator:
            s[0]                    //         a copy of the last value
          :                         //       else, for the negative operator:
            -S()                    //         the opposite of the last value
        ) :                         //     end of unshift()
      !!b[0] / s[1] ?               //   if there's at least 2 values and 1 binary operator:
        s[U](                       //     unshift into s[]:
          +eval(                    //       the result of the following expression:
            S(o = b.pop()) +        //         the last value, followed by the
            (o < '$' ? '==' : o) +  //         binary operator o with '#' replaced by '=='
            S()                     //         followed by the penultimate value
          )                         //       end of eval()
        ) : 0;                      //     end of unshift()
    );                              //   end of for()
  },                                // end of replace() callback
  s = [],                           // initialize the value stack s[]
  u = [],                           // initialize the unary operator stack u[]
  b = [],                           // initialize the binary operator stack b[]
  S = _ => s.shift()                // S = helper function to shift from s[]
) | s                               // return the final result

이것이 효과가 있다고 생각하지 마십시오 -1+-2. -3 대신 3을 반환합니다.
Rick Hitchcock

1
@RickHitchcock 내 이해는 두 번째 --1즉시 적용해야한다는 것 입니다.
Arnauld

나는 다른 연산자 뒤에 오는 두 번째 -와 함께 갈 것이라고 생각합니다 . 아마도 @HyperNeutrino가 명확히 할 수 있습니다. 일부 상황에서는 부정 연산자가 모호 할 수 있습니다. 2
Rick Hitchcock

3

자바 스크립트 (ES6) 162 152 143 150 바이트

(s,N=s.replace(/(-?\d+)-|-(-)/g,'- $1 ').match(/(- ?)*?\d+|R/g))=>+eval(`R=${N[0]>'9'?N[1]:N[0]},${s.match(/[+*=]/g).map((o,i)=>'R=R'+o+'='+N[i+1])}`)

약간 골퍼되지 않음 :

(s,
 N=s.replace(/(-?\d+)-|-(-)/g,'- $1 ').      //change postfix negatives to prefix,
                                             //and change "--" to "- - "
     match(/(- ?)*?\d+|R/g)                  //grab numbers and duplicates
)=>+eval(`R=${N[0] > '9' ?  N[1] : N[0]},    //handle a delayed duplicate
          ${s.match(/[+*=]/g).               //grab the operators
              map((o,i)=>'R=R'+o+'='+N[i+1]) //create a comma-separated list of assignments
           }
         `)

설명

내가 사용하고 *곱셈과 R중복을 위해. 다른 연산자는 질문과 동일합니다.

N 숫자의 배열이됩니다 (중복 포함).

그만큼 replace 음의 부호가 오는 경우 처리 수 있습니다. 예를 들어, 변경됩니다 1-- 1-1-- -1 .

내에서 eval, s.match이항 연산자의 배열을 만듭니다. 이 요소는 요소보다 요소가 항상 하나 더 적습니다 N.

함수의 결과는 eval 는 숫자와 연산자의 매핑 .

여기가 무엇입니까 eval 각 테스트 사례에 대한 .

0+2*3        R=0,R=R+=2,R=R*=3        = 6 
1+2*3        R=1,R=R+=2,R=R*=3        = 9 
1R+R+        R=1,R=R+=R,R=R+=R        = 4 
2R**R        R=2,R=R*=R,R=R*=R        = 16 
3R*+R        R=3,R=R*=R,R=R+=R        = 18 
3R+*R        R=3,R=R+=R,R=R*=R        = 36 
123R=        R=123,R=R==R             = 1 
1+2=3        R=1,R=R+=2,R=R==3        = 1 
1R=2+        R=1,R=R==R,R=R+=2        = 3 
1-2-+        R=- 1,R=R+=- 2           = -3 
-1-2+        R=1,R=R+=2               = 3 
*+R10 10     R=10,R=R*=10,R=R+=10     = 110 
+*R10 10     R=10,R=R+=10,R=R*=10     = 200 
-1+--2       R=-1,R=R+=- -2           = 1 
-1+-2        R=-1,R=R+=-2             = -3 

JavaScript 표현식의 쉼표 연산자는 마지막 표현식의 결과를 리턴하므로 map 리턴 자동으로 사용 가능한 표현식을 리턴합니다.

+(가) 이전에 서명이 필요합니다 eval변경 true1false0 .

사용 R모두 변수로 복제 연산자 하면map 의 하위 표현식이 됩니다.

테스트 사례 :


2
나는 replace작품이 의도 한대로 생각하지 않습니다 . 이 수익률 3에 대한 -1+--2내 생각과는 1(올바른 것 1에 대한 두 번째 인수가되기 전에 변경은 세 번에 서명 +을 사용할 수의 결과 -1 + 2).
Felix Palmen

@FelixPalmen, 좋은 캐치. 이제 수정되었습니다.
Rick Hitchcock

2

자바 스크립트, 321 311 바이트

_="f=a=>(a.replace(/\\d+|./g,mq!~(b='+*=\"- '.indexOf(a))|b>2j3j4j5&&o+aw1/y?(y*=-1wcz:1/y?oywcz:hz,rql.map(z=>m(lki,1)[0],i)),hq1/s[1]?sk0,2,+eval(`y${a=='='?a+a:a}s[1]`)):cz,cqlki,0,a),s=[],l=[],e='splice'),s)z(a,i)ys[0]w)^r``:q=z=>os.unshift(k[e](j?b-";for(i of"jkoqwyz")with(_.split(i))_=join(pop());eval(_)

온라인으로 사용해보십시오!

5 개의 문자는 *곱셈을 제외하고 는 질문에서와 동일 합니다.
스크립트는 RegPack을 사용하여 압축됩니다 . 원본 스크립트는 _평가 후 변수에 저장됩니다 .


이것이 효과가 있다고 생각하지 마십시오 -1+-2. -3 대신 3을 반환합니다.
Rick Hitchcock

@RickHitchcock. 왜 -3대신에 돌아와야한다고 생각 3합니까?

부정 연산자를 오해하고있을 수 있습니다. 일반적으로 -1 + -2되어 -3있지만로서 해석 할 수 있어야 --1 + 2대신?
Rick Hitchcock

1
@RickHitchcock. 결과가 확실합니다 3. 2스택에 오기 전에 두 번째 -는 평가되므로 1 2 +실제로는 3입니다. 아, 아마 당신도 답변을 편집해야합니다.

당신 말이 맞을 것입니다. 당신과 Arnauld는 같은 대답을 얻었고, 나는 OP에게 설명을 요청했습니다. 가능하다면 다시 투표 해주세요.
Rick Hitchcock

1

하스켈 , 251 바이트

(#([],[]))
(x:r)#(o,n)|x>'9'=r#h(o++[x],n)|[(a,t)]<-lex$x:r=t#h(o,read a:n)
_#(o,n:_)=n
h=e.e
e(o:s,n:m:r)|o>'N'=e(s,g[o]n m:r)
e(o:s,n:r)|o=='D'=e(s,n:n:r)|o=='N'=e(s,-n:r)
e(o:s,n)|(p,m)<-e(s,n)=(o:p,m)
e t=t
g"a"=(+)
g"m"=(*)
g"q"=(((0^).abs).).(-)

온라인으로 사용해보십시오! 다음과 같은 문자를 사용 : a추가 할, m곱셈, q평등을 위해, D중복과 N부정을 위해. ( e평등 을 위해 사용 하고 싶었지만 숫자로 lex구문 분석 하는 문제가 발생했습니다 2e3.) 사용법 예 : (#([],[])) "2a3 4m"yields 20.


1

6502 머신 코드 (C64), 697 바이트

00 C0 A2 00 86 29 86 26 86 27 86 28 86 4B 86 4C 86 CC 20 E4 FF F0 FB C9 0D F0
10 C9 20 30 F3 A6 27 9D B7 C2 20 D2 FF E6 27 D0 E7 C6 CC A9 20 20 1C EA A9 0D
20 D2 FF 20 95 C0 20 09 C1 20 95 C0 A6 26 E4 27 F0 4E BD B7 C2 E6 26 C9 20 F0
E8 C9 2D D0 09 A6 4C A9 01 9D B7 C3 D0 32 C9 22 D0 09 A6 4C A9 02 9D B7 C3 D0
25 C9 2B D0 09 A6 4C A9 81 9D B7 C3 D0 18 C9 2A D0 09 A6 4C A9 82 9D B7 C3 D0
0B C9 3D D0 0D A6 4C A9 83 9D B7 C3 E6 28 E6 4C D0 A3 4C 8A C2 A6 29 F0 6F A4
28 F0 6B CA F0 4B C6 28 A6 4B E6 4B BD B7 C3 F0 F5 30 14 AA CA D0 0B 20 7B C2
20 E1 C1 20 4D C2 D0 D9 20 5C C2 D0 D4 29 0F AA CA D0 0B 20 6D C2 20 08 C2 20
4D C2 D0 C3 CA D0 0B 20 6D C2 20 16 C2 20 4D C2 D0 B5 20 6D C2 20 F4 C1 20 4D
C2 D0 AA A4 4B B9 B7 C3 F0 02 10 AC C8 C4 4C F0 0F B9 B7 C3 F0 F6 30 F4 AA A9
00 99 B7 C3 F0 A6 60 A0 00 A6 26 E4 27 F0 15 BD B7 C2 C9 30 30 0E C9 3A 10 0A
E6 26 99 37 C4 C8 C0 05 D0 E5 C0 00 F0 08 A9 00 99 37 C4 20 39 C2 60 A2 FF E8
BD 37 C4 D0 FA A0 06 88 CA 30 0A BD 37 C4 29 0F 99 37 C4 10 F2 A9 00 99 37 C4
88 10 F8 A9 00 8D 3D C4 8D 3E C4 A2 10 A0 7B 18 B9 BD C3 90 02 09 10 4A 99 BD
C3 C8 10 F2 6E 3E C4 6E 3D C4 CA D0 01 60 A0 04 B9 38 C4 C9 08 30 05 E9 03 99
38 C4 88 10 F1 30 D2 A2 06 A9 00 9D 36 C4 CA D0 FA A2 10 A0 04 B9 38 C4 C9 05
30 05 69 02 99 38 C4 88 10 F1 A0 04 0E 3D C4 2E 3E C4 B9 38 C4 2A C9 10 29 0F
99 38 C4 88 10 F2 CA D0 D6 C0 05 F0 06 C8 B9 37 C4 F0 F6 09 30 9D 37 C4 E8 C8
C0 06 F0 05 B9 37 C4 90 F0 A9 00 9D 37 C4 60 A9 FF 45 FC 85 9F A9 FF 45 FB 85
9E E6 9E D0 02 E6 9F 60 A2 00 86 9F A5 FB C5 FD D0 07 A5 FC C5 FE D0 01 E8 86
9E 60 A5 FB 18 65 FD 85 9E A5 FC 65 FE 85 9F 60 A9 00 85 9E 85 9F A2 10 46 FC
66 FB 90 0D A5 FD 18 65 9E 85 9E A5 FE 65 9F 85 9F 06 FD 26 FE CA 10 E6 60 20
33 C1 A6 29 AD 3D C4 9D 3F C4 AD 3E C4 9D 3F C5 E6 29 60 A6 29 A5 9E 9D 3F C4
A5 9F 9D 3F C5 E6 29 60 A6 29 BD 3E C4 9D 3F C4 BD 3E C5 9D 3F C5 E6 29 60 C6
29 A6 29 BD 3F C4 85 FD BD 3F C5 85 FE C6 29 A6 29 BD 3F C4 85 FB BD 3F C5 85
FC 60 A6 29 BD 3E C5 10 13 20 7B C2 20 E1 C1 20 4D C2 A9 2D 20 D2 FF A6 29 BD
3E C5 8D 3E C4 BD 3E C4 8D 3D C4 20 8B C1 A9 37 A0 C4 4C 1E AB

온라인 데모

Usage sys49152 를 입력 한 다음 anyfix 표현식을 입력하고 return 키를 누르십시오.

  • 오류 검사가 거의 없으므로 유효하지 않은 표현식에서 재미있는 출력을 기대하십시오.
  • 곱셈의 상징은 * 다른 모든 것입니다.
  • 최대 입력 길이는 256 자이며 대기열에 127 명을 초과 할 수 없습니다.
  • 입력 루틴 제어 문자를 처리하지 않으므로 잘못 입력하지 마십시오.
  • 정수는 16 비트 부호이며 오버플로는 자동으로 줄 바꿈됩니다.
  • 이 CPU도 곱셈을 모르는 및 C64 OS / ROM이 당신에게 제공하지 않기 때문에 바이트 수는 조금 큰 어떤 진수 문자열에서 /에 정수를 arithmetics 또는 전환.

다음은 읽을 수있는 ca65 스타일 어셈블러 소스 코드 입니다.


1

VB.NET (.NET 4.5) 615 576 바이트

Felix Palmen에게 -39 바이트 \r\n\n

필요 Imports System.Collections.Generic(바이트 수에 포함)

Dim s=New Stack(Of Long),q=New List(Of String),i=Nothing,t=0,c=0
Function A(n)
For Each c In n
If Long.TryParse(c,t)Then
i=i &"0"+t
Else
If c<>" "Then q.Add(c)
If i<>A Then s.Push(i)
i=A
End If
If i=A Then E
Next
If i<>A Then s.Push(i)
E
A=s
End Function
Sub E()
c=s.Count
If c=0Then Exit Sub
For Each op In q
If op="-"Or op="d"Or c>1Then
Select Case op
Case"*"
s.Push(s.Pop*s.Pop)
Case"+"
s.Push(s.Pop+s.Pop)
Case"="
s.Push(-(s.Pop=s.Pop))
Case"-"
s.Push(-s.Pop)
Case"d"
s.Push(s.Peek)
End Select
q.Remove(op)
E
Exit Sub
End If
Next
End Sub

진입 점은 Function A이며, 문자열을 입력으로 사용하여Stack(Of Long) .

기호 :

  • 추가- +
  • 곱셈- *
  • 평등- =
  • 부정- -
  • 복제- d

개요 :

함수 A는 입력을 받아 토큰 화합니다. a Long?를 사용하여 여러 자리 정수에 대한 누계를 계산합니다.Nothing 계산합니다. 이는 현재 정수를 읽지 않음 나타냅니다.

서브 루틴 E은 정수 스택과 연산자 큐를 가져 와서 접미사 표기법을 평가합니다. 남아있는 동작이 없을 때까지 재귀 적으로 호출합니다.

선언과 매개 변수 전달 모두에서 바이트를 절약하기 위해 전역 매개 변수를 한 번에 선언합니다.

반환 값 A은 일치하는 변수에 값을 할당하여 설정됩니다 A.

VB는와 True동일 -1하므로 연산이 올바른 값을 얻기 위해 결과를 무효화해야합니다.

온라인으로 사용해보십시오!


추가하는 것이 좋습니다 온라인으로보십시오!
Felix Palmen

btw를 사용하면 Imports바이트 수만 얻습니다. 576잘못 계산 했습니까?
Felix Palmen

@FelixPalmen \r\n대신으로 계산 했으므로 \n불일치가 발생합니다.
Brian J

@FelixPalmen TIO를 추가했습니다. 상기시켜 주셔서 감사합니다! :) (아, 나는 당신이 이미이 포스트를 위해 그것을 만든 것을 몰랐다)
Brian J
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.