Regex (รสชาติ PCRE), 66 (65🐌) ไบต์
แรงบันดาลใจจากการเห็นว่าทั้งMartin Enderและjaytea , อัจฉริยะสองคนของ regex เขียนโซลูชันของ regex ให้กับกอล์ฟรหัสนี้ฉันเขียนของตัวเองตั้งแต่เริ่มต้น การตรวจสอบเฉพาะนายกที่มีชื่อเสียงไม่ปรากฏที่ใดก็ได้ในโซลูชันของฉัน
อย่าอ่านสิ่งนี้หากคุณไม่ต้องการให้เวทมนตร์ Regex ของคุณเสียหาย หากคุณต้องการถ่ายภาพเพื่อหาเวทมนตร์นี้ด้วยตัวเองฉันขอแนะนำให้เริ่มต้นด้วยการแก้ปัญหาบางอย่างใน ECMAScript regex:
- จับคู่หมายเลขเฉพาะ (ถ้าคุณไม่คุ้นเคยกับการทำสิ่งนี้ใน regex)
- จับคู่พลังของ 2 (ถ้าคุณยังไม่ได้ทำ) หรือเพียงแค่ทำงานผ่านRegex Golfซึ่งรวมถึง Prime และ Powers ตรวจสอบให้แน่ใจว่าได้ทำทั้งชุดปัญหาคลาสสิกและ Teukon
ค้นหาวิธีที่สั้นที่สุดในการจับคู่พลังของ N โดยที่ N เป็นค่าคงที่ (เช่นที่ระบุใน regex ไม่ใช่อินพุต) ซึ่งสามารถประกอบได้ (แต่ไม่จำเป็นต้องเป็น) ตัวอย่างเช่นจับคู่พลังของ 6
ค้นหาวิธีการจับคู่พลัง Nth โดยที่ N มีค่าคงที่> = 2 ตัวอย่างเช่นจับคู่สี่เหลี่ยมที่สมบูรณ์แบบ (สำหรับวอร์มอัพจับคู่มหาอำนาจ )
จับคู่คำชี้แจงการคูณที่ถูกต้อง ตรงกับตัวเลขสามเหลี่ยม
จับคู่หมายเลขฟีโบนักชี (ถ้าคุณบ้าอย่างที่ฉันเป็น) หรือถ้าคุณต้องการที่จะยึดติดกับสิ่งที่สั้นกว่าให้จับคู่คำแถลงการยกกำลังที่ถูกต้อง (สำหรับการอุ่นเครื่อง โบนัสทำเช่นเดียวกันกับหมายเลขใด ๆ ปัดเศษตามที่คุณต้องการ) หรือตัวเลขแฟคทอเรียล (สำหรับวอร์มอัพจับคู่หมายเลขดั้งเดิม)
จับคู่ตัวเลขมากมาย (ถ้าคุณบ้าเหมือนฉัน)
คำนวณจำนวนอตรรกยะเพื่อความแม่นยำที่ร้องขอ (เช่นหารอินพุทด้วยสแควร์รูทของ 2 คืนผลลัพธ์การปัดเศษเป็นคู่)
(เอ็นจิ้น regex ที่ฉันเขียนอาจช่วยได้เนื่องจากมันเร็วมากที่เลขเอกภาพทางคณิตศาสตร์ regexes และรวมถึงโหมดตัวเลขแบบเอกนารีซึ่งสามารถทดสอบช่วงของตัวเลขธรรมชาติ ด้วยตัวคั่น) โดยค่าเริ่มต้นจะเป็น ECMAScript ที่เข้ากันได้ แต่มีส่วนขยายเพิ่มเติม (ซึ่งสามารถเลือกเพิ่มชุดย่อยของ PCRE หรือแม้แต่ lookahead โมเลกุลสิ่งที่ไม่มี regex engine อื่น))
ไม่เช่นนั้นอ่านต่อและอ่านGitHub Gist นี้ (คำเตือน, สปอยเลอร์จำนวนมาก) ซึ่งบันทึกการเดินทางของการผลัก ECMAScript regex เพื่อจัดการกับฟังก์ชั่นจำนวนธรรมชาติของการเพิ่มความยากลำบาก (เริ่มต้นด้วยชุดปริศนาของ Teukon การเดินทาง)
เช่นเดียวกับวิธีแก้ปัญหา regex อื่น ๆ สำหรับปัญหานี้อินพุตจะได้รับเป็นตัวเลขสองหลักในหน่วย bijective unary คั่นด้วยเครื่องหมายจุลภาคแทนช่วงที่ครอบคลุม ส่งคืนหมายเลขเดียวเท่านั้น regex สามารถแก้ไขได้เพื่อส่งกลับตัวเลขทั้งหมดที่ใช้ปัจจัยหลักที่เล็กที่สุดเหมือนกัน แต่เป็นการจับคู่ที่มีความยาวผันแปรและต้องใส่\K
lookahead หรือส่งคืนผลลัพธ์เป็นการจับภาพแทนการจับคู่
เทคนิคที่ใช้ที่นี่ของการหารโดยนัยซ้ำ ๆ โดยปัจจัยหลักที่เล็กที่สุดนั้นเหมือนกับเทคนิคที่ใช้ในสตริงการแข่งขันที่มีความยาวคือคำตอบพลังงานที่สี่ที่ฉันโพสต์ในขณะที่กลับ
ไม่มีความกังวลใจเพิ่มเติม:
((.+).*),(?!.*(?=\1)(((?=(..+)(\5+$))\6)*)(?!\2)).*(?=\1)\K(?3)\2$
คุณสามารถลองได้ที่นี่
และเวอร์ชันฟรีที่มีระยะห่างพร้อมความคิดเห็น:
# No ^ anchor needed, because this algorithm always returns a
# match for valid input (in which the first number is less than
# or equal to the second number), and even in /g mode only one
# match can be returned. You can add an anchor to make it reject
# invalid ranges.
((.+).*), # \1 = low end of range; \2 = conjectured number that is the
# smallest number in the set of the largest prime factor of each
# number in the range; note, it is only in subsequent tests that
# this is implicitly confined to being prime.
# We shall do the rest of our work inside the "high end of range"
# number.
(?! # Assert that there is no number in the range whose largest prime
# factor is smaller than \2.
.*(?=\1) # Cycle tail through all numbers in the range, starting with \1.
( # Subroutine (?3):
# Find the largest prime factor of tail, and leave it in tail.
# It will both be evaluated here as-is, and later as an atomic
# subroutine call. As used here, it is not wrapped in an atomic
# group. Thus after the return from group 3, backtracking back
# into it can increase the value of tail – but this won't mess
# with the final result, because only making tail smaller could
# change a non-match into a match.
( # Repeatedly divide tail by its smallest prime factor, leaving
# only the largest prime factor at the end.
(?=(..+)(\5+$)) # \6 = tool to make tail = \5 = largest nontrivial factor of
# current tail, which is implicitly the result of dividing it
# by its smallest prime factor.
\6 # tail = \5
)*
)
(?!\2) # matches iff tail < \ 2
)
# now, pick a number in the range whose largest prime factor is \2
.*(?=\1) # Cycle tail through all numbers in the range, starting with \1.
\K # Set us up to return tail as the match.
(?3) # tail = largest prime factor of tail
\2$ # Match iff tail == \2, then return the number whose largest
# prime factor is \2 as the match.
อัลกอริทึมสามารถย้ายไปยัง ECMAScript ได้ง่ายโดยแทนที่การเรียกรูทีนย่อยด้วยสำเนาของรูทีนย่อยและส่งคืนการจับคู่เป็นกลุ่มการจับภาพแทนการใช้ \ K ผลลัพธ์คือความยาว 80 ไบต์:
((x+)x*),(?!.*(?=\1)((?=(xx+)(\4+$))\5)*(?!\2)).*(?=\1)(((?=(xx+)(\8+$))\9)*\2$)
ลองออนไลน์!
โปรดทราบว่า((.+).*)
สามารถเปลี่ยนเป็น((.+)+)
ลดขนาดได้ 1 ไบต์ (จาก 66 เป็น65 ไบต์ ) โดยไม่สูญเสียฟังก์ชันการทำงานที่ถูกต้อง แต่ regex จะขยายตัวอย่างช้าๆแบบช้า
ลองออนไลน์! (79 รุ่น ECMAScript exponential-slowdown version)