볼프람 언어 (티카) , 733 (728) 690 564 516 506 513 548 바이트
j=Integer;f=Flatten;s=SequenceReplace;A=FixedPoint[f@s[#,{{x_j,p,y_j,t}->{y,t,x*y,p},{x_j,y_j,p}->x+y,{x_j,y_j,t}->x*y,{x_j,p,y_j,p}->{x+y,p},{x_j,t,y_j,t}->{x*y,t},{0,p}|{1,t}->{},{0,t}->{d,0}}]//.{a___,Except[i|o]}->{a}&,#]&;B=Expand@Check[f@FoldPairList[f/@Switch[#2,i,{{i},{#,i@c++}},o,{{Last@#},#},d,{{},Most@#},p,{{},{#[[;;-3]],Tr@#[[-2;;]]}},t,{{},{#[[;;-3]],#[[-2]]*Last@#}},_,{{},{##}}]&,c=0;{},#],x]&;F=MinimalBy[w=A@f[#/.m->{-1,t,p}];z=B@w;s[#,{-1,t,p}->m]&/@A/@Select[Permutations@Join[w,Cases[z /.i@_->i,_j,∞]],B@#==z&],Length][[1]]&
온라인으로 사용해보십시오!
이것은 (1) "-"를 "-1 * +"로 대체하여 뺄셈을 처리 할 필요가없는 4 단계 둘러보기 (2) 명령 목록을 조금 단순화합니다 ( 3)이 명령 목록의 모든 순열 목록을 만들고 파싱 (실행) 할 때 동일한 결과를 제공하는 명령을 선택하고 (4) 특정 명령을 다시 변환 한 후 명령 목록을 조금 단순화하고 가장 짧은 명령 빼기.
이 코드는 입력 코드의 모든 순열 목록을 거치므로 매우 비효율적입니다. 긴 입력 코드의 경우이 코드를 실행하지 않는 것이 좋습니다. 그러나 그것을 읽으 면서이 도전에는 런타임 또는 메모리 제한이 없습니다.
이 코드는 모든 "-"연산을 부호가 뒤집힌 상태에서 "+"연산으로 변환 한 후 최적화 단계를 수행하며, 마지막으로 코드를 다시 문자열로 변환 할 때 "-"연산자를 다시 소개합니다. 이는 예를 들어 "i -1 i * + o"가 "ii-o"에 올바르게 최적화되었음을 의미합니다.
I / O 형식 요구 사항이 매우 느슨하기 때문에이 코드는 코드를 목록으로 가져 와서 반환합니다. 여기서 "+", "-", "*"기호는 각각 p, m, t, 토큰으로 표시됩니다. 문자열과의 변환은 TIO에 제공된 래퍼 함수에서 수행됩니다.
G[S_] := StringReplace[{"p" -> "+", "m" -> "-", "t" -> "*"}]@StringRiffle@
Quiet@F@
ToExpression[StringSplit[S] /. {"+" -> p, "-" -> m, "*" -> t}]
문자열 형식 래퍼를 포함하고 토큰 수 대신 최종 코드 문자열 길이를 최소화하고 몇 가지 변환 기능을 포함한 골프화되지 않은 버전 :
(* convert code string to list of operators *)
inputfilter[s_] := ToExpression[Flatten[StringSplit[s] /.
{"i" -> i, "o" -> o, "d" -> d, "+" -> p, "-" -> {-1, t, p}, "*" -> t}]]
(* convert list of operators to code string *)
outputfilter[s_] := StringReplace[StringRiffle@Flatten@SequenceReplace[s,
{{-1, t, p} -> m, (* convert "-1 t p" back to "-" *)
{x_ /; x < 0, p} -> {-x, m}, (* convert "y x +" to "y -x -" when x<0 *)
{x_ /; x < 0, t, p} -> {-x, t, m}}], (* convert "y x * +" to "y -x * -" when x<0 *)
{"m" -> "-", "p" -> "+", "t" -> "*"}] (* backsubstitution of symbols *)
(* simplify a list of operators somewhat *)
simplifier[s_] := FixedPoint[Flatten@SequenceReplace[#,
{{x_Integer, p, y_Integer, t} -> {y, t, x*y, p}, (* "x + y *" -> "y * (xy) +" *)
{x_Integer, y_Integer, p} -> x + y, (* "x y +" -> "(x+y)" *)
{x_Integer, y_Integer, t} -> x*y, (* "x y *" -> "(xy)" *)
{x_Integer, p, y_Integer, p} -> {x + y, p}, (* "x + y +" -> "(x+y) +" *)
{x_Integer, t, y_Integer, t} -> {x*y, t}, (* "x * y *" -> "(xy) * *)
{0, p} | {1, t} -> {}, (* "0 +" and "1 *" are deleted *)
{x_Integer, i, p} -> {i, x, p}, (* "x i +" -> "i x +" *)
{x_Integer, i, t} -> {i, x, t}, (* "x i *" -> "i x *" *)
{0, t} -> {d, 0}}] //. (* "0 *" -> "d 0" *)
{a___, Except[i | o]} -> {a} &, s] (* delete trailing useless code *)
(* execute a list of operators and return the list of generated outputs *)
parse[s_] := Expand@Quiet@Check[Flatten@FoldPairList[ (* stack faults are caught here *)
Function[{stack, command}, (* function called for every command*)
Flatten /@ Switch[command, (* code interpretation: *)
i, {{i}, {stack, i[inputcounter++]}}, (* output "i" and add input to stack*)
o, {{stack[[-1]]}, stack}, (* output top of stack *)
d, {{}, Most[stack]}, (* delete top of stack *)
p, {{}, {stack[[;; -3]], stack[[-2]] + stack[[-1]]}}, (* add two stack elements *)
t, {{}, {stack[[;; -3]], stack[[-2]]*stack[[-1]]}}, (* multiply two stack elements*)
_, {{}, {stack, command}}]], (* put number onto stack *)
inputcounter = 0; {}, (* start with zero input counter and empty stack*)
s], (* loop over code list *)
x] (* return "x" if an error occurred *)
(* the main function that takes a code string and returns an optimized code string *)
F[s_] := Module[{w, q},
w = simplifier@inputfilter@s; (* convert input to useful form *)
q = parse[w]; (* execute input code *)
MinimalBy[
outputfilter@*simplifier /@ (* simplify and stringify selected codes *)
Select[Permutations[w], (* all permutations of code list *)
parse[#] == q &], (* select only those that give the correct output *)
StringLength] // Union] (* pick shortest solution by length *)
버그 잡기를위한 @redundancy 덕분에 : 파서는 Expand
분산 등가를 처리하기 위해 출력에 적용되어야합니다. 506 → 513
최신 정보
이제로 최적화 1 o 1 + o
합니다 1 o 2 o
. 이것은 놀랍게도 어려운 경우였으며 코드를 훨씬 느리게 만들었습니다. 513 → 548
i i d o
에i o i
(입력 순서에 출력 순서에) 또는 당신이 그것을 간단하지 않겠습니까? (입력 및 출력 세트가 순서대로 있어야 함)