सरल रिवर्स पोलिश संकेतन प्रोग्रामिंग भाषा के लिए कंपाइलर का अनुकूलन करें


24

विवरण

काल्पनिक प्रोग्रामिंग भाषा (आईपीएल) पोलिश रिवर्स नोटेशन का उपयोग करती है। इसकी निम्न आज्ञाएँ हैं:

  • i - इनपुट नंबर और इसे स्टैक पर धकेलें
  • - स्टैक के गैर-विनाशकारी आउटपुट शीर्ष (संख्या स्टैक पर रहती है)
  • डी - स्टैक के शीर्ष त्यागें
  • पूर्णांक संख्या - इस संख्या को स्टैक पर धकेलें
  • + - * - स्टैक से दो नंबर पॉप करें, संबंधित ऑपरेशन करें और परिणाम को पीछे धकेलें। आईपीएल में कोई विभाजन नहीं है।

आईपीएल केवल पूर्णांकों के साथ काम करता है और इसका उपयोग सरल गणनाओं के लिए किया जाता है। एक आईपीएल कार्यक्रम एक पंक्ति पर लिखा गया है और रिक्त स्थान द्वारा अलग किया गया है। खाली स्ट्रिंग एक वैध आईपीएल कार्यक्रम है।

आईपीएल कार्यक्रम:

i i + o 

दो नंबर इनपुट करता है, उन्हें एक साथ जोड़ता है और परिणाम को आउटपुट करता है।

इनपुट संख्या और पूर्णांक जिन्हें स्टैक में धकेला जा सकता है, वे रेंज [-999, 999] में हैं, हालांकि आउटपुट कोई भी हो सकता है। यदि आपकी भाषा बड़ी संख्या का समर्थन नहीं करती है तो यह ठीक है।

इनपुट / आउटपुट प्रारूप

आप किसी भी इनपुट / आउटपुट फॉर्मेट को तब तक चुन सकते हैं जब तक वह समझने और पढ़ने / लिखने के लिए स्पष्ट न हो: स्ट्रिंग, सूची, टोकन आदि।

कार्य

आपको कुछ IPL कार्यक्रम दिए गए हैं, आपको इसे अनुकूलित करने की आवश्यकता है (लंबाई कम करें):

i 12 + 3 + o d 2 3 + d

अनुकूलन के बाद बन जाएगा

i 15 + o

आपको स्टैक स्थिति को संरक्षित करने की आवश्यकता नहीं है, लेकिन इनपुट और आउटपुट की मात्रा और उनका क्रम मूल और अनुकूलित कार्यक्रम के लिए मेल खाना चाहिए।

तो आईपीएल कार्यक्रम:

-40 i * 2 * o i + 3 1 + o i 2 *

अनुकूलन के बाद बन जाएगा

i -80 * o i 4 o i

या

-80 i * o i 4 o i

(ध्यान दें कि आपको सभी इनपुट को सहेजना होगा, भले ही वे अप्रासंगिक हों)।

परीक्षण मामलों के लिए कोई हार्डकोडिंग नहीं होनी चाहिए, कोड को किसी भी आईपीएल कार्यक्रम पर काम करना चाहिए और आवश्यकताओं को पूरा करने वाले कम से कम आईपीएल कार्यक्रम का उत्पादन करना चाहिए।

स्कोरिंग

डिफ़ॉल्ट कोड-गोल्फ स्कोरिंग।

अद्यतन: @Sanchises सुझाव के अनुसार, स्कोरिंग को शुद्ध कोड गोल्फ स्कोरिंग में बदल दिया गया।

परीक्षण के मामलों:

इनपुट:

(empty string)

संभव उत्पादन:

(empty string)

इनपुट:

i 4 * 2 + 3 * 6 - o

संभव उत्पादन:

i 12 * o

इनपुट:

1 1 + o

संभव उत्पादन:

2 o

इनपुट:

i 2 + 3 + o d 2 3 + d

संभव उत्पादन:

i 5 + o

इनपुट:

-40 i * 2 * o i + 3 1 + o i 2 *

संभव उत्पादन:

-80 i * o i 4 o i

इनपुट:

i i 1 + i 1 + i 1 + i 1 + d d d d o 

संभव उत्पादन:

i i i i i d d d d o 

इनपुट:

i i i 0 * * * o

संभव उत्पादन:

i i i 0 o

इनपुट:

i i i 1 * * * o

संभव उत्पादन:

i i i * * o

इनपुट:

i 222 + i 222 - + o

संभव उत्पादन:

i i + o

इनपुट:

i 2 + 3 * 2 + 3 * 2 + 3 * i * d i 2 + 3 * i + d i o 2 + 2 - 0 * 1 o

संभव उत्पादन:

i i i i i o 1 o

इनपुट:

i 1 + 2 * 1 + o 

संभव उत्पादन:

i 2 * 3 + o

इनपुट:

1 1 + o i 2 + 3 + o d 2 3 + d 4 i * 2 * o i + 3 1 + o i 2 * i i 1 + i 1 + i 1 + i 1 + d d d d o i i i 0 * * * o i i i 1 * * * o i 2 + i 2 - + o i 2 + 3 * 2 + 3 * 2 + 3 * i * d i 2 + 3 * i + d i o 2 + 2 - 0 * 1 o

संभव उत्पादन:

2 o i 5 + o 8 i * o i 4 o i i i i i i d d d d o i i i 0 o i i i * * * o i i + o i i i i i o 1 o

1
एक सवाल: क्या आप को आसान बनाने में कर सकते हैं i i d oकरने के लिए i o i(इनपुट क्रम में है और उत्पादन के क्रम में है) या आप इसे आसान बनाने में नहीं करना चाहिए? (इनपुट और आउटपुट का सेट क्रम में होना चाहिए)
Sanchises

1
@ सनसनी नहीं, इनपुट और आउटपुट क्रम में होना चाहिए। यदि मूल कार्यक्रम इनपुट 2 नंबर आउटपुट से पहले अनुकूलित कुछ भी करना चाहिए।
Андрей Ломакин

1
PPCG में आपका स्वागत है! अच्छी पहली चुनौती!
लुइस फेलिप डी जेउस मुनोज़

6
से समीक्षा की पंक्ति , मुझे नहीं लगता कि इस चुनौती स्पष्ट नहीं है है। यदि आप करते हैं, तो कृपया इसके बारे में टिप्पणी करें।
mbomb007

2
@ मुझे लगता है कि ओपी का मतलब है कि आपको प्रश्न में सूचीबद्ध केवल परीक्षण मामलों को हार्डकोड नहीं करना चाहिए। आपको मनमाने इनपुट का समर्थन करना होगा। परीक्षण मामलों के लिए कोई हार्डकोडिंग नहीं होनी चाहिए, कोड को किसी भी मनमाने ढंग से आईपीएल कार्यक्रम पर
mbomb007

जवाबों:


5

वोल्फ्राम लैंग्वेज (गणितज्ञ) , 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" + "के साथ" प्रतिस्थापित करता है ताकि हमें घटाव से निपटना न पड़े, (2) कमांड की सूची को थोड़ा सरल करता है, ( 3) आदेशों की इस सूची के सभी क्रमों की एक सूची बनाता है और उन लोगों को चुनता है जो पार्स (निष्पादित) होने पर एक ही परिणाम देते हैं, और (4) कमांड की इन सूचियों को थोड़ा सरल करते हैं और कुछ कार्यों को वापस करने के बाद कम से कम उठाते हैं। subtractions।

यह कोड बहुत अक्षम है क्योंकि यह इनपुट कोड के सभी क्रमपरिवर्तन की सूची से गुजरता है। लंबे इनपुट कोड के लिए मैं इस कोड को चलाने की सलाह नहीं देता; लेकिन जैसा कि मैंने पढ़ा कि इस चुनौती में कोई रनटाइम या मेमोरी प्रतिबंध नहीं हैं।

यह कोड सभी "-" ऑपरेशंस को "+" ऑपरेशंस में बदलने के बाद ऑप्टिमाइज़ेशन स्टेप्स करता है, जिसके सिग्नल्स फ़्लिप होते हैं, और केवल अंत में कोड्स को वापस स्ट्रिंग्स में कनवर्ट करते हुए "-" ऑपरेटर को फिर से पेश करता है। इसका तात्पर्य यह है कि "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 1 + i 1 + i 1 + i 1 + d d d d o
ग्रैमी

@ जैसा कि मैंने कहा, यह कोड बड़ी समस्याओं के लिए नहीं चलता है क्योंकि यह कोड स्थान की संपूर्ण दहनशील खोज से गुजरता है। आपकी त्रुटि TIO पर एक आउट-ऑफ-मेमोरी गलती है, और मेरे कोड के कारण नहीं।
रोमन

@ Ii "d 1 + d o" के लिए मेरा कोड "iid o" देता है, जिसे मैं अनुकूलित मानता हूं। "Ii 1 + i 1 + dd o" के लिए यह "iii + d o" देता है, जिसमें अधिक स्पष्ट "iiidd o" अनुकूलन के समान टोकन की संख्या है। मैंने अधिक इनपुट की कोशिश नहीं की है।
रोमन

मेरा मानना ​​है कि इनपुट i 2 * i 2 * + oको अनुकूलित आउटपुट का उत्पादन करना चाहिए i i + 2 * o, लेकिन यह कोड (अडॉप्टिमाइज्ड) इनपुट देता है।
अतिरेक

धन्यवाद @ ह्रास, यह तय हो गया है और आपका उदाहरण अब शामिल किए गए परीक्षण मामलों में से एक है।
रोमन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.