แปลง Expression เป็น Panfix Notation


19

ฉันถูกเรียกดู esolangs และ chanced เมื่อภาษานี้: https://github.com/catseye/Quylthulg

สิ่งหนึ่งที่น่าสนใจเกี่ยวกับภาษานี้คือมันไม่ได้ใช้คำนำหน้า postfix หรือมัดมันใช้ทั้งสามคนเรียกมันว่า "panfix" สัญกรณ์

นี่คือตัวอย่าง เพื่อเป็นตัวแทนของมัดปกติ1+2ใน panfix +1+2+มันจะกลายเป็น: สังเกตว่าผู้ประกอบการมีทั้งก่อนระหว่างและหลังตัวถูกดำเนินการ (1+2)*3อีกตัวอย่างหนึ่งคือ *+1+2+*3*นี้จะกลายเป็น แจ้งให้ทราบอีกครั้งว่า*มีอยู่ในทุกสามสถานที่ที่เกี่ยวกับการถูกดำเนินและ+1+2+3

ความท้าทาย

ดังที่คุณอาจเดาได้งานของคุณในการท้าทายนี้คือการแปลงนิพจน์จากมัดเป็น Panfix

คำอธิบายบางอย่าง:

  • คุณต้องจัดการกับการดำเนินงานพื้นฐานสี่ประการเท่านั้น: +-*/
  • คุณไม่จำเป็นต้องจัดการกับไบนารีรุ่นเดียวเท่านั้น
  • คุณต้องจัดการกับวงเล็บ
  • สมมติว่ากฎที่มีมาก่อนเป็นปกติจาก*/นั้น+-และปล่อยให้การเชื่อมโยงสำหรับพวกเขาทั้งหมด
  • ตัวเลขจะเป็นจำนวนเต็มไม่ใช่ค่าลบ
  • คุณสามารถเลือกที่จะมีช่องว่างทั้งอินพุตและเอาต์พุต

กรณีทดสอบ

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)

ทำงานโดยการอ้างอิงตัวดำเนินการทั้งหมด (ซึ่งให้รหัสอักขระมาก่อน*) จากนั้นมองหาที่มีอยู่'*'หรือ'/'การดำเนินการ'+'หรือ'-'การดำเนินการหรือ()s และแทนที่อันแรกด้วยสัญกรณ์ 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

JavaScript (ES6), 285 282 281 267 251 243 241 238 234 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 นี้เป็นพื้นมากกว่าความเชี่ยวชาญและแข็งแรงเล่นกอล์ฟparser ประกอบการมีความสำคัญ

ทำให้สแต็คโอเวอร์โฟลว์สำหรับอินพุตที่ไม่ถูกต้อง

การสาธิต

Ungolfed

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

@ 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 คัดแยกลำดับความสำคัญของโอเปอเรเตอร์ในเวลาการแยกวิเคราะห์มากกว่าเวลาการประเมินดังนั้นการซ้อนควรถูกต้องแบบอัตโนมัติ อย่างน้อยกรณีทดสอบใช้งานได้ตามที่คาดไว้

คำอธิบาย: มันง่ายพอที่จะตีความการแสดงออกทั้งหมดในรูปของต้นไม้เช่น:

ต้นไม้

ในขั้นตอนนี้ตัวดำเนินการ (ทุกโหนดที่ไม่ใช่ใบไม้) ไม่ได้เป็นตัวดำเนินการอีกต่อไปพวกเขาได้รับการแปลงเป็นสตริงเช่น "+"เพิ่มเติมพวกเขาได้รับจริงแปลงสตริงเช่น จำนวนเต็มยังถูกส่งไปยังสตริง แล้วกฎการเปลี่ยนแปลงซ้ำโหนดที่มีตรงสองใบเพื่อ parent-leaf1-parent-leaf2-parentpanfix หลังจากการวนซ้ำต้นไม้จะลดเป็นสตริงเดียว

การสูญเสียที่สำคัญในการนับไบต์คือ Mathematica ตีความ

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

และสิ่งนี้ก็เกิดขึ้นในเวลาที่แจง

แข็งแรงเล่นกอล์ฟลงเล็กน้อยเนื่องจากรูปแบบถูกตีความว่าเป็นa_/b_ a_ * (b_)^(-1)นอกจากนี้ยังมีการเพิ่มประสิทธิภาพเล็กน้อยที่อื่น


1

Prolog, 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 (พวกเขาใช้จุดในอินพุตในลักษณะเดียวกับที่ภาษาอื่นใช้บรรทัดใหม่) ที่อาจหรืออาจจะไม่ตัดคำตอบ

คำอธิบาย

ดำเนินการทางคณิตศาสตร์ในการเปิดฉากจะถูกตีความตามปกติขณะที่การก่อสร้าง tuple อย่างไรก็ตามพวกเขาปฏิบัติตามกฎที่มีลำดับความสำคัญเท่ากันกับตัวดำเนินการทางคณิตศาสตร์ที่แท้จริง คุณสามารถสร้าง tuples ด้วยสัญกรณ์มัดและ+และ-ผูกแน่นน้อยกว่า*และ/ด้วยความสำคัญกว่าจากซ้ายไปขวาภายในกลุ่ม นี่คือสิ่งที่คำถามถาม ดังนั้นเราสามารถอ่าน tuple ที่ซ้อนกันทั้งหมดจากอินพุตและมีโครงสร้างที่เหมาะสมอยู่แล้ว นั่นคือสิ่งที่pทำ

ต่อไปเราต้องแปลงเป็นสัญกรณ์ panfix xแปลงใส่ลงในรายการ panfixed ของการก่อสร้างและจำนวนเต็มและสามารถอ่านได้เป็นประโยคภาษาอังกฤษเกือบจะตรง " xของTคือถ้าTเป็น tuple กับคอนสตรัคOและข้อโต้แย้งA, Bแล้วO, xของA, O, xของB, Oอื่นT" ในที่สุดเราก็ต้องพิมพ์รายการโดยไม่มีตัวคั่นใด ๆ (เช่นใช้maplistเพื่อโทรwriteองค์ประกอบของรายการแต่ละรายการ)

ฉันใช้ SWI-Prolog เพื่อทดสอบสิ่งนี้เนื่องจาก GNU Prolog รุ่นของฉันยังไม่ได้maplist(เห็นได้ชัดว่ามันถูกเพิ่มเข้าไปในรุ่นที่ใหม่กว่า) แต่โดยทั่วไปแล้วมันควรพกพาได้ง่ายระหว่างการใช้งาน Prolog

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.