Panfix ไปยังวงเล็บที่ใส่ไว้


16

Quylthulgเป็นภาษาโดย Chris Pressey ที่พยายามแก้ไขปัญหาสัญกรณ์ของ infix โดยใช้สิ่งที่เรียกว่าpanfix :

เช่น postfix Panfix ไม่ต้องการการปรับใช้ Arcane contrivances เช่นวงเล็บเพื่อแทนที่การมาก่อนของโอเปอเรเตอร์ ในเวลาเดียวกัน panfix อนุญาตให้ระบุเงื่อนไขในลำดับและลักษณะเดียวกับมัดซึ่งเป็นสัญกรณ์ธรรมชาติและใช้งานง่ายสำหรับผู้ที่คุ้นเคย


คุณจะได้รับความสะดวกสบายของสัญกรณ์มัดพร้อมกับความไม่น่าสงสัยของคำนำหน้าหรือ postfix? ใช้แน่นอนทั้งสาม!

=y=+*3*x*+1+=

เป็นทางการมากขึ้นปล่อยให้+เป็นโอเปอเรเตอร์aและbเป็นนิพจน์ จากนั้น(a+b)เป็นนิพจน์มัดที่ถูกต้อง (วงเล็บ) การแสดง Panfix ของนิพจน์นั้นคือ+a+b+ที่ juxtaposition แสดงถึงการต่อกัน

เป้าหมายของคุณคือการใช้สตริง panfix และแปลงเป็นมัดมัดเต็ม:

(y=((3*x)+1))

เพื่อความง่ายเราจะทำการเปลี่ยนแปลงดังต่อไปนี้:

  • ตัวดำเนินการสามารถประกอบด้วยอักขระที่ไม่ซ้ำกันสองตัวเท่านั้น (คุณสามารถเลือกได้ แต่ที่นี่ฉันจะใช้*และ+)
  • มีเพียงตัวอักษรเดียวซึ่งประกอบด้วยตัวละครอื่นที่แตกต่างกัน (คุณสามารถเลือกใด ๆ แต่ที่นี่ฉันจะใช้_)
  • อินพุตจะเป็นนิพจน์ Panfix ที่มีรูปแบบที่ดี

สำหรับความซับซ้อนเราจะทำการเปลี่ยนแปลงดังต่อไปนี้:

  • ผู้ประกอบการสามารถประกอบด้วยจำนวนอักขระที่เป็นบวกใด ๆไม่ใช่เพียงหนึ่งตัวอักษร

สิ่งนี้ทำให้ความท้าทายมีความยุ่งยากมากขึ้นเนื่องจากคุณไม่สามารถระบุได้ว่าสตริงย่อยของตัวดำเนินการที่กำหนดจะถูกแบ่งพาร์ติชันโดยไม่ได้ดูสตริงที่เหลือหรือไม่

นี่คือการดำเนินการอ้างอิงสำหรับความท้าทายที่ได้รับความอนุเคราะห์จาก @ user202729

กรณีทดสอบ

format: input -> output
+*+_*+_*+++_+*+_*+_*+++ -> ((_*+_)+(_+(_*+_)))
**++*+***++_+_++_+*++*+***_*++*+*****_**_*_*** -> ((((_+_)+_)*++*+***_)*(_*(_*_)))
***_**_***_* -> ((_**_)*_)
+_+_+ -> (_+_)
*+*+++**+***+++++_*+*+++**+***+++++_*+*+++**+***+++++ -> (_*+*+++**+***+++++_)
*++++*+*_*_*+*+++****+_++****+_++****++*+*+++_*+++ -> (((_*_)+*+(_++****+_))*+++_)
+**+_*+_*+*_*+*_*+*_+*_+**+ -> (((_*+_)*_)+(_*(_+*_)))
+**+++++_+++++_+++++*_*+*+_++++++_+++++_+++++++* -> (((_+++++_)*_)+*(_+(_+++++_)))
+*+*+_+*+_+*+*_*+*_*+*+_+*+_+*+*+ -> (((_+*+_)*_)+(_*(_+*+_)))
**_**_**_*_****_* -> ((_*(_*(_*_)))*_)

ฉันใช้โปรแกรมนี้เพื่อสร้างสตริงมัดสำหรับความท้าทายนี้ (การแปลงเป็น panfix เป็นเรื่องเล็กน้อย แต่การย้อนกลับไม่ใช่)




6
**_**_**_*_****_*กรณีทดสอบที่แนะนำ: คำตอบที่ฉันทดสอบได้ล้มเหลวทั้งหมดนี้
Nitrodon

1
ฉันสามารถมีช่องว่างเพิ่มเติมในผลงานของฉันได้(_ + _)ไหม?
Ton Hospel

2
@TonHospel แน่นอน
แยกผลไม้

คำตอบ:


6

Prolog (SWI) , 194 163 ไบต์

บันทึกขนาดใหญ่ถึง 31 ไบต์โดยใช้เคล็ดลับนี้จาก0 ' !

[C|T]/O/R:-C\=x,(T/P/R,concat(C,P,O);O=C,R=T).
[x|R]-x-R.
L-X-R:-L/O/A,A-Y-B,B/O/C,C-Z-D,D/O/R,atomics_to_string(['(',Y,O,Z,')'],X).
X^P:-string_chars(X,L),L-P-[].

โอเปอเรเตอร์^ใช้สำหรับอาร์กิวเมนต์ซ้ายของสตริงที่มีนิพจน์ panfix และตั้งค่าอาร์กิวเมนต์ที่ถูกต้องเป็นสตริงที่มีนิพจน์มัดในวงเล็บที่เกี่ยวข้อง โดยจะใช้เป็นตัวอักษรในสถานที่ของx_

ลองออนไลน์!

คำอธิบาย

เนื่องจาก Prolog เป็นภาษาที่มีการประกาศเราจึงต้องอธิบายความสัมพันธ์ระหว่าง panfix และนิพจน์ที่มีวงเล็บ

คำอธิบายนี้ใช้เวอร์ชันที่ไม่อัปโหลดเล็กน้อย:

oper([C|T],O,R) :- C\=x, oper(T,P,R), concat(C,P,O).
oper([C|T],C,T).

expr([x|R],x,R).
expr(L,X,R) :- oper(L,O,A), expr(A,Y,B), oper(B,O,C), expr(C,Z,D), oper(D,O,R),
               atomics_to_string(['(',Y,O,Z,')'],X).

parenthesize(X,P) :- string_chars(X,L), expr(L,P,[]).

การผลิตหลักของเราคือparenthesizeซึ่งใช้ในนิพจน์ panfix Xเป็นสตริงและส่งออกการแสดงออกมัดมัดที่สอดคล้องกันPเป็นสตริง โดยจะใช้การแปลงสายป้อนลงในรายการของตัวละครแล้วก็ผ่านมันไปstring_charsexpr

exprใช้เวลาในรายการของตัวอักษรLแยกวิเคราะห์การแสดงออก panfix แรกที่พบในLและส่งออกเทียบเท่าวงเล็บและส่วนที่เหลือของรายการของตัวละครX Rมีการแสดงออกสองประเภทที่เป็นไปได้:

  • ถ้าตัวอักษรตัวแรกของLเป็นxแล้วการแสดงออกเป็นและที่เหลือเป็นทุกอย่างหลังจากที่xx
  • มิฉะนั้นให้แยกวิเคราะห์โอเปอเรเตอร์O(ดูoperด้านล่าง); แยกการแสดงออกY; แยกOอีกครั้ง แยกการแสดงออกอื่นZ; และแยกวิเคราะห์Oเป็นครั้งที่สาม Oส่วนที่เหลือเป็นทุกอย่างหลังจากที่อินสแตนซ์ที่สามของ การแสดงออกเป็นผลมาจากการเข้าร่วมY, OและZล้อมรอบด้วยวงเล็บเป็นสตริง

operใช้เวลาในรายการของตัวละครที่ตัวละครตัวแรกเป็นCและส่วนที่เหลือเป็นT; มันจะแยกวิเคราะห์ผู้ประกอบการ (เช่นการทำงานของหนึ่งหรือมากกว่าหนึ่งตัวละครที่ดำเนินการ) และส่งออกผู้ประกอบการและส่วนที่เหลือของรายการของตัวละครO RในรูปแบบการดำเนินการตัวละครCจะต้องมีสิ่งอื่นที่ไม่ใช่x; เช่นกัน

  • ผู้ประกอบการPจะต้องแยกจากTกับส่วนที่เหลือR; ในกรณีนี้Oคือการต่อข้อมูลCและP; หรือ,
  • Oเป็นตัวละครเดียวC; ในกรณีนี้เป็นเพียงRT

ตัวอย่างการทำงาน

ลองหาอินพุท+*+x+x++*x+*สำหรับตัวอย่าง

  • +*+x+x++*x+*เราต้องการที่จะแยกการแสดงออกจาก สิ่งนี้ไม่ได้เริ่มต้นด้วยxดังนั้นเราจึงแยกโอเปอเรเตอร์ตั้งแต่ต้น
  • oper+*+จะแยกเป็นใหญ่ของผู้ประกอบการที่เป็นไปได้เพื่อให้เราลอง
    • x+x++*x+*ต่อไปเราจะแยกการแสดงออกจาก xนี้จะต้องมี
    • ตอนนี้เราพยายามที่จะแยกผู้ประกอบการเดียวกันจาก+*+ +x++*x+*แต่นี้ล้มเหลว
  • ดังนั้นเราจึงย้อนกลับและลองแยกวิเคราะห์โอเปอเรเตอร์+*แทน
    • +x+x++*x+*เราแยกการแสดงออกจาก สิ่งนี้ไม่ได้เริ่มต้นด้วยxดังนั้นเราต้องแยกโอเปอเรเตอร์
    • +ความเป็นไปได้เพียงอย่างเดียวคือ
    • ตอนนี้แยก subexpression x+x++*x+*จาก xนี้จะต้องมี
    • ตอนนี้แยกอีกครั้งจาก++x++*x+*
    • ตอนนี้แยก subexpression x++*x+*อื่นจาก xนี้จะต้องมี
    • สุดท้ายแยกอีกครั้งจาก+++*x+*
    • การแยกวิเคราะห์นิพจน์สำเร็จแล้ว (x+x)เรากลับสตริง
  • กลับไปที่ระดับ recursion ก่อนหน้านี้เราแยกผู้ประกอบการอีกครั้งจาก+*+*x+*
  • ตอนนี้แยก subexpression x+*อื่นจาก xนี้จะต้องมี
  • สุดท้ายแยกอีกครั้งจาก+*+*
  • การแยกวิเคราะห์นิพจน์สำเร็จแล้ว ((x+x)+*x)เรากลับสตริง

เนื่องจากไม่มีอักขระเหลืออยู่เราจึงแปลนิพจน์ได้สำเร็จ


4

Perl, 78 60 58 57 50 ไบต์

รวม+1สำหรับp

ใช้1สำหรับ+และ2สำหรับ*(หรือในความเป็นจริงใด ๆ งานหลักสำหรับผู้ประกอบการใด ๆ )

perl -pe 's/\b((\d+)((?1)|_)\2((?3))\2)\b/($3 $2 $4)/&&redo' <<< 22_22_22_2_2222_2

สำหรับการทดสอบที่สะดวกเมื่อเทียบกับตัวอย่างที่ให้ไว้คุณสามารถใช้สิ่งนี้ซึ่งจะทำการแปลและลบพื้นที่ให้คุณ:

perl -pe 'y/+*/12/;s/\b((\d+)((?1)|_)\2((?3))\2)\b/($3 $2 $4)/&&redo;y/ //d;y/12/+*/' <<< "**_**_**_*_****_*"

3

ทำความสะอาด , 200 192 189 ไบต์

import StdEnv,Text
f"_"=["_"]
f l=["("+a+p+b+")"\\p<-[l%(0,i)\\i<-[0..indexOf"_"l]|endsWith(l%(0,i))l],t<-[tl(init(split p l))],n<-indexList t,a<-f(join p(take n t))&b<-f(join p(drop n t))]

ลองออนไลน์!

นิยามฟังก์ชั่นfการรับStringและการคืนค่าซิงเกิลตัน[String]พร้อมผลลัพธ์ภายใน

บางสิ่งที่เรียบร้อย:

  • ไม่ใช้ regex
  • ทำงานร่วมกับตัวละครใด ๆ สำหรับผู้ประกอบการยกเว้น_

3

เรติน่า 0.8.2 , 138 ไบต์

.+
($&)
+`\((\d+)(_|((?<i>(?<i>\d+))|_(?<-i>\k<i>)+)+(?(i)(?!)))\1(_|((?<i>(?<i>\d+))|_(?<-i>\k<i>)+)+(?(i)(?!)))\1\)
(($2)$1($4))
\(_\)
_

ลองออนไลน์! ลิงค์นั้นรวมถึงกรณีทดสอบที่เร็วกว่า คำอธิบาย: เอ็นจิน regex ใช้การย้อนรอยเพื่อแยกสตริงออกเป็นโทเค็นซึ่งจะถูกผลักหรือเปิดจากiกลุ่มสมดุล มีการเรียกใช้ตัวดำเนินการอย่างน้อยหนึ่งตัวที่ผลักเมื่อเริ่มต้นก่อนตัวแปรแรก หลังจากตัวแปรมีตัวดำเนินการอย่างน้อยหนึ่งตัวถูกจุดซึ่งผู้ประกอบการที่ถูกเรียกใช้หรือตัวแปรอื่นนั้นถูกกฎหมาย ผู้ประกอบการได้รับการผลักดันให้กลุ่มที่ซ้ำกันเพื่อให้พวกเขาสามารถตอกได้อย่างถูกต้อง ตัวอย่าง:

Input           Stack
Push *          * *
Push *++*+***   * * *++*+*** *++*+***
Push +          * * *++*+*** *++*+*** + +
Push +          * * *++*+*** *++*+*** + + + +
Variable _
Pop +           * * *++*+*** *++*+*** + + +
Variable _
Pop +           * * *++*+*** *++*+*** + +
Pop +           * * *++*+*** *++*+*** +
Variable _
Pop +           * * *++*+*** *++*+***
Pop *++*+***    * * *++*+***
Variable _
Pop *++*+***    * *
Pop *           *
Push *          * * *
Variable _
Pop *           * *
Push *          * * * *
Variable _
Pop *           * * *
Variable _
Pop *           * *
Pop *           *
Pop *

น่าเสียดายที่สิ่งนี้ไม่ได้ช่วยให้เราสามารถจับผลลัพธ์เพื่อยึดไว้ดังนั้นผู้ประกอบการภายนอกจึงจับคู่ด้วยตนเอง วงเล็บถูกเพิ่มเข้าด้านนอกดังนั้นขั้นตอนแรกจะล้อมรอบนิพจน์ทั้งหมดในวงเล็บและขั้นตอนสุดท้ายจะลบออกในขณะที่พวกเขาได้แพร่กระจายไปยังตัวแปร


1
สิ่งนี้ก็ล้มเหลว**_**_**_*_****_*เช่นกัน
user202729

@ user202729 ทำงานอยู่ตอนนี้หรือไม่
Neil

@Neil มันทำงานแล้วใช่
Feburous

1

Haskell , 167 166 ไบต์

head.e
e('_':r)=["_",r]
e(x:r)=[x]%r
e _=[]
o%t@(c:r)|[x,u]<-e t,n<-length o,[y,v]<-e$drop n u,all((==o).take n)[u,v]=['(':x++o++y++")",drop n v]|p<-o++[c]=p%r
o%_=[]

ลองออนไลน์! ตัวอย่างการใช้งาน: อัตราผลตอบแทนhead.e "**_**_**_*_****_*" ((_*(_*(_*_)))*_)อักขระทั้งหมดยกเว้น_ถูกตีความว่าเป็นโอเปอเรเตอร์_ตัวมันเองจะระบุตัวระบุ


0

Python 3, 226 ไบต์

from re import*
P=r'([*+]+)'+r'(\(.+?\)|_)\1'*2;R=lambda i,J=lambda i,o:i[:o]+sub(P,lambda o:'('+o[2]+o[1]+o[3]+')',i[o:],1),s=search:s(P,i)and R([J(i,o)for o in range(len(i))if s(P,J(i,o))or J(i,o)[0]+J(i,o)[-1]=='()'][0])or i

Rกำหนดฟังก์ชั่นที่ไม่ระบุชื่อชื่อ

ลองออนไลน์!


โปรดทราบว่าคุณสามารถใช้อักขระอื่นนอกเหนือจาก_*+; นี่เป็นเพียงสิ่งที่ใช้ในตัวอย่าง คุณอาจสามารถใช้สิ่งนี้เพื่อตีกอล์ฟ regexes ของคุณ (เช่นโดยใช้\dแทน[*+])
แยกผลไม้
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.