식을 Panfix 표기법으로 변환


19

나는 esolangs를 탐색하고,이 언어에 우연히되었다 https://github.com/catseye/Quylthulg .

이 언어에 대한 흥미로운 점은 접두사, 접미사 또는 접두사를 사용하지 않고 "panfix"표기법이라고하는 세 가지를 모두 사용한다는 입니다.

다음은 예입니다. 1+2panfix에서 일반 접두사 를 나타내려면 다음과 같이됩니다 +1+2+. 연산자가 피연산자 앞, 뒤 및 뒤에 어떻게 있는지 확인하십시오. 또 다른 예는 (1+2)*3입니다. 이됩니다 *+1+2+*3*. 공지 사항을 다시 방법 *피연산자에 대한 세 가지 장소에 +1+2+3.

도전

짐작 하셨겠지만이 과제의 과제는 표현식을 접두사에서 접두사로 변환하는 것입니다.

몇 가지 설명 :

  • 네 가지 기본 작업 만 처리하면됩니다. +-*/
  • 단항 버전을 다룰 필요가 없으며 바이너리 만 처리해야합니다.
  • 괄호를 다루어야합니다
  • */그때 의 일반적인 우선 순위 규칙을 가정하고 +-모든 규칙에 대해 왼쪽 연관성을 가정하십시오 .
  • 숫자는 음이 아닌 정수입니다.
  • 선택적으로 입력과 출력 모두에 공백이있을 수 있습니다

테스트 사례

1+2  ->  +1+2+
1+2+3  ->  ++1+2++3+
(1+2)*3  ->  *+1+2+*3*
10/2*5  ->  */10/2/*5*
(5+3)*((9+18)/4-1)  ->  *+5+3+*-/+9+18+/4/-1-*

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

답변:


3

JavaScript (ES6), 160 바이트

f=(s,t=s.replace(/[*-/]/g,"'$&'"),u=t.replace(/^(.*?)([*-9]+)'([*/])'([*-9]+)|([*-9]+)'([+-])'([*-9]+)|\(([*-9]+)\)/,"$1$3$2$3$4$3$6$5$6$7$6$8"))=>t==u?t:f(s,u)

(전 그 문자 코드를 제공하는 모든 사업자를 인용하여 작품 *후 사용할 수를 찾고,) '*'또는 '/'작업, '+'또는 '-'작업 또는 ()의, 그 panfix 표기와 함께 첫 번째 교체. 예:

(5+3)*((9+18)/4-1)
(5'+'3)'*'((9'+'18)'/'4'-'1)
(+5+3+)'*'((9'+'18)'/'4'-'1)
+5+3+'*'((9'+'18)'/'4'-'1)
+5+3+'*'((+9+18+)'/'4'-'1)
+5+3+'*'(+9+18+'/'4'-'1)
+5+3+'*'(/+9+18+/4/'-'1)
+5+3+'*'(-/+9+18+/4/-1-)
+5+3+'*'-/+9+18+/4/-1-
*+5+3+*-/+9+18+/4/-1-*

3

자바 스크립트 (ES6) 285 282 268 267 251 243 241 238 234 232 231 바이트

~ 15 덕분에 바이트 .

f=(I,E=I.match(/\d+|./g),i=0)=>(J=T=>T.map?T.map(J).join``:T)((R=(H,l=(P=_=>(t=E[i++])<")"?R(0):t)(),C,F)=>{for(;(C=P())>")"&&(q=C>"*"&&C<"/")*H-1;)F=q+H?l=[C,l,C,P(),C]:F?l[3]=[C,l[3],C,R(1),C]:l=R(1,l,i--)
i-=C>")"
return l})(0))

JavaScript에서는 Mathematica보다 약간 어렵습니다. 이것은 기본적으로 지나치게 전문화되고 골프를 친 운영자 우선 순위 파서 입니다.

유효하지 않은 입력에서 스택 오버플로가 발생합니다.

데모

언 골프

convert = input => {
  tokens = input.match(/\d+|./g);
  i = 0;
  parse_token = () => (token = tokens[i++]) == "(" ? parse_tree(false) : token;
  parse_tree = (mul_div_mode, left = parse_token()) => {
    while ((oper = parse_token()) != ")" && !((is_plus_minus = oper == "+" || oper == "-") && mul_div_mode)) {
      if (is_plus_minus || mul_div_mode)
        left = [oper, left, oper, parse_token(), oper];
      else if (non_first)
        left[3] = [oper, left[3], oper, parse_tree(true), oper];
      else
        left = parse_tree(true, left, i--);
      non_first = true;
    }
    if (oper != ")")
      i--;
    return left;
  };
  format_tree = tree => tree.map ? tree.map(format_tree).join("") : tree;
  return format_tree(parse_tree(false));
}

S.split``해야 [...S]실제로 도움에 맞게 수 있지만, /\d+|./g그 대신에 선행 작업을.
Neil

감사합니다. 내가 살펴볼 게
PurkkaKoodari

2

수학, 203 195 바이트

이것은 효율적이지는 않지만 일을하는 것처럼 보입니다.

Function[f,ReleaseHold[(Inactivate@f/._[Plus][a_,b_/;b<0]:>a~"-"~-b//Activate@*Hold)//.a_/b_:>a~"/"~b/.{a_Integer:>ToString@a,Plus:>"+",Times:>"*"}]//.a_String~b_~c_String:>b<>a<>b<>c<>b,HoldAll]

이것은 실제 표현식을 사용하고 panfix 표기법으로 문자열을 반환하는 익명 함수입니다. Mathematica는 평가 시간이 아닌 구문 분석시 연산자의 우선 순위를 정렬하므로 중첩은 자동으로 정확해야합니다. 최소한 테스트 케이스가 예상대로 작동합니다.

설명 : 다음과 같이 전체 표현식을 트리로 해석하기가 쉽습니다.

나무

이 단계에서 연산자 (리프가 아닌 모든 노드)는 더 이상 연산자가 아니며 실제로는 같은 문자열로 변환되었습니다 "+". 정수도 문자열로 캐스트됩니다. 그런 다음 반복되는 교체 규칙은 정확히 두 개의 리프가있는 모든 노드를 panfix로 변환합니다 parent-leaf1-parent-leaf2-parent. 일부 반복 후 트리는 단일 문자열로 줄어 듭니다.

바이트 수의 주요 손실은 Mathematica가 해석한다는 것입니다

5 - 4 -> 5 + (-4)
9 / 3 -> 9 * (3^(-1))

그리고 이것은 파싱 시간에도 발생합니다.

패턴도로 a_/b_해석 되기 때문에 약간 다운 되었습니다 a_ * (b_)^(-1). 다른 곳에서도 약간의 최적화가 있습니다.


1

프롤로그, 87 바이트

x(T)-->{T=..[O,A,B]}->[O],x(A),[O],x(B),[O];[T].
p:-read(T),x(T,L,[]),maplist(write,L).

이것은 함수입니다 (주로 전체 프로그램을 작성하는 것은 Prolog에 악의적 인 수준의 상용구를 가지고 있기 때문에 일반적으로 프로그램 을 컴파일 하더라도 실행될 때 REPL을 생성합니다) p. stdin에서 입력을 받고 stdout에서 출력합니다. 입력에 마침표를 추가해야합니다. 이는 Prolog의 입력 루틴이 작동하는 방식의 불행한 결과입니다 (입력에서 마침표는 다른 언어에서 줄 바꾸기를 사용하는 것과 거의 같은 방식으로 사용됨). 답을 실격시킬 수도 있고 그렇지 않을 수도 있습니다.

설명

Prolog의 산술 연산자는 일반적 으로 튜플 생성자로 해석 됩니다. . 그러나 실제 산술 연산자와 동일한 우선 순위 규칙을 따릅니다. 당신이하고, 튜플과 중위 표기법을 형성 할 수 +-결합 덜 단단 이상 */우선 순위가 촬영 그룹 내에서 왼쪽에서 오른쪽으로. 이것이 바로 질문이 요구하는 것입니다. 따라서 입력에서 전체 중첩 튜플을 읽을 수 있으며 이미 올바른 구조를 가지고 있습니다. 그게 뭐야 p.

다음으로 panfix 표기법으로 변환해야합니다. x생성자와 정수의 panfixed 목록에 입력을 변환하고, 거의 직접 영어 문장으로 읽을 수 있습니다 : " xT이다 경우 T생성자와 튜플 O과 인수 A, B다음 O, xA, O, x의는B , O, 다른 T"가. 마지막으로 구분 기호없이 목록을 인쇄하면됩니다 (예 : 목록의 각 요소 maplist를 호출 write하는 데 사용 ).

내 GNU Prolog 버전은 maplist아직 (아직 새 버전에 추가 된) 버전이 아니기 때문에 SWI-Prolog를 사용하여 테스트 했지만, 일반적으로 Prolog 구현간에 상당히 이식 가능해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.