ออกแบบภาษา: การจับคู่รูปแบบ 2 มิติ


49

นี่คือรายปักษ์ท้าทาย # 6 กระทู้: การออกแบบภาษา

มีห้องแชทสำหรับความท้าทายนี้ มาร่วมกับเราถ้าคุณต้องการที่จะพูดคุยความคิด!

และตอนนี้สำหรับบางสิ่งที่แตกต่างอย่างสิ้นเชิง ...

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

ความท้าทาย

คุณกำลังออกแบบภาษาที่จับคู่รูปแบบซึ่งช่วยให้คำอธิบายของรูปแบบสองมิติในบล็อกข้อความ โหมดการทำงานของภาษาของคุณจะคล้ายกับการแสดงออกปกติ (แม้ว่าภาษาของคุณไม่จำเป็นต้องมีอะไรที่เหมือนกันกับ regex อื่น ๆ ):

  • ในฐานะที่เป็นอินพุตคุณจะได้รับบล็อกสี่เหลี่ยมเป็นข้อความ คุณอาจคิดว่าข้อความนั้นประกอบด้วยอักขระ ASCII ที่พิมพ์ได้ (0x20 ถึง 0x7E) และบรรทัดใหม่ (0x0A) เพื่อแยกแถวของตาราง
  • หากการจับคู่ตามคำอธิบายรูปแบบสามารถพบได้เป็นส่วนย่อยของบล็อกข้อความนี้การแข่งขันนี้ควรจะกลับหรือพิมพ์ หากการจับคู่นั้นไม่ใช่รูปสี่เหลี่ยมผืนผ้าก็ควรจะมีเบาะไปยังพื้นที่สี่เหลี่ยมที่มีอักขระที่สงวนไว้บางส่วน หากมีการแข่งขันที่ถูกต้องหลายครั้งคุณอาจตัดสินใจเลือกวิธีการจับคู่ที่ส่งคืน (ใหญ่ที่สุดเล็กที่สุดก่อน ฯลฯ )

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

อย่างน้อยที่สุดภาษาของคุณควรจะสามารถจับคู่รูปแบบเป็นส่วนย่อยย่อยที่ต่อเนื่องกันของรูปสี่เหลี่ยม

คำตอบของคุณควรมี:

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

หากคำตอบของคุณต่อยอดจากแนวคิดที่มีอยู่นั่นก็ดี แต่โปรดให้เครดิตเมื่อถึงกำหนด

ส่วนขยาย

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

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

เกณฑ์การให้คะแนน

เป้าหมายหลักของความท้าทายนี้คือการสร้างภาษาการจับคู่รูปแบบ 2D ที่มีประสิทธิภาพซึ่งอาจนำไปใช้ในอนาคต ด้วยเหตุนี้ระบบการให้คะแนนเช่น "ความยาวรวมที่สั้นที่สุดเพื่อแก้ไขตัวอย่าง" จะนำไปสู่การเข้ารหัสที่ซับซ้อนของฟังก์ชั่นบางอย่างด้วยค่าใช้จ่ายในการใช้งานทั่วไป ดังนั้นเราจึงตัดสินใจว่าความท้าทายนี้ดำเนินไปได้ดีที่สุดในฐานะการประกวดความนิยม การส่งด้วยคะแนนเสียงสุทธิมากที่สุดชนะ แม้ว่าเราจะไม่สามารถบังคับให้ผู้คนโหวตได้ แต่นี่เป็นแนวทางบางประการสำหรับสิ่งที่ผู้ลงคะแนนเสียงควรมองหา:

  • ลึกซึ้ง ภาษาสามารถแก้ไขปัญหาได้หลากหลายหรือไม่นอกเหนือจากตัวอย่างที่แสดงในคำถามนี้ มันสนับสนุนส่วนขยายใด ๆ ที่แนะนำหรือไม่
  • การอ่าน สัญกรณ์ใช้งานง่ายแค่ไหน (อย่างน้อยสำหรับผู้ที่รู้ไวยากรณ์พื้นฐาน)
  • Golfitude นี่คือ CodeGolf.SE สำหรับวัตถุประสงค์ของเว็บไซต์นี้แน่นอนว่าจะมีภาษาที่ตรงกันซึ่งต้องการรหัสน้อยมากในการอธิบายรูปแบบ

ตัวอย่างปัญหา

Stack Snippet ต่อไปนี้แสดงปัญหาตัวอย่าง 16 ข้อซึ่งภาษาการจับคู่รูปแบบ 2 มิติสามารถจัดการได้ แต่ละตัวอย่างมีคำอธิบายปัญหาสั้น ๆ และมักจะตามด้วยตัวอย่างอินพุตหนึ่งที่สามารถพบการจับคู่และตัวอย่างหนึ่งที่ไม่พบการจับคู่ (ถ้ามี)

ตามที่ระบุไว้ข้างต้นภาษาของคุณจะต้องสามารถแก้ไขปัญหา 8 ข้อเหล่านี้ได้เท่านั้น ทุกอย่างที่นอกเหนือจากนั้นเป็นตัวเลือก แต่แน่นอนว่าควรเพิ่มจำนวนคะแนนที่คุณได้รับ

(ไม่คุณไม่จำเป็นต้องอ่านโค้ด HTML นั้นกดปุ่ม "เรียกใช้ข้อมูลโค้ด" เพื่อให้เบราว์เซอร์ของคุณแสดงผลได้อย่างดีซึ่งคุณสามารถดูแบบเต็มหน้าจอได้)


ปัญหาเหล่านี้มีการ จำกัด เวลาโดยทั่วไปหรือไม่? ฉันสนใจที่จะแก้ปัญหานี้ แต่ฉันยุ่งมากมันอาจใช้เวลา 2 สัปดาห์ในการทำ
Devon Parsons

7
@DevonParsons ไม่มีกำหนดส่ง
PhiNotPi

ดูน่าสนใจโดยเฉพาะเมื่อคุณสร้างแท็กใหม่สำหรับสิ่งนี้ ฉันคิดว่าควรมีคะแนนโบนัสสำหรับการสร้างภาษา 2 มิติ
mbomb007

1
@ mbomb007 มีคะแนนโบนัสสำหรับการสร้างภาษา 2 มิติ ฉันค่อนข้างแน่ใจว่ามันจะได้รับจำนวน upvotes ที่เหมาะสม ;)
Martin Ender

@ MartinBüttnerฉันไม่รู้จักวิธีการสร้างภาษาจริงๆ มันอาจเป็นสิ่งที่ (ง่าย?) ในการสร้างโปรแกรม Python ที่ใช้ไฟล์ของรหัสภาษาใหม่ของคุณ
mbomb007

คำตอบ:


32

SnakeEx

แก้ไขปัญหา 15/16 จนถึงขณะนี้!

ล่ามออนไลน์ ! - ข้อมูลจำเพาะภาษาเต็ม -แหล่ง Javascript

ภาพหน้าจอของล่าม

แนวคิดเบื้องหลังภาษานี้คือการกำหนด 'งู' ที่เคลื่อนไปรอบ ๆ ตัวอักษรตรวจสอบข้อความโดยใช้ไวยากรณ์เหมือน regex

โปรแกรมใน SnakeEx ประกอบด้วยรายการคำจำกัดความของงูโดยใช้ลำดับของคำสั่งต่างกัน งูสามารถวางไข่งูอื่น ๆ โดยใช้คำจำกัดความเหล่านี้ซึ่งเป็นที่ SnakeEx ได้รับอำนาจมากที่สุด - เราสามารถจับคู่โครงสร้างการแยกและแม้แต่เรียกซ้ำ (ดูตัวอย่างการจับคู่ Paren)

ทุกโปรแกรมจะดูเหมือนชุดของ regexes แต่ด้วยการเพิ่มคำสั่งทิศทางของรูปแบบ<dir>ที่เปลี่ยนทิศทางของงูและเรียกคำสั่งของรูปแบบ{label<dir>params}ที่วางไข่งูมากขึ้น

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

มันไม่รัดกุม แต่มีประสิทธิภาพมากและ (ฉันคิดว่า) อ่านได้ค่อนข้างสวย

อัพเดท

  • เปลี่ยนแล้ว! เป็นตรรกะไม่ใช่และ ~ เพื่อไม่ทำเครื่องหมายที่ตรงกัน
  • เพิ่ม<!>เพื่อแก้ปัญหาลำไส้ใหญ่
  • แก้ไขการจับคู่ข้าม
  • แก้ไขกระดานหมากรุกอย่างน่ากลัวน้อยกว่า
  • เพิ่มไวยากรณ์การปิดล้อม %{min,max}
  • เพิ่มตัวอย่างการสอบถามซ้ำ

โซลูชั่น

15 แก้ไขแล้ว 1 กำลังดำเนินการ

คุณสามารถลองใช้โปรแกรมเหล่านี้ได้อย่างง่ายดายโดยใช้ Online Interpreter ที่ลิงก์ด้านบน!

ปัญหา 1 - การค้นหากระดานหมากรุก

m:{v<R>2}{h<>1}
v:{c<L>A1}+
h:{c<R>A2}+
c:_?(#_)+#?

สำหรับการแนะนำโดยละเอียดเริ่มต้นที่ปัญหา 3

ปัญหาที่ 2 - ตรวจสอบกระดานหมากรุก

m:{v<R>2}{h<>1}
v:${c<L>A1}+$
h:${c<R>A2}+$
c:$_?(#_)+#?$

การสิ้นสุดของงูที่เหมาะสมและมีสัญลักษณ์นอกขอบเขตการจอง$เป็นวิธีหนึ่งที่จะทำให้โปรแกรมจับคู่กับอินพุตทั้งหมดเท่านั้น

ปัญหา 3 - ตรวจหาสี่เหลี่ยมผืนผ้าของตัวเลข

m:{c<R>A1}%{2,}
c:[0-9]%{2,}

mย้ายงูขวาพล่านอย่างน้อย 2 งู ( %{2,}คือการปิดหมายถึง "2 ถึงอินฟินิตี้") ใช้คำนิยาม C ( c) และการย้ายขวา ( <R>) หรือมากกว่าลงในกรณีนี้เพราะทุกทิศทางเป็นญาติกับงูปัจจุบัน Aพระรามเป็นน้ำตาลที่เพียงแค่ระบุว่างูวางไข่ควรย้ายหลังจากที่โทร 1พารามิเตอร์คือวิธีที่เราจะ จำกัด การแข่งขันสี่เหลี่ยม - พารามิเตอร์จำนวนงูใส่ใน "กลุ่ม" การแข่งขันจะไม่ถูกนับเว้นแต่ว่างูทั้งหมดในกลุ่มเดียวกันจะเดินทางในระยะทางเดียวกัน

ปัญหาที่ 4 - การค้นหาคำในการค้นหาคำ

m:<*>GOLF

คำสั่งทิศทาง<*>ระบุว่างูควรเลี้ยวในทิศทางทแยงมุมหรือมุมฉากใด ๆ จากนั้นค้นหา regex ง่าย ๆ

ปัญหาที่ 5 - ตรวจหาอินพุตของสแควร์

m:{v<R>1}{h<>1}
v:${c<L>A1}+$
h:${c<R>A1}+$
c:$.+$

กุญแจสำคัญในที่นี้คือตัวละครพิเศษ$ซึ่งตรงกับถ้างูอยู่นอกขอบเขต เราวางไข่งูแนวนอนและแนวดิ่ง; งูแต่ละตัวมีงูมากขึ้นขณะที่วิ่งตามขอบและทุกคนอยู่ในกลุ่มเดียวกันและจะต้องมีความยาวเท่ากัน

ปัญหาที่ 6 - ค้นหาเครื่องร่อนในเกมแห่งชีวิต

m:<+>[({l1<R>A}{l2<R>A}{l3<R>})({l1<L>A}{l2<L>A}{l3<L>})]
l1:##\.
l2:[(#\.)(\.#)]#
l3:#\.\.

mเริ่มในทิศทางสี่มุมฉากใด ๆ ( <+>) เพื่อให้เกิดการหมุน จากนั้นดูทั้งสามด้านซ้ายหรือขวาตามลำดับเพื่อให้ได้ภาพสะท้อน

(โปรดทราบว่าฉันได้แทนที่ช่องว่างด้วยจุดเท่านั้นเพราะ textareas HTML ที่ใช้ในล่ามของฉันดูเหมือนจะทำสิ่งที่โง่ถ้าพวกเขามีช่องว่างหลายแห่งในแถว)

ปัญหาที่ 7 - จับคู่ Nether Portals

m:{e<R>A1}{d<R>A1}%{2,22}{e<R>1}
e:~.X%{3,22}~.
d:X\.+X

mย้ายงูขวาพล่านงูเพื่อตรวจสอบขอบด้านซ้าย, 2-22 งูเพื่อตรวจสอบคอลัมน์กลางและในที่สุดก็งูเพื่อตรวจสอบขอบด้านขวา ~ประกอบการแสดงให้เห็นว่าสิ่งต่อไปนี้ควรได้รับการตรวจสอบ แต่ไม่ควรทำเครื่องหมายว่าเป็นส่วนหนึ่งของการแก้ปัญหา

การปิดที่ถูกผูกไว้ตอนนี้ช่วยให้เราสามารถแก้ไขปัญหานี้ได้อย่างเต็มที่และอย่างถูกต้อง!

ปัญหาที่ 8 - ตำแหน่งหน้าอก Minecraft

m:~{s<>}~!{d<+>}\.
s:<+>.<BR>([$\.]<R>)%{3}
d:.<+>CC

ที่นี่เราใช้ตรรกะไม่ใช่ ( !) ซึ่งตรงกับถ้าหากโทเค็นต่อไปนี้ไม่ตรงกับสิ่งใดเลย การประกาศdตรวจจับหน้าอกคู่ในทิศทางที่เฉพาะเจาะจงดังนั้น!{d<+>}ตรวจสอบให้แน่ใจว่าไม่มีทรวงอกสองชั้นในทิศทางมุมฉาก sเคลื่อนที่ด้วยเพชรเล็ก ๆ รอบ ๆ จัตุรัสปัจจุบันเพื่อยืนยันว่าอย่างน้อย 3 ของพื้นที่เหล่านั้นว่างเปล่าหรือหลุดออกจากกระดาน \.ในที่สุดการลากจะตรงกับสี่เหลี่ยมจัตุรัสโดยสมมติว่าเงื่อนไขก่อนหน้านี้สำเร็จทั้งหมด

ปัญหาที่ 9 - การจัดตำแหน่งแนวนอนและแนวตั้ง

m:<R>?#~.*#

งูmอาจเลี้ยวขวา ( <R>?) ก่อนที่จะจับคู่ลำดับ .เป็นสัญลักษณ์แทนเช่น regex

ปัญหาที่ 10 - คะแนน Colinear

m:<!>#~.*#~.*#

ด้วยการเพิ่ม<!>ทิศทางเราสามารถแก้ปัญหานี้ได้ในตอนนี้! <!>เป็นเหมือน<+>แต่แทนที่จะแยกเป็นสี่ทิศทางมันจะแตกกิ่งก้านไปทุกทิศทางที่เป็นไปได้

ปัญหาที่ 12 - หลีกเลี่ยงตัวอักษร Q

m:{h<R>A}%{4}
h:[^Qq]%{4}

เพียงวางไข่งู 4 ตัวที่แต่ละตัวค้นหาตัวละครสี่ตัวที่ไม่ใช่ตัวอักษรถาม

ปัญหาที่ 13 - การขุดเพชร

m:{tl<RB>1}{tr<RF>1}
tl:X/*{bl<L>1}X
tr:X\\*{br<R>1}X
bl:X\\*X
br:X/*X

คนนี้สวยเนี๊ยบ mวางไข่งูสองตัวตัวหนึ่งวิ่งไปทางขวาหลังและอีกอันไปทางขวา แต่ละคนตามมาทับเครื่องหมาย X แล้ววางไข่งูอีกตัวที่มุมขวาตามทิศทางปัจจุบันของมันซึ่งตามหลังทับไปที่ด้านล่าง X

ปัญหาที่ 14 - การจับคู่ข้าม

m:{a<R>A}+{b<R>A}+{a<R>A}+
a:{e<>P1}{c<>P2}{e<>P3}
b:{c<>P1}{c<>P2}{c<>P3}
e:\.+
c:#+

นี่เป็นครั้งแรกที่ฉันใช้Pพารามิเตอร์ iggyback โดยปกติแล้วงูมีความเป็นอิสระ แต่ถ้าคุณโทรด้วยพารามิเตอร์นี้งูที่โทรมาจะถูกย้ายไปพร้อมกับ callee ดังนั้นe2สามารถตรวจสอบลำดับของ '.' จากนั้นลำดับ '#' จากนั้นอีกลำดับหนึ่งของ '.' และให้พวกเขาทั้งหมดแยกสายเพื่อให้เราสามารถจัดกลุ่มพวกเขาด้วย '1,' 2 'และ' 3 ' บังคับให้ความยาวตรงกัน

ปัญหาที่ 15 - จับคู่คำในกระดานเกรงกลัว

m{I}:<*>p<*>a<*>n<*>a<*>m<*>a

ง่ายถ้าฟุ่มเฟือย Iพารามิเตอร์ระบุตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ (เราสามารถระบุพารามิเตอร์ตามข้อกำหนดและในการโทร) งูหันไปในทิศทางใดตรงกับตัวละครหันอีกครั้งและอื่น ๆ

m{EI}:<*>p<*>a<*>n<*>a<*>m<*>a

นี่เป็นเวอร์ชันที่ไม่มีการใช้ซ้ำอักขระ Eพารามิเตอร์ Xclusive ห้ามงูจากที่ตรงกับตัวอักษรใด ๆ ที่ได้รับแล้วทำเครื่องหมายเหมือน feersum ของเส้นทางน้ำเมือก

ปัญหาที่ 16 - ล้อมรอบขอบ

m{W}:{c<R>WA}%{3}
c:###

Wพารามิเตอร์ช่วยให้งูห่อเมื่อมันวิ่งออกไปนอกสนาม นอกจากนี้เรายังมีHและVอนุญาตให้ตัดแบบแนวนอนหรือแนวตั้ง

Extra - Maze Solver

m{E}:$(<P>\.)+$

แก้ไขเขาวงกต ASCII ที่พื้นเดินเป็นระยะเวลา <P>ทิศทางหมายถึงข้างซ้ายหรือขวา (น้ำตาล[<F><L><R>])

การจับคู่แบบ Paren พิเศษ

m:\(~{r<>P}\)
r:[^\(\)]*(\({r<>P}\))?[^\(\)]*

ยังไม่ได้คิดว่าจะทำ Prelude ได้อย่างไร แต่นี่เป็นขั้นตอนแรก! ที่นี่ฉันใช้rงูซ้ำเพื่อจับคู่วงเล็บที่เกี่ยวข้องโดยตรวจสอบว่าไม่มีวงเล็บที่ไม่ตรงกันระหว่างพวกเขา

Extra - ASCII Topology: การนับลูป


คุณจะพิจารณาเพิ่มไวยากรณ์เพื่อให้ภาษานี้สามารถแทนที่ได้มากกว่าเพียงแค่การจับคู่? ฉันต้องการใช้วิธีแก้ปัญหาความท้าทายนี้เพื่อเขียนรายการสำหรับcodegolf.stackexchange.com/questions/51231/ …แต่ไม่มีวิธีแก้ปัญหาเดียวที่นี่ค้นหาและแทนที่ (ฉันรู้ว่าคำตอบของฉันจะไม่ถูกต้องเนื่องจากกฎกำหนดเวลาภาษา)
Sparr

@Sparr ไม่ใช่ความคิดที่ไม่ดีแน่นอนมันจะมีประโยชน์มากกว่าสำหรับการตีกอล์ฟ ไม่แน่ใจว่าเมื่อไหร่ฉันจะมีเวลาทำด้วยตัวเอง แต่ฉันจะจำไว้
BMac

3
แยกต่างหาก: ไวยากรณ์สำหรับการเปลี่ยนทิศทางทำให้เกิดความสับสน เพราะงูดำเนินไปหลังจากจับคู่ตัวละครฉันดูเหมือนจะต้องทำให้ทิศทางของฉันเปลี่ยนไปตัวละครตัวหนึ่งก่อนที่มันจะสมเหตุสมผลสำหรับฉัน ตัวอย่าง: สตริง "ABC \ nDEF" และฉันต้องการจับคู่ชิ้นส่วนรูปตัว L ที่กำหนดโดย ABCF ฉันต้องการเขียนงูของฉันเป็น "m: ABC <R> F" แต่ฉันต้องเขียน "m: AB <R> CF "แทน ฉันเข้าใจว่าสิ่งนี้ตรงกับข้อมูลจำเพาะ แต่ฉันพบว่ามันใช้ง่ายมาก
Sparr

ฉันมีทางออกบางส่วนสำหรับการโหมโรงไวยากรณ์ ปัญหาเดียวคือฉันไม่สามารถทำให้มันไม่ตรงกันถ้ามันไม่ตรงกับอินพุตทั้งหมด: m:{a<>} a:[({n<R>A})({n<R>A}*{l<R>A}{a<>P}{r<R>A})]*{n<R>A}* l:$[^\(\)]*\([^\(\)]*$ r:$[^\(\)]*\)[^\(\)]*$ n:$[^\(\)]+$
TheNumberOne

21

Slip, Python 3.4 ( Github wiki , ล่ามออนไลน์ )

เช่นเดียวกับการยอมแพ้ของ feersum สิ่งนี้ก็ขึ้นอยู่กับการข้ามตาราง แต่เช่นเดียวกับการยอมจำนนของ CarpetPython สิ่งนี้ขึ้นอยู่กับ regex อย่างใดดูเหมือนว่าฉันจัดการเพื่อใช้พื้นกลาง

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


อัพเดท

(ดูหน้า Github สำหรับข่าวรายละเอียด)

  • 5 เมษายน 2015 : สลิปตอนนี้มีล่ามออนไลน์ ! มันยังอยู่ในช่วงเริ่มต้นดังนั้นอาจมีข้อผิดพลาดเล็กน้อย

  • 5 เมษายน 2015 : การปรับปรุงประสิทธิภาพ! ตอนนี้พอร์ทัลจะใส่ข้อมูลขนาดใหญ่ได้เร็วขึ้น (2 วินาที) นอกจากนี้ยังมีการเปลี่ยนแปลงทางไวยากรณ์จำนวนมากดังนั้นโปรดตรวจสอบวิกิ แก้ไขหมายเลขกลุ่มด้วย


สลิปมีตัวชี้การจับคู่ซึ่งเริ่มต้นที่ช่องสี่เหลี่ยมเฉพาะและเริ่มหันไปทางขวาทันที เมื่อจับคู่อักขระตัวชี้จะเลื่อนไปข้างหน้าในทิศทางปัจจุบัน (แม้ว่าการนำไปใช้จะไม่ทำสิ่งต่าง ๆ ตามลำดับนั้น)

ทิศทางที่ชี้การแข่งขันสามารถตั้งค่าให้เป็นทิศทางโดยเฉพาะอย่างยิ่งกับ^<digit>ที่^0, ^1, ^2, ... , ^7ตั้งค่าตัวชี้ไปที่ N, NE, E, ... , NW ตามลำดับ (ไปตามเข็มนาฬิกา)

ทางลัดต่อไปนี้ยังมีอยู่:

  • ^* ตรวจสอบทิศทางทั้ง 8 มุมฉากหรือแนวทแยง
  • ^+ ตรวจสอบทิศทางทั้งสี่มุมฉาก

(แผนในอนาคต: อนุญาตการตั้งค่าทิศทางโดยพลการเช่น(1, 2)อัศวินเคลื่อนที่)

ตัวอย่างเช่น ( ปัญหา 4 - การค้นหาคำในการค้นหาคำ )

^*GOLF

พยายาม 8 ทิศทางในแนวตั้งฉากหรือแนวทแยงทั้งหมดโดยมองหาคำว่า "GOLF" โดยค่าเริ่มต้น Slip พยายามสี่เหลี่ยมเริ่มต้นที่เป็นไปได้ทั้งหมดและส่งกลับผลลัพธ์หนึ่งรายการจากแต่ละรายการคัดกรองรายการที่ซ้ำกันดังนั้นกริดเหมือน

GOLF
O
L
FLOG

ส่งกลับเฉพาะแถวบนสุดและแถวล่างสุดเป็นการจับคู่ (ตั้งแต่แถวบนสุดและคอลัมน์ด้านซ้าย "GOLF" เริ่มจากจัตุรัสเดียวกัน) หากต้องการรับการแข่งขันทั้งหมดoสามารถใช้โหมดการจับคู่ที่ทับซ้อนกันได้

ในทำนองเดียวกัน ( ปัญหา 15 - จับคู่คำในกระดานเกรงกลัว )

p^*a^*n^*a^*m^*a

จับคู่panamaโดยพยายามเปลี่ยนทิศทางในแต่ละครั้ง ใช้iแฟล็กสำหรับการคำนึงถึงขนาดตัวพิมพ์ สลิปจะนำ chars กลับมาใช้ใหม่ตามค่าเริ่มต้น แต่สามารถสลับได้โดยrใช้ค่าสถานะที่ไม่ซ้ำกัน

(แผนในอนาคต: ตัวดัดแปลงโหมดการค้นหาซึ่งตรวจสอบชุดเส้นทางโดยอัตโนมัติหลังจากการย้ายแต่ละครั้งเพื่อให้การทำซ้ำ^*ไม่จำเป็น)

ทิศทางของตัวชี้การจับคู่ยังสามารถหมุนได้ 90 องศาไปทางซ้ายหรือขวาด้วย<หรือ>ตามลำดับ ตัวอย่างเช่น

 `#`#< `#<  <`#<`#

มองหารูปแบบ

  #
## 
 ##

โดยดูตามลำดับต่อไปนี้:

765
894
123

สิ่งนี้ทำให้เราสามารถแก้ปัญหา 6 - การค้นหาเครื่องร่อนด้วย

^+(`#`# >`# > `#>`#> |`#`# <`# < `#<`#< | `#`#> `#>  >`#>`#| `#`#< `#<  <`#<`#)

เมื่อส่วนที่ 1 และ 2 เข้ารหัสรูปร่างของเครื่องร่อนและส่วนที่ 3 และ 4 เข้ารหัสรหัสคู่ที่สะท้อนออกมา

โปรดทราบว่าสลิปใช้ backtick `สำหรับการหลบหนี นี่เป็นเพราะสลิปมีรูปแบบการเคลื่อนไหวอีกรูปแบบหนึ่งซึ่งให้ชื่อภาษา - คำสั่งสลิป /เลื่อนตัวชี้การแข่งขันไปทางซ้ายในขณะ\ที่เลื่อนตัวชี้การแข่งขันไปทางขวา

ตัวอย่างเช่น,

abc   ghi
   def

abc\def/ghiสามารถจับคู่โดย

ในขณะที่ไม่มีประโยชน์ในตัวมันเองการลื่นไถลกลายเป็นเรื่องสำคัญมากเมื่อรวมกับ(?| <regex> )กลุ่มที่อยู่กับที่ซึ่งทำหน้าที่เหมือนจับคู่ lookahead regex ภายในจะถูกจับคู่จากนั้นในตอนท้ายของตำแหน่งและทิศทางของตัวชี้การแข่งขันจะถูกรีเซ็ตเป็นสถานะก่อนที่กลุ่มนิ่ง

ตัวอย่างเช่น,

abc
def
ghi

(?|abc)\(?|def)\(?|ghi)สามารถจับคู่กับ

ในทำนองเดียวกันปัญหาที่ 12 - หลีกเลี่ยงตัวอักษร Qสามารถแก้ไขได้

%(\(?|[^qQ]{4})){4}

ที่%เป็นคำสั่งที่ไม่ลื่นเพื่อหยุดคนแรกที่\มาจากการเปิดใช้งาน

สลิปยังมีการยืนยันความยาว(?_(<group num>) <regex> )ซึ่งตรงกับ regex ภายในเท่านั้นหากความยาวการแข่งขันนั้นมีความยาวเท่ากับความยาวของจำนวนที่กำหนด

ตัวอย่างเช่นปัญหาที่ 13 - การขุดเพชรสามารถแก้ไขได้อย่างง่ายดาย

^1X(`/*)X>(?_(1)`\*)X>(?_(1)`/*)X>(?_(1)`\*)

ซึ่งพยายามจับคู่กับด้านซ้ายบนของเพชรก่อนจากนั้นยืนยันว่าอีกสามด้านนั้นมีความยาวเท่ากัน

(รันด้วยvแฟล็กสำหรับเอาต์พุตแบบละเอียด)

Match found in rectangle: (8, 0), (12, 4)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (0, 0), (6, 6)
   X
  / \
 /   \
X     X
 \   /
  \ /
   X

Match found in rectangle: (2, 2), (4, 4)
 X
X X
 X

Match found in rectangle: (10, 2), (14, 6)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (5, 3), (9, 7)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (0, 6), (2, 8)
 X
X X
 X

ทางเลือกนักกอล์ฟคือ

^1X(`/*)(X>(?_(1)`\*)X>(?_(1)`/*)){2}

ซึ่งตรงกับด้านแรกสองครั้ง

ปัญหาอื่น ๆ อีกมากมายสามารถแก้ไขได้ด้วยการลื่นไถลกลุ่มเครื่องเขียนและการยืนยันความยาว:

ปัญหาที่ 14 - การจับคู่ข้าม:

(?|(`.+)(`#+)(`.+))(\(?|(?_(2)`.+)(?_(3)`#+)(?_(4)`.+)))*(\(?|(?_(2)`#+)(?_(3)`#+)(?_(4)`#+)))+(\(?|(?_(2)`.+)(?_(3)`#+)(?_(4)`.+)))+

เมื่อคุณจับความกว้างของ.s และ#s ในแถวแรกมันแค่เลื่อนลงมาจนสุด

เอาท์พุท:

Match found in rectangle: (0, 1), (5, 5)
.###..
######
######
.###..
.###..

Match found in rectangle: (4, 6), (6, 8)
.#.
###
.#.

อันนี้น่าจะเล่นกับการเรียกซ้ำเล็กน้อยเมื่อฉันได้รับข้อบกพร่องบางอย่างแยกออก

ปัญหา 3 - ตรวจหาสี่เหลี่ยมของตัวเลข:

(?|`d`d+)(\(?|(?_(1)`d+)))+

จับคู่แถวบนสุดของตัวเลขสองหลักขึ้นไปจากนั้นตรวจสอบให้แน่ใจว่าทุกบรรทัดด้านล่างมีความยาวเท่ากัน เป็นตัวอักษรระดับที่กำหนดไว้ล่วงหน้าเทียบเท่ากับ`d[0-9]

โปรดทราบว่านี้พบการแข่งขันทั้งหมด

ปัญหาที่ 7 - จับคู่พอร์ทัลด้านล่าง:

(?|.X{2,22}.)\((?|(?_(1)X`.+X))\){3,22}(?_(1).X+.)

เอาท์พุทใดสำหรับตัวอย่างบนสุดในเธรดต้นฉบับ :

Match found in rectangle: (2, 1), (5, 5)
XXXX
X..X
X..X
X..X
XXXX

Match found in rectangle: (9, 1), (14, 5)
.XXXX.
X....X
X....X
X....X
.XXXX.

Match found in rectangle: (13, 4), (17, 8)
.XXXX
X...X
X...X
X...X
.XXX.

ในที่สุดฟีเจอร์อื่น ๆ ของ Slip รวมถึง:

  • $0, $1, $2, ..., $7ยึดขอบเหนือ, มุมตะวันออกเฉียงเหนือ, ขอบตะวันออก, ฯลฯ$+ยึดขอบใด ๆ และ$*จุดยึดใด ๆ
  • $ตามด้วยตัวอักษรตัวพิมพ์เล็กชุดสมอที่ตำแหน่งปัจจุบันซึ่งสามารถมาจับคู่โดย$ตามด้วยตัวอักษรตัวพิมพ์ใหญ่ที่สอดคล้องกันเช่นและ$a$A
  • # สลับค่าสถานะไม่ย้ายซึ่งหยุดตัวชี้การจับคู่จากการย้ายไปข้างหน้าหลังจากการแข่งขันครั้งถัดไป
  • ,จับคู่อักขระที่ชอบ.แต่ไม่เพิ่มลงในเอาต์พุตทำให้สามารถจับคู่แบบไม่ต่อเนื่องในขณะที่สามารถจดจำ(?_())ได้

... และอื่น ๆ. มีรายการมากเกินไปในหน้านี้

ปัญหาอื่น ๆ

ปัญหา 1 - การค้นหากระดานหมากรุก:

(?|`#?(`_`#)+`_?)(?_(1)(?|...+))(\(?_(1)(?|`#?(`_`#)+`_?$a)))+<(?|`#?(`_`#)+`_?)(?_(9)(?|...+))(\(?_(9)(?|`#?(`_`#)+`_?)))+$A

ปัญหากระดานหมากรุกสองปัญหาไม่ได้เกิดขึ้นอย่างแน่นอน เราจับคู่แถวบนสุดแล้วตรวจสอบให้แน่ใจว่ามีความยาวอย่างน้อย 3 ตัวและสลับระหว่าง#และ_จากนั้นจัดและจับคู่แถวถัดไป ในตอนท้าย$aสมอควรอยู่ที่ด้านล่างขวาของกระดานหมากรุก

จากนั้นเราเลี้ยวซ้ายและทำซ้ำสำหรับคอลัมน์ทำให้แน่ใจว่าเราตรง$Aกับตอนท้าย

ปัญหา 2 - การตรวจสอบกระดานหมากรุก:

$7%(\(?|`_?(`#`_)*`#?$2))+$5<%(\(?|`_?(`#`_)*`#?$0))+$3

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

ปัญหาที่ 9 - การจัดตำแหน่งแนวนอนและแนวตั้ง:

>?`#,*`#

เราใช้ทางเลือกหรือไม่ quantifier ของ>คำสั่งหมุนเพื่อให้เราจับคู่ทางขวาหรือลง เราพบทั้ง 5 ในตัวอย่างด้วยoโหมดที่ทับซ้อนกัน แต่มีเพียง 4 ตัวที่ไม่มีมันตั้งแต่#.,##และ#.,#เริ่มจากตำแหน่งเดียวกัน

ปัญหาที่ 10 - คะแนน Collinear

^+`#(?|(,*)<(,*))(((?_(2),*)<(?_(3),*),>)+#`#){2}

ตรง#แล้วบางตัวอักษรในแนวนอนและแนวตั้งบางตัวอักษรแล้วทำซ้ำจนวินาทีและทำซ้ำจนกว่าที่สาม##

ปัญหาที่ 5 - การตรวจจับอินพุตแบบสี่เหลี่ยม:

$7.(.*)>(?_(1).*)$3>((?|.*)\)*

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

ปัญหาที่ 8 - ตำแหน่งหน้าอก Minecraft:

`.^+(($^|(?|`.))>){3}($^|`.|C<(($^|(?|`.))>){3})

วิ่งด้วยpธงเพื่อรับตำแหน่งของการแข่งขันแต่ละนัด $^เป็นตัวยึดที่ตรงกันถ้าการย้ายครั้งต่อไปจะทำให้ตัวชี้การแข่งขันออกนอกขอบเขต

ครั้งแรกที่เราจับคู่.แล้วตรวจสอบว่าเรากำลังล้อมรอบด้วยสาม.s / ขอบเขตแล้วทำให้แน่ใจว่าตารางรอบที่สี่ยังเป็น./ เขตแดนหรือหน้าอกเดียว (โดยการตรวจสอบของสี่เหลี่ยมรอบ)

ปัญหา 11 - ตรวจสอบไวยากรณ์โหมโรง :

$7>%(/(?|[^()]+$4)(?1)?|/(?|[^()]*`([^()]*$4)(?1)?/(?|[^()]*`)[^()]*$4)(?1)?)$1

ใช้เวลาลองไม่กี่ครั้ง แต่ฉันคิดว่ามันถูกต้อง ที่นี่เราใช้การเรียกซ้ำซึ่งมีไวยากรณ์เดียวกับ PCRE

วิธีการนี้ต้องการให้อินพุตเป็นรูปสี่เหลี่ยมผืนผ้า แต่เมื่อฉันได้รับการจับคู่ที่ไม่ใช่รูปสี่เหลี่ยมผืนผ้าแล้วการตั้งสมมติฐานนั้นไม่จำเป็น

นี่คือวิธีการเดียวกันที่เล่นด้วยการเรียกซ้ำมากกว่าเดิม:

$7>%((/(?|([^()]*)$4)|/(?|(?4)`((?3))(?1)?/(?|(?4)`)(?3)))*)$1

ปัญหา 16 - ล้อมรอบขอบ:

%(\(?|`#{3})){3}

(หมายเหตุ: การตัดคำยังไม่ได้ถูกผลักไปที่ล่ามออนไลน์)

wธงนี้ต้องตัด ในทางเทคนิคแล้วการเริ่มต้น%สำหรับการไม่ลื่นไม่จำเป็น แต่จากนั้นการแข่งขันจะถูกนับเป็นการเริ่มต้นจากหนึ่งตารางที่สูงกว่า

ปัญหา EX 1 - ตัวแก้เขาวงกต:

S(^+`.)*^+E

ปัญหาจากความคิดเห็นของ BMAC ในการแชท ใช้การrตั้งค่าสถานะสำหรับโหมดไม่ซ้ำเพื่อให้ตัวชี้การจับคู่ไม่ติดไปมา

ปัญหา EX 2 - การจดจำใบหน้า :

(?|O(,*),(?_(2),*)O)(?_(2)(\(?|,))*)\(?|,(?_(2),*)O)(?_(2)(\(?|,))*)\`\(?_(2)`_*)`_(?_(2)`_*)`/

โปรดทราบว่าฉันเป็นเพียงการจับคู่ใบหน้าเท่านั้นไม่ทำการล้างข้อมูลใด ๆ โปรดทราบว่าคำถามนั้นมีสัญลักษณ์ยูโรซึ่งจะต้องถูกแทนที่ด้วย ASCII ที่พิมพ์ได้เพื่อให้ทำงานได้


รูปแบบแฮชนั้นเป็นเครื่องร่อน Conway
Heimdall

17

PMA / หอย (C ++)

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

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

  1. ภายในกลุ่ม ( ) [ ]
  2. แยกตามตัวอักษรสลับ |
  3. ประเมินทุกอย่างทางด้านซ้ายของ`กลุ่ม
  4. ปริมาณ[m],[n]และn
  5. ยืนยัน = !
  6. เรียงต่อกัน

ล่ามเขียนด้วยภาษา C ++ รหัสที่มาสุดซึ้งสามารถพบได้ที่นี่

ปัญหาที่ 4: การค้นหาคำ

โปรแกรม

z\G\O\L\F

ก็เพียงพอที่จะได้รับความจริงหรือเท็จตามตัวอักษรไม่ว่าจะเป็นคำที่พบ z(หนึ่งใน 15 คำสั่งสัมบูรณ์หรือคำสั่งทิศทางสัมพัทธ์) จับคู่ในทิศทางแปดด้านใดก็ได้ คำสั่งทิศทางต่อเนื่องหลายคำสั่งถูกรวมเข้าด้วยกัน ตัวอย่างเช่นruldyจะเกือบเทียบเท่ากับzที่เป็นคำสั่งสำหรับทิศทางขวาขึ้นซ้ายซ้ายและทิศทางแนวทแยง อย่างไรก็ตามเส้นทางจะถูกทดสอบในลำดับที่แตกต่างกัน อักขระตัวแรกที่จับคู่จะเป็นหอยทากที่เริ่มต้นเสมอโดยไม่คำนึงถึงทิศทาง \<character> จับคู่อักขระตัวเดียว

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

?
z\G\O\L\F

หากมีบรรทัดใหม่อย่างน้อยหนึ่งบรรทัดในไฟล์ต้นฉบับบรรทัดแรกจะถือว่าเป็นตัวเลือกสำหรับการแปลงเริ่มต้นของอินพุตในรูปแบบสี่เหลี่ยมผืนผ้า ?ตัวเลือกพิมพ์ 0 หรือ 1 ขึ้นอยู่กับว่ามีการแข่งขันที่ใดก็ได้

ปัญหาที่ 15: เกรงกลัว

หลังจากใช้งานการสลับกันตอนนี้สามารถแก้ปัญหาเกรงกลัวได้แล้ว จะเป็นการดีกว่าถ้าใช้การจับคู่แบบตรงตามตัวพิมพ์ใหญ่ - เล็กสำหรับการจับคู่นี้ แต่การใช้งานที่ไม่ได้รับความสำคัญสูงสุดของฉัน

\p|\P)z(\a|\A)z{\n|\N)z{\a|\A}z(\m|\M)z(\a|\A

|ทำงานเหมือนกับ regex 1 มิติ มีสองคู่จับคู่ของตัวคั่นมีการจัดกลุ่มคือและ() {}เครื่องหมายวงเล็บปิดจะปิดกลุ่มที่เปิดอยู่ของประเภทตรงกันข้ามที่อยู่ระหว่างกลุ่มนั้นกับกลุ่มประเภทที่ใกล้เคียงที่สุด ตัวอย่างเช่นต่อไปนี้{({{)เฉพาะกลุ่มซ้ายสุดยังคงเปิดอยู่ อย่างที่คุณเห็นสัญลักษณ์การจัดกลุ่มที่ไม่ตรงกันที่ขอบถูกปิดโดยปริยาย มีคำสั่งจัดกลุ่มอื่น`ที่ฉันจะไม่เข้าไปตอนนี้

ปัญหาที่ 8: หีบ Minecraft

โปรแกรมจะพิมพ์จำนวนตำแหน่งหน้าอกที่ถูกต้อง นี่เป็นครั้งแรกที่ฉันต้องเล่นกอล์ฟและลดจำนวนไบต์ของฉัน (17) สองสามครั้ง

\.!(o\C)2o(!\Cw)3
  • \. ตรงกับจุดแท้จริงที่จุดเริ่มต้นของการแข่งขัน
  • !(o\C)2เทียบเท่ากับ!((o\C)2)ปริมาณที่มีความสำคัญสูงกว่าการยืนยัน <atom> <number>หมายถึงการทำซ้ำ<atom>ว่า<number>ครั้ง oหมุนหอยทากไปในทิศทางใดก็ได้ !เป็นการยืนยันเชิงลบ ดังนั้นในส่วนนี้จะตรวจสอบการขาดของหน้าอกคู่ที่อยู่ติดกัน
  • o หันไปในทิศทางมุมฉาก
    • (!\Cw)3ยืนยันว่าไม่มีCด้านหน้าของหอยทากแล้วหมุนทวนเข็มนาฬิกา 3 ครั้ง

ปัญหาที่ 2: การตรวจสอบกระดานหมากรุก

&
\#!(o^_)|\_!(o^#

&ตัวเลือกการตั้งค่าเอาท์พุทของโปรแกรมเช่น1หากการแข่งขันประสบความสำเร็จในทุกตำแหน่งและ0อย่างอื่น ^cจับคู่อักขระที่ไม่cเท่ากับ[^c]regex โดยรวมแล้วโปรแกรมหมายถึง: พิมพ์ 1 หากทุกตำแหน่งในรูปสี่เหลี่ยมผืนผ้าที่มีขอบเขตของอินพุตมีทั้งแบบ#ที่ไม่ได้อยู่ติดกันกับตัวละครที่ไม่ใช่ orthogonally _หรือ_ที่ไม่ได้อยู่ติดกันกับตัวอักษรแบบ ไม่#; มิฉะนั้น 0


ความคิดเส้นทางน้ำเมือกเป็นสิ่งที่ดีสำหรับการรับมือกับการเกรงกลัวฉันมีปัญหาบางอย่างกับมัน
BMac

นั่นเป็นทางออกที่ดีสำหรับปัญหาเกรงกลัว ฉันไม่สามารถแก้ปัญหาด้วยวิธีการของฉัน
Logic Knight

14

คลาส Re2d, Python 2

อัปเดต: เพิ่มปัญหา "9. การจัดตำแหน่ง"

แนวทางของฉันคือใช้โมดูล Python ใหม่เพื่อทำการค้นหาและจับคู่ ชั้น Re2d เตรียมข้อความสำหรับการประมวลผลดำเนินการฟังก์ชั่นใหม่และจัดรูปแบบผลลัพธ์สำหรับการส่งออก

โปรดทราบว่านี่ไม่ใช่ภาษาใหม่ทั้งหมด - เป็นภาษานิพจน์ทั่วไปมาตรฐานที่คาดการณ์ไว้ใน 2 มิติพร้อมการตั้งค่าสถานะเพิ่มเติมสำหรับโหมด 2D พิเศษ

ชั้นมีการใช้งานดังต่อไปนี้:

re2dobject = Re2d(<horizontal pattern>, [<vertical pattern>], [<flags>])

รูปแบบทั้งสองเป็นรูปแบบ RE ข้อความเชิงเส้นมาตรฐาน หากไม่ได้จัดรูปแบบแนวตั้งคลาสจะใช้รูปแบบแนวนอนเพื่อจับคู่ในแนวตั้งด้วย ธงเป็นธง RE มาตรฐานที่มีนามสกุล 2D บางอย่าง

การทดสอบ

1. Finding chessboards
Chessboard pattern at (2, 1, 4, 3)

print '\n1. Finding chessboards'
reob1 = Re2d('#(_#)+_?|_(#_)+#?')
found = reob1.search('~______~\n~##_#_#~\n~#_#_##~\n~##_#_#~\n~______~')
print 'Chessboard pattern at', found
assert not reob1.search('#_##\n_#_#\n__#_\n#_#_\n#_#_')

วิธีการค้นหาพบรูปแบบกระดานหมากรุกและส่งคืนตำแหน่งแบบ 4-tuple tuple มีx,yตำแหน่งของอักขระตัวแรกของการจับคู่และ width, heightของพื้นที่ที่จับคู่ มีการกำหนดรูปแบบเดียวเท่านั้นจึงจะใช้สำหรับการจับคู่แนวนอนและแนวตั้ง

2. Verifying chessboards
Is chess? True

print '\n2. Verifying chessboards'
reob2 = Re2d('^#(_#)*_?|_(#_)*#?$')
print 'Is chess?', reob2.match('_#_#_#_#\n#_#_#_#_\n_#_#_#_#')
assert not reob2.match('_#_#_#__\n__#_#_#_\n_#_#_#__')

กระดานหมากรุกได้รับการยืนยันด้วยวิธีการจับคู่ซึ่งส่งคืนบูลีน โปรดทราบว่า^และ$เริ่มต้นและสิ้นสุดตัวละครจะต้องตรงกับทั้ง ข้อความ

3. Rectangle of digits
Found: [(0, 1, 5, 3), (1, 1, 4, 3), (2, 1, 3, 3), (3, 1, 2, 3), (0, 2, 5, 2), (1, 2, 4, 2), (2, 2, 3, 2), (3, 2, 2, 2), (6, 3, 2, 2)]
Not found: None

print '\n3. Rectangle of digits'
reob3 = Re2d(r'\d\d+', flags=MULTIFIND)
print 'Found:', reob3.search('hbrewvgr\n18774gwe\n84502vgv\n19844f22\ncrfegc77')
print 'Not found:', reob3.search('uv88wn000\nvgr88vg0w\nv888wrvg7\nvvg88wv77')

ตอนนี้เราใช้การMULTIFINDตั้งค่าสถานะเพื่อส่งคืนการจับคู่ที่เป็นไปได้ทั้งหมดสำหรับบล็อก 2 หลัก วิธีการพบ 9 การแข่งขันที่เป็นไปได้ โปรดทราบว่าพวกเขาสามารถทับซ้อนกัน

4. Word search (orthogonal only)
Words: [(0, 0, 4, 1), (0, 3, 4, 1), (3, 3, -4, -1), (3, 2, -4, -1), (3, 0, -4, -1)] [(0, 0, 1, 4), (3, 0, 1, 4), (3, 3, -1, -4), (0, 3, -1, -4)]
Words: ['SNUG', 'WOLF', 'FLOW', 'LORE', 'GUNS'] ['S\nT\nE\nW', 'G\nO\nL\nF', 'F\nL\nO\nG', 'W\nE\nT\nS']
No words: [] []

print '\n4. Word search (orthogonal only)'
words = 'GOLF|GUNS|WOLF|FLOW|LORE|WETS|STEW|FLOG|SNUG'
flags = HORFLIP | VERFLIP | MULTIFIND
reob4a, reob4b = Re2d(words, '.', flags), Re2d('.', words, flags)
matching = 'SNUG\nTEQO\nEROL\nWOLF'
nomatch = 'ABCD\nEFGH\nIJKL\nMNOP'
print 'Words:', reob4a.search(matching), reob4b.search(matching)
print 'Words:', reob4a.findall(matching), reob4b.findall(matching)
print 'No words:', reob4a.findall(nomatch), reob4b.findall(nomatch)

การทดสอบนี้แสดงให้เห็นถึงการใช้การพลิกในแนวตั้งและแนวนอน อนุญาตให้ใช้คำที่ตรงกันที่ตรงกันข้าม ไม่รองรับคำในแนวทแยง MULTIFINDธงช่วยให้การแข่งขันที่ทับซ้อนกันหลายตัวในทั้ง 4 ทิศทาง เมธอด findall ใช้การค้นหาเพื่อค้นหากล่องจับคู่จากนั้นแตกบล็อกที่ตรงกันของข้อความ โปรดทราบว่าการค้นหาใช้ความกว้างและ / หรือความสูงเป็นลบสำหรับการจับคู่ในทิศทางตรงกันข้าม คำในแนวตั้งมีอักขระขึ้นบรรทัดใหม่ซึ่งสอดคล้องกับแนวคิดของบล็อกอักขระแบบสองมิติ

7. Calvins portals
Portals found: [(3, 1, 5, 6)]
Portal not found None

print '\n7. Calvins portals'
reob7 = Re2d(r'X\.{2,22}X|.X{2,22}.', r'X\.{3,22}X|.X{3,22}.', MULTIFIND)
yes = '....X......\n.XXXXXX.XX.\n...X...X...\n.X.X...XXX.\n...X...X.X.\n.XXX...X.X.\nX..XXXXX.X.'
no = 'XX..XXXX\nXX..X..X\nXX..X..X\n..X.X..X\n.X..X.XX'
print 'Portals found:', reob7.search(yes)
print 'Portal not found', reob7.search(no)

การค้นหานี้ต้องการรูปแบบแยกต่างหากสำหรับแต่ละมิติเนื่องจากขนาดต่ำสุดแตกต่างกันสำหรับแต่ละมิติ

9. Alignment
Found: ['#.,##', '##'] ['#\n.\n,\n.\n#', '#\n,\n.\n#']
Found: [(3, 4, 5, 1), (6, 4, 2, 1)] [(7, 0, 1, 5), (3, 1, 1, 4)]
Not found: None None

print '\n9. Alignment'
reob9a = Re2d(r'#.*#', r'.', MULTIFIND)
reob9b = Re2d(r'.', r'#.*#', MULTIFIND)
matching = '.,.,.,.#.,\n,.,#,.,.,.\n.,.,.,.,.,\n,.,.,.,.,.\n.,.#.,##.,\n,.,.,.,.,.'
nomatch = '.,.#.,.,\n,.,.,.#.\n.,#,.,.,\n,.,.,.,#\n.#.,.,.,\n,.,.#.,.\n#,.,.,.,\n,.,.,#,.'
print 'Found:', reob9a.findall(matching), reob9b.findall(matching)
print 'Found:', reob9a.search(matching), reob9b.search(matching)
print 'Not found:', reob9a.search(nomatch), reob9b.search(nomatch)

การค้นหา 2 ชุดนี้จะค้นหาการจับคู่แนวตั้งและแนวนอน 2 คู่ แต่ไม่สามารถค้นหา#.,#สตริงที่ฝังได้

10. Collinear Points (orthogonal only)
Found: [(0, 1, 7, 1)] [(3, 1, 1, 4)]
Not found: None None

print '\n10. Collinear Points (orthogonal only)'
matching = '........\n#..#..#.\n...#....\n#.......\n...#....'
nomatch = '.#..#\n#..#.\n#....\n..#.#'
reob10h = Re2d(r'#.*#.*#', '.')
reob10v = Re2d('.', r'#.*#.*#')
flags = MULTIFIND
print 'Found:', reob10h.search(matching, flags), reob10v.search(matching, flags)
print 'Not found:', reob10h.search(nomatch, flags), reob10v.search(nomatch, flags)

ที่นี่เราใช้การค้นหา 2 ครั้งเพื่อค้นหาการแข่งขันทั้งสองทิศทาง มันสามารถค้นหาการแข่งขันหลายฉาก แต่วิธีนี้ไม่สนับสนุนการแข่งขันในแนวทแยง

12. Avoid qQ
Found: (2, 2, 4, 4)
Not found: None

print '\n12. Avoid qQ'
reob12 = Re2d('[^qQ]{4,4}')
print 'Found:', reob12.search('bhtklkwt\nqlwQklqw\nvtvlwktv\nkQtwkvkl\nvtwlkvQk\nvnvevwvx')
print 'Not found:', reob12.search('zxvcmn\nxcvncn\nmnQxcv\nxcvmnx\nazvmne')

การค้นหานี้ค้นหาคู่แรก

13. Diamond Mining
.X.
X.X
.X.

.X.
X.X
.X.

..X..
./.\.
X...X
.\./.
\.X..

..X..
./.\.
X...X
.\./.
..X..

.XX.\
//.\.
X...X
.\./.
..X..

...X...
../.\..
./.X.\.
X.X.X.X
.\.X.//
..\./X.
.X.X..\

Diamonds: [(2, 2, 3, 3), (0, 6, 3, 3)] [(8, 0, 5, 5), (10, 2, 5, 5), (5, 3, 5, 5)] [(0, 0, 7, 7)]
Not found: None None None

print '\n13. Diamond Mining'
reob13a = Re2d(r'.X.|X.X', flags=MULTIFIND)
reob13b = Re2d(r'..X..|./.\\.|X...X|.\\./.', flags=MULTIFIND)
reob13c = Re2d(r'...X...|../.\\..|./...\\.|X.....X|.\\.../.|..\\./..', flags=MULTIFIND)
match = '''
...X......X....
../.\..../.\...
./.X.\..X...X..
X.X.X.XX.\./.\.
.\.X.//.\.X...X
..\./X...X.\./.
.X.X..\./...X..
X.X....X.......
.X.............
'''.strip().replace(' ', '')
nomatch = '''
.X......./....
.\....X.......
...X.\.\...X..
..X.\...\.X.\.
...X.X...X.\.X
../X\...\...X.
.X...\.\..X...
..\./.X....X..
...X..../.....
'''.strip().replace(' ', '')
for diamond in reob13a.findall(match)+reob13b.findall(match)+reob13c.findall(match):
    print diamond+'\n'
print 'Diamonds:', reob13a.search(match), reob13b.search(match), reob13c.search(match)
print 'Not found:', reob13a.search(nomatch), reob13b.search(nomatch), reob13c.search(nomatch)

ปัญหาเพชรยากขึ้น ต้องการค้นหาวัตถุสามรายการสำหรับสามขนาด สามารถหาเพชรทั้งหกได้ในชุดทดสอบ แต่ไม่ได้ปรับขนาดเป็นเพชรขนาดแปรผัน นี่เป็นเพียงวิธีการแก้ปัญหาเพชรบางส่วนเท่านั้น

รหัส Python 2

import sys
import re

DEBUG = re.DEBUG
IGNORECASE = re.IGNORECASE
LOCALE = re.LOCALE
UNICODE = re.UNICODE
VERBOSE = re.VERBOSE
MULTIFIND = 1<<11
ROTATED = 1<<12     # not implemented
HORFLIP = 1<<13
VERFLIP = 1<<14
WRAPAROUND = 1<<15  # not implemented

class Re2d(object):
    def __init__(self, horpattern, verpattern=None, flags=0):
        self.horpattern = horpattern
        self.verpattern = verpattern if verpattern != None else horpattern
        self.flags = flags

    def checkblock(self, block, flags):
        'Return a position if block matches H and V patterns'
        length = []
        for y in range(len(block)):
            match = re.match(self.horpattern, block[y], flags)
            if match:
                length.append(len(match.group(0)))
            else:
                break
        if not length:
            return None
        width = min(length)
        height = len(length)
        length = []
        for x in range(width):
            column = ''.join(row[x] for row in block[:height])
            match = re.match(self.verpattern, column, flags)
            if match:
                matchlen = len(match.group(0))
                length.append(matchlen)
            else:
                break
        if not length:
            return None
        height = min(length)
        width = len(length)
        # if smaller, verify with RECURSIVE checkblock call:
        if height != len(block) or width != len(block[0]):
            newblock = [row[:width] for row in block[:height]]
            newsize = self.checkblock(newblock, flags)
            return newsize
        return width, height

    def mkviews(self, text, flags):
        'Return views of text block from flip/rotate flags, inc inverse f()'
        # TODO add ROTATED to generate more views
        width = len(text[0])
        height = len(text)
        views = [(text, lambda x,y,w,h: (x,y,w,h))]
        if flags & HORFLIP and flags & VERFLIP:
            flip2text = [row[::-1] for row in text[::-1]]
            flip2func = lambda x,y,w,h: (width-1-x, height-1-y, -w, -h)
            views.append( (flip2text, flip2func) )
        elif flags & HORFLIP:
            hortext = [row[::-1] for row in text]
            horfunc = lambda x,y,w,h: (width-1-x, y, -w, h)
            views.append( (hortext, horfunc) )
        elif flags & VERFLIP:
            vertext = text[::-1]
            verfunc = lambda x,y,w,h: (x, height-1-y, w, -h)
            views.append( (vertext, verfunc) )
        return views

    def searchview(self, textview, flags=0):
        'Return matching textview positions or None'
        result = []
        for y in range(len(textview)):
            testtext = textview[y:]
            for x in range(len(testtext[0])):
                size = self.checkblock([row[x:] for row in testtext], flags)
                if size:
                    found = (x, y, size[0], size[1])
                    if flags & MULTIFIND:
                        result.append(found)
                    else:
                        return found
        return result if result else None

    def search(self, text, flags=0):
        'Return matching text positions or None'
        flags = self.flags | flags
        text = text.split('\n') if type(text) == str else text
        result = []
        for textview, invview in self.mkviews(text, flags):
            found = self.searchview(textview, flags)
            if found:
                if flags & MULTIFIND:
                    result.extend(invview(*f) for f in found)
                else:
                    return invview(*found)
        return result if result else None

    def findall(self, text, flags=0):
        'Return matching text blocks or None'
        flags = self.flags | flags
        strmode = (type(text) == str)
        text = text.split('\n') if type(text) == str else text
        result = []
        positions = self.search(text, flags)
        if not positions:
            return [] if flags & MULTIFIND else None
        if not flags & MULTIFIND:
            positions = [positions]
        for x0,y0,w,h in positions:
            if y0+h >= 0:
                lines = text[y0 : y0+h : cmp(h,0)]
            else:
                lines = text[y0 : : cmp(h,0)]
            if x0+w >= 0:
                block = [row[x0 : x0+w : cmp(w,0)] for row in lines]
            else:
                block = [row[x0 : : cmp(w,0)] for row in lines]
            result.append(block)
        if strmode:
            result = ['\n'.join(rows) for rows in result]
        if flags & MULTIFIND:
            return result
        else:
            return result[0]

    def match(self, text, flags=0):
        'Return True if whole text matches the patterns'
        flags = self.flags | flags
        text = text.split('\n') if type(text) == str else text
        for textview, invview in self.mkviews(text, flags):
            size = self.checkblock(textview, flags)
            if size:
                return True
        return False

หากปัญหาเพชรไม่ชัดเจนเพชรสามารถมีขนาดใดก็ได้ไม่ใช่แค่ 0, 1 หรือ 2 แก้ไข: ฉันได้แก้ไขข้อมูลจำเพาะเพื่อให้ชัดเจนยิ่งขึ้น
PhiNotPi

เข้าใจแล้ว. ฉันจะจดบันทึกในคำตอบที่ Re2d มีเพียงวิธีการแก้ปัญหาบางส่วนเท่านั้น ไม่สามารถปรับขนาดเป็นขนาดตัวแปรได้ ไม่เป็นไร?
Logic Knight

ไม่เป็นไร.
PhiNotPi

14

สิ่งสกปรก Haskell

บทนำ

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

แก้ไข:แก้ไขกากบาท (ขอบคุณ DLosc สำหรับการตรวจจับจุดบกพร่อง) และเพิ่มการขุดเพชร

EDIT2:เพิ่มคลาสของตัวละครโดยได้รับแรงบันดาลใจจาก Slip นอกจากนี้ยังเปลี่ยนไวยากรณ์ของการตั้งค่าสถานะตัวเลือกปรับปรุง parser นิพจน์และเพิ่มปัญหา no-Q

EDIT3:ใช้ข้อ จำกัด ขนาดและเพิ่มปัญหาพอร์ทัล Nether

การใช้

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

runhaskell grime.hs [options] grammarfile matrixfile

โดยที่matrixfileเป็นไฟล์ที่มีเมทริกซ์อักขระ ตัวอย่างเช่นหลักไวยากรณ์จะถูกประเมินเป็น

runhaskell grime.hs digits.gr digit-matrix

เพื่อความเร็วที่เพิ่มขึ้นฉันแนะนำให้รวบรวมไฟล์ด้วยการปรับให้เหมาะสม:

ghc -O2 grime.hs
./grime digits.gr digit-matrix

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

  • -e: จับคู่เฉพาะเมทริกซ์ทั้งหมดพิมพ์1เพื่อจับคู่และ0ไม่ตรงกัน
  • -n: พิมพ์จำนวนการแข่งขันหรือเมทริกซ์ทั้งหมดหาก-eได้รับด้วย
  • -a: พิมพ์การแข่งขันทั้งหมด
  • -p: (x,y,w,h)พิมพ์ยังตำแหน่งของการแข่งขันในรูปแบบ
  • -s: อย่าพิมพ์การแข่งขันด้วยตนเอง
  • -d: พิมพ์ข้อมูลการดีบัก

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

ไวยากรณ์และความหมาย

ไวยากรณ์ของ Grime ประกอบด้วยคำจำกัดความอย่างน้อยหนึ่งคำแต่ละคำในบรรทัดแยกต่างหาก แต่ละของพวกเขากำหนดค่าของที่nonterminal , และหนึ่งในนั้นต้องกำหนดนิรนามnonterminal ระดับบนสุด ไวยากรณ์ของคำนิยามเป็นทั้งN=EหรือEที่Nเป็นตัวอักษรตัวพิมพ์ใหญ่และEเป็นการแสดงออก

นิพจน์ถูกสร้างขึ้นดังนี้

  • อักขระใด ๆ ที่หลบหนีด้วยการ\จับคู่1x1สี่เหลี่ยมใด ๆที่มีอักขระนั้นอยู่
  • . จับคู่อักขระเดี่ยวใด ๆ
  • $จับคู่กับ1x1สี่เหลี่ยมนอกเมทริกซ์อักขระ
  • _ ตรงกับสี่เหลี่ยมใด ๆ ที่มีความกว้างหรือความสูงเป็นศูนย์
  • กลุ่มอักขระที่กำหนดไว้ล่วงหน้าคือdigit, uppercase, lowercase, alphabetic, alpha numeric และsymbol
  • [a-prt-w,d-gu]ตัวละครใหม่เรียนสามารถกำหนดได้โดยไวยากรณ์ abchijklmnoprtvwตัวอักษรด้านซ้ายจะถูกรวมและผู้ที่อยู่ในที่เหมาะสมจะได้รับการยกเว้นดังนั้นนี้ตรงกับตัวอักษร หากด้านซ้ายว่างเปล่าจะมีตัวอักษรทั้งหมด เครื่องหมายจุลภาคสามารถละเว้นได้หากด้านขวาว่างเปล่า ตัวละครจะต้องหนีด้วย[],-\\
  • ตัวอักษรตัวพิมพ์ใหญ่ที่ไม่ใช้ค่า Escape เป็น nonterminal และตรงกับนิพจน์ที่กำหนดไว้
  • ถ้าPและQมีการแสดงออกแล้วPQเป็นเพียงการเรียงต่อกันในแนวนอนของพวกเขาและP/Qเป็นเรียงต่อกันในแนวตั้งของพวกเขาด้วยPด้านบน
  • P+คือPแนวนอนหนึ่งแนวขึ้นไปและP/+แนวเดียวกัน
  • การดำเนินงานแบบบูลจะแสดงP|Q, และP&QP!
  • P?คือชวเลขP|_, P*สำหรับP+|_, และสำหรับP/*P/+|_
  • P#ตรงกับสี่เหลี่ยมใด ๆ Pที่มีการแข่งขัน
  • P{a-b,c-d}ที่abcdเป็นจำนวนเต็มไม่ติดลบเป็นข้อ จำกัด ขนาดPบน ถ้าPเป็นคลาสตัวอักษรนิพจน์จะจับคู่กับmxnสี่เหลี่ยมใด ๆที่มีเฉพาะอักขระเหล่านั้นโดยมีเงื่อนไขว่าmระหว่างaและbรวมและnอยู่ระหว่างcและdรวม ในกรณีอื่นนิพจน์จะจับคู่กับสี่เหลี่ยมใด ๆ ที่มีขนาดที่ถูกต้องและPตรงกับ หากaหรือcถูกละเว้นพวกเขาจะถูกนำไปใช้0และหากbหรือdถูกละเว้นพวกเขาจะไม่มีที่สิ้นสุด ถ้าเครื่องหมายขีดคั่นระหว่างaและbถูกละไว้เราจะใช้หมายเลขเดียวกันสำหรับปลายทั้งสองของช่วงเวลา ถ้าทั้งตัวc-dส่วนที่ถูกละไว้ทั้งสองแกนถูก จำกัด ชี้แจง{-b}เทียบเท่ากับ{0-b,0-b}และเทียบเท่ากับ{a-,c}{a-infinity,c-c}

หมายเหตุ

สิ่งสกปรกทำให้คำจำกัดความที่ขัดแย้งกันเช่นเดียวA=A!กับพฤติกรรมที่ไม่ได้กำหนด อย่างไรก็ตามจะไม่ทำให้เกิดการขัดข้องหรือลูปไม่สิ้นสุด

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

ในอนาคตฉันต้องการใช้สิ่งต่อไปนี้:

  • การจับคู่ที่เร็วขึ้น ขณะนี้ล่ามไม่ได้คำนึงถึงข้อเท็จจริงที่ว่าตัวอย่างเช่น.สามารถจับคู่กับ1x1รูปสี่เหลี่ยมผืนผ้าได้เท่านั้น จนกว่าจะพบการจับคู่มันจะพยายามสี่เหลี่ยมผืนผ้าทุกขนาดตามลำดับและล้มเหลวในแต่ละรายการทันที
  • การหมุนและการสะท้อนการดำเนินการสำหรับการค้นหาคำและความท้าทายของเครื่องร่อน
  • การแข่งขันที่ไม่ใช่รูปสี่เหลี่ยมผืนผ้าโดยใช้บริบทซึ่งจะเป็นประโยชน์ในการท้าทายบอร์ดเกรงกลัว ตัวอย่างเช่นPv(Q>R)หมายถึงPบริบทด้านล่าง ( Qพร้อมบริบทที่เหมาะสมR) มันจะตรงกับรูปแบบตัว L

    PPP
    PPP
    QQQRRRR
    QQQRRRR
    QQQRRRR
    

งาน

ได้รับอย่างคร่าวๆตามลำดับความซับซ้อน

สี่เหลี่ยมผืนผ้าของตัวเลข

d{2-}

นี้เป็นเรื่องง่าย: 2x2สี่เหลี่ยมของตัวเลขที่มีขนาดอย่างน้อย

ไม่มีคิวหรือคิว

[,qQ]{4}

นี่เป็นเรื่องง่ายเหมือนคนแรก ตอนนี้เรามีขนาดที่ จำกัด มากขึ้นและคลาสอักขระที่กำหนดเอง

การจัดตำแหน่งแนวนอนและแนวตั้ง

\#.*\#|\#/./*/\#

ตอนนี้เรามีตัวละครบางตัวที่หลบหนี โดยพื้นฐานแล้วสิ่งนี้จะจับคู่กับหนึ่งตัว#จากนั้นก็จะมีจำนวนอักขระใด ๆ ก็ตาม#ไม่ว่าจะเป็นแนวนอนหรือแนวตั้ง

ตรวจจับอินพุตสี่เหลี่ยม

S=.|S./+/.+
e,S

ไวยากรณ์นี้ง่ายมากโดยทั่วไปกำหนดว่าสี่เหลี่ยมเป็นทั้ง1x1สี่เหลี่ยมผืนผ้าหรือสี่เหลี่ยมเล็ก ๆ ที่มีหนึ่งคอลัมน์ติดอยู่ที่ขอบด้านขวาของมันและหนึ่งแถวที่ถูกตรึงที่ด้านล่างของที่ โปรดทราบว่าeตัวเลือกก่อนที่จะยกระดับ nonterminal ซึ่งสลับการตรวจสอบอินพุตทั้งหมด

การค้นหาคำในการค้นหาคำ

G=\G
O=\O
L=\L
F=\F
GOLF|FLOG|G/O/L/F|F/L/O/G|G.../.O../..L./...F|...G/..O./.L../F...|F.../.L../..O./...G|...F/..L./.O../G...

คนนี้น่ากลัวเพราะ Grime ไม่มีการหมุนหรือการสะท้อน นอกจากนี้ยังช้ามากเนื่องจากสิ่งสกปรกไม่ทราบว่าการแข่งขันเท่านั้นที่สามารถจะมีขนาด4x1, หรือ1x44x4

ปัญหาเครื่องร่อนสามารถแก้ไขได้ในทำนองเดียวกัน แต่ฉันขี้เกียจเกินกว่าจะเขียนลงไป

พอร์ทัล Nether

.\X+./\X/+\.{2-22,3-22}\X/+/.\X+.

ด้วยตัวดำเนินการ จำกัด ขนาดคน ๆ นี้ไม่ได้ยากขนาดนั้น ส่วนตรงกลาง\.{2-22,3-22}ตรงกับสี่เหลี่ยมทุก.ขนาดที่ถูกต้องจากนั้นเราก็เพิ่มคอลัมน์ของXทั้งสองข้างและตะปูหัวแถวของXs ด้วยปลายที่ถูกละเว้นที่ด้านบนและล่างของที่นั้น

การจับคู่ข้าม

E=\.+/+
F=\#+/+
EFE/F/EFE&(E/F/E)F(E/F/E)

สิ่งที่เรามีที่นี่คือการรวมกัน (ตรรกะ AND) ของสองนิพจน์ ตัวไม่ใช่เทอร์มินัลEจับคู่กับรูปสี่เหลี่ยมผืนผ้า.s Fที่ไม่ว่าง#เปล่าและรูปสี่เหลี่ยมผืนผ้าที่ไม่ใช่อันว่างเปล่า ด้านซ้ายของการเชื่อมต่อจับคู่กับสี่เหลี่ยมของประเภท

...####..
...####..
...####..
#########
#########
.....##..
.....##..

ที่ที่เรามีEFEอยู่ด้านบนแล้วFจากนั้นEFEอีกครั้ง ทางด้านขวาตรงกับการเปลี่ยนแปลงของสิ่งเหล่านี้ดังนั้นเราจึงได้ไม้กางเขนอย่างแน่นอน

การขุดเพชร

C=./+
T=\X|CTC/\/.+\\
B=\X|\\.+\//CBC
CTC/\X.+\X/CBC

nonterminal Cเป็นชวเลขสำหรับ1xnคอลัมน์ใด ๆ ครึ่งบนของเพชรจะถูกจับคู่โดยT: เป็นอย่างใดอย่างหนึ่งXหรืออย่างอื่นที่Tล้อมรอบด้วยคอลัมน์ทั้งสองด้านและแถว/[something]\ด้านล่าง Bตรงกับด้านล่างของเพชรในลักษณะเดียวกันและ nonterminal ระดับบนสุดเป็นเพียงแถวของรูปแบบX[something]Xระหว่างครึ่งบนและครึ่งล่าง

ค้นหากระดานหมากรุก

(\#\#|\#/\#|\_\_|\_/\_)#!&[#_]{3-}

ด้านขวามือ[#_]{3-}ตรงใด ๆ3x3หรือมีขนาดใหญ่รูปสี่เหลี่ยมผืนผ้า#และ_s ในขณะที่การค้ำประกันด้านซ้ายมือว่ามันไม่ได้มีสองที่อยู่ติดกัน#หรือ_s

การตรวจสอบกระดานหมากรุก

e,(\#\#|\#/\#|\_\_|\_/\_)#!&[#_]+/+

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

ตรวจสอบไวยากรณ์โหมโรง

A=[,()]/*
P=A*|P(A/\(/A)P(A/\)/A)P
e,P

นี่อาจเป็นไวยากรณ์ที่น่าสนใจที่สุด ไม่ใช่เทอร์มินัลAจับคู่คอลัมน์ใด ๆ ที่ไม่มี(หรือ)และPจับคู่จำนวนAs หรือวงเล็บที่จับคู่ทั้งสองระหว่างระหว่างและนอกที่มีPs มากกว่า


@DLosc แก้ไขขอบคุณสำหรับการค้นหาข้อผิดพลาด!
Zgarb

จะ\#(.*|./*)\#ทำงานอย่างไร
seequ

@ ซิกสำหรับการจัดตำแหน่งหรือไม่ น่าเสียดายไม่เพราะจะถูกแยกเป็น "หนึ่ง#ทางซ้ายแล้วแถวหรือคอลัมน์ของสิ่งใดแล้วหนึ่ง#ทางด้านขวา" ฉันจำเป็นต้องระบุว่า#s /จะถูกตัดแบ่งในแนวตั้งเพื่อคอลัมน์โดยใช้เครื่องหมายทับ
Zgarb

10

TMARL

แม่แบบการจับคู่และการรู้จำภาษา

ลักษณะ

ล่ามของฉันจะขึ้น 24K ตัวอักษร ( ตัวอย่างโค้ดใช้เวลาถึงตัวละคร? ) ดังนั้นคำอธิบายแบบเต็มสามารถพบได้ที่นี่

ส่วนที่ดีที่สุด: ล่ามอยู่ใน Javascript ซึ่งหมายความว่าคุณสามารถลองได้ที่นี่!

และสำหรับปัญหา:

# 1 - ค้นหากระดานหมากรุก

$#_#
a
$_#_
bvacvbS5&(avcS5)G0G2P

&ผนวกการค้นหา G2 ในตอนท้ายได้รับองค์ประกอบที่ 3 ในองค์ประกอบการแข่งขันซึ่งเป็นการแข่งขันที่เกิดขึ้นจริง 2 องค์ประกอบแรกคือพิกัด x และ y (ตาม 1 ไม่ใช่ 0)

# 3 - ตรวจหาสี่เหลี่ยมผืนผ้าของตัวเลข

$DD
$DD
S1G2P

ฉันคิดว่าอันนี้ค่อนข้างตรงไปตรงมา

# 4 - การค้นหาคำในการค้นหาคำ

$GO\LF
a
$G
$*O
$**\L
$***F
S6&(aS6)G0G2P

Sอาร์กิวเมนต์เป็นแม้กระทั่งเพื่อที่จะค้นหาผลัดทั้งหมด มีค่ามากกว่า 4 เพราะสามารถผนวกเข้ากับการค้นหาถัดไปได้ (ไม่สามารถต่อท้ายแต่ละรายการได้)

# 5 - ตรวจสอบอินพุตของสแควร์

IL-(IG0L)!P

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

# 6 - ค้นหาเครื่องร่อนในเกมแห่งชีวิต

$## 
$# #
$# 
a
$ ##
$## 
$  #
bS6&(bMS6)&(aS6)&(aMS6)G0G2P

ในที่สุดการใช้กระจก!

# 12 - หลีกเลี่ยงตัวอักษร Q

$[^Qq]
~4*4S1G2P

S1 เนื่องจากต้องการเพียง 1 คู่ที่ตรงกัน

ฉันจะทำสิ่งที่ยากขึ้นในภายหลัง

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