ตรงกับการเรียงสับเปลี่ยน!


15

ความท้าทายของคุณคือการสร้าง regex ที่ตรงกับการเปลี่ยนแปลงสตริงของตัวเองทุกอย่างและไม่มีอะไรอื่น การแข่งขันจะต้องเป็นกรณี ๆ ไป

ตัวอย่างเช่นถ้า regex ของคุณคือ:

ABC

มันควรจะจับคู่ (และตรงเท่านั้น) สตริงเหล่านี้:

ABC
ACB
BAC
BCA
CAB
CBA

ไม่ควรจับคู่สิ่งที่ต้องการ:

AABC (contains an extra A)
ABCD (contains an extra D)
AC   (no B)
AAA  (no B and C, extra 2 A's)
abc  (case-sensitive)

กฎ:

  • คุณได้รับอนุญาตให้ใช้รสชาติของ regex ที่คุณชอบ
  • ช่องโหว่มาตรฐานใช้
  • คุณต้องมีอักขระอย่างน้อยสองตัวในรหัสของคุณ นั่นหมายถึงวิธีแก้ปัญหาเช่น1นั้นไม่ถูกต้อง
  • regex ควรมีเฉพาะ ASCII ที่พิมพ์ได้และไม่มีอะไรอื่น


ที่เกี่ยวข้องเพิ่มเติม: การนับจำนวนตัวอักษรในซอร์สโค้ด
jimmy23013

ฉันคิดว่า(ABC|ACB|BAC|BCA|CAB|CBA)แต่คุณต้องการคำตอบทั่วไป
Stephen Quan

คำตอบ:


11

JavaScript, 64 57 ไบต์

ลบ 4 ไบต์ด้วย Martin Ender

^(?!.*([^])(.*\1){3}]?)[$$[-^?!!.'''-*11{33}5577\\-]{57}$

ลองที่นี่

คำอธิบาย (ล้าสมัย)

^                                  # Beginning of the string.
(?!.*                              # Match only the strings that don't contain...
  (.)(.*\1){4}                     #     5 occurrences of the same character.
  [^1]?[^1]?                       #     Something that doesn't matter.
)
[]zzz^(?!!!.**[)\\1{{44}}666]{64}  # 64 occurrences of these 16 characters.
                                   # Some are duplicated to make sure the regex
                                   # contains 4 occurrences of each character.
\z                                 # End of the string.

2
ฉันคิดว่ามันใช้งานได้ 60: ^(?!.*(\S)(.*\1){3}[^1]?)[]zzSS[-^?!!.'''-*1{33}0066-]{60}\z regex101
Martin Ender

เกือบจะทำงานใน. NET:^(?'4'(?!(.*\4){3})[]$$[\\^^?!!..'-*{}33-5-]){54}$[5]*
jimmy23013

อะไรไม่ทำงาน linefeeds ต่อท้าย?
Martin Ender

@ มาร์ตินใช่
jimmy23013

2

Perl และ PCRE regex, 280 ไบต์

^(?=(.*z){2})(?=(.*\(){43})(?=(.*\)){43})(?=(.*\*){22})(?=(.*\.){23})(?=(.*0){2})(?=(.*1){6})(?=(.*2){16})(?=(.*3){7})(?=(.*4){4})(?=(.*5){1})(?=(.*6){3})(?=(.*7){2})(?=(.*8){2})(?=(.*9){1})(?=(.*=){22})(?=(.*\?){22})(?=(.*\\){11})(?=(.*\^){2})(?=(.*\{){23})(?=(.*\}){23}).{280}\z

(เล็กน้อย) อ่านได้มากขึ้น:

^
(?=(.*z){2})
(?=(.*\(){43})
(?=(.*\)){43})
(?=(.*\*){22})
(?=(.*\.){23})
(?=(.*0){2})
(?=(.*1){6})
(?=(.*2){16})
(?=(.*3){7})
(?=(.*4){4})
(?=(.*5){1})
(?=(.*6){3})
(?=(.*7){2})
(?=(.*8){2})
(?=(.*9){1})
(?=(.*=){22})
(?=(.*\?){22})
(?=(.*\\){11})
(?=(.*\^){2})
(?=(.*\{){23})
(?=(.*\}){23})
.{280}\z

สิ่งนี้จะทำงานในเวลา O (2 ^ n) ตามที่เขียนดังนั้นจึงไม่มีประสิทธิภาพอย่างไม่น่าเชื่อ วิธีที่ง่ายที่สุดในการทดสอบคือการแทนที่ทุกเหตุการณ์ที่เกิดขึ้น.*ด้วย.*?ซึ่งทำให้กรณีที่ตรงกับที่จะตรวจสอบก่อน (หมายความว่ามันตรงกับในเวลาเชิงเส้น แต่ยังคงใช้เวลาชี้แจงถ้ามันไม่ตรงกับ)

แนวคิดพื้นฐานคือเราบังคับความยาวของ regex ให้เท่ากับ 280 และใช้ lookahead assertions เพื่อบังคับให้ตัวละครแต่ละตัวใน regex ปรากฏอย่างน้อยจำนวนหนึ่งครั้งเช่น(?=(.*z){2})บังคับให้zตัวละครปรากฏอย่างน้อยสองครั้ง 2+43+43+22+23+2+6+16+7+4+1+3+2+2+1+22+22+11+2+23+23คือ 280 ดังนั้นเราจึงไม่มีตัวอักษร "พิเศษ" เกิดขึ้น

นี่คือตัวอย่างการเขียนโปรแกรมของautogramประโยคที่อธิบายตัวเองโดยแสดงหมายเลขของอักขระแต่ละตัวที่มี (และในกรณีนี้รวมถึงความยาวทั้งหมดด้วย) ฉันโชคดีที่ได้สร้างมันขึ้นมา (โดยปกติคุณต้องใช้กำลังดุร้าย แต่ฉันสะดุดในวิธีแก้ปัญหานี้ในขณะที่ทดสอบโปรแกรมกำลังเดรัจฉานก่อนที่ฉันจะเขียนเสร็จ)

Perl และ PCRE regex ขนาด 253 ไบต์โดยความร่วมมือกับ Martin Ender

ฉันตั้งสมมติฐานว่าอาจมีวิธีแก้ปัญหาที่สั้นกว่าซึ่งไม่ใช้ตัวเลขบางตัว (น่าจะเป็น 9, 8, หรือ 7) Martin Ender พบหนึ่งดังแสดงด้านล่าง:

^(?=(.*z){2})(?=(.*\(){39})(?=(.*\)){39})(?=(.*\*){20})(?=(.*\.){21})(?=(.*0){4})(?=(.*1){6})(?=(.*2){11})(?=(.*3){6})(?=(.*4){3})(?=(.*5){2})(?=(.*6){3})(?=(.*9){4})(?=(.*=){20})(?=(.*\?){20})(?=(.*\\){9})(?=(.*\^){2})(?=(.*{){21})(?=(.*}){21}).{253}\z

รุ่นที่อ่านได้:

^
(? = (. * z) {2})
(? = (. * \ () {39})
(? = (. * \)) {39})
(? = (. * \ *) {20})
(? = (. * \.) {21})
(? = (. * 0) {4})
(? = (. * 1) {6})
(? = (. * 2) {11})
(? = (. * 3) {6})
(? = (. * 4) {3})
(? = (. * 5) {2})
(? = (. * 6) {3})
(? = (. * 9) {4})
(? = (. * =) {20})
(? = (. * \?) {20})
(? = (. * \\) {9})
(? = (. * \ ^) {2})
(? = (. * {) {21})
(? = (. *}) {21})
. {253} \ Z

ฉันไม่คิดว่าคุณจะต้องหลบหนีพวกมัน{}ในช่วงสองคนสุดท้าย คุณไม่จำเป็นต้องเพิ่มสิ่งต่าง ๆ เช่น(?=(.*5){1})เนื่องจากจะไม่มี5ถ้าคุณไม่มี lookahead นั้น ปัญหาหนึ่งคือการ$อนุญาตให้ป้อนบรรทัดต่อดังนั้นคุณจะต้องใช้ที่\zนั่นแทนที่จะเป็น$จิมมี่ไม่ได้ แต่ที่จะไม่เสียค่าใช้จ่ายไบต์ฉันคิดว่าตั้งแต่คุณบันทึก\ใน lookahead แรก
Martin Ender

ฉันรู้ว่าเป็นไปได้ที่จะละเว้นสิ่งต่าง ๆ เช่นตัวเลข แต่พวกเขากำลังมีเพื่อให้autogramทำงาน การลบส่วนใดส่วนหนึ่งของโปรแกรมจะทำให้ส่วนที่เหลือทั้งหมดหยุดทำงานเนื่องจากไม่ได้อธิบายโปรแกรมอย่างถูกต้องอีกต่อไป (การนับสำหรับแต่ละบรรทัดนับการนับสำหรับแต่ละบรรทัด! ดังนั้นโดยทั่วไปจะเป็นไปไม่ได้ที่จะเปลี่ยนโปรแกรม) สำหรับการ$อนุญาตให้ขึ้นบรรทัดใหม่ในตอนท้ายของสตริง โปรแกรม (โดยปกติแล้วพวกเขาจะทำงานกับรหัสที่ได้รับการแยกวิเคราะห์เป็นบรรทัด)

หรือให้แม่นยำยิ่งขึ้น: ฉันต้องการ(?=(.*5){1})ในกรณีนี้ หากฉันลบมันมีจะเป็น 5 ในโปรแกรมเพราะเส้นตอนนี้จะต้องอ่าน(?=(.*1){6}) (?=(.*1){5})

สำหรับลากเลื่อนบรรทัดมีไม่ดูเหมือนจะเป็นข้อ จำกัด ในการท้าทายกับชนิดของการป้อนข้อมูลเพื่อ regex ของคุณเพื่อที่มักจะหมายความว่ามันควรจะทำงานสำหรับสตริงใด ๆ และการเปลี่ยนแปลง$ที่จะ\zไม่ทำอันตรายใด ๆ (และ doesn ไม่ทำลาย autogram)
Martin Ender

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