Perl 5 , -p0 105 101 96 93 90 89 ไบต์
ใช้bแทน1อินพุต
ตรวจสอบให้แน่ใจว่าเมทริกซ์ใน STDIN ถูกยกเลิกด้วยการขึ้นบรรทัดใหม่
#!/usr/bin/perl -p0
s%b%$_="$`z$'";s:|.:/
/>s#(\pL)(.{@{-}}|)(?!\1)(\pL)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
ลองออนไลน์!
ใช้การทดแทน 3 ระดับ!
เวอร์ชัน 87 ไบต์นี้มีทั้งในรูปแบบอินพุตและเอาต์พุตที่ตีความได้ง่ายกว่า แต่ไม่สามารถแข่งขันได้เนื่องจากใช้อักขระต่างกัน 3 ตัวในเอาต์พุต:
#!/usr/bin/perl -0p
s%b%$_="$`z$'";s:|.:/
/>s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
ลองออนไลน์!
เป็นการง่ายที่จะบันทึกไบต์อื่น ( sตัวแก้ไขregex ) ในทั้งสองเวอร์ชันโดยใช้อักขระ (ไม่ใช่ตัวอักษรและตัวเลข) ที่แตกต่างกันเป็นตัวยุติแถว (แทนที่จะขึ้นบรรทัดใหม่) แต่นั่นทำให้อินพุตไม่สามารถอ่านได้อีกครั้ง
มันทำงานอย่างไร
พิจารณาการทดแทน
s#(\w)(.{columns}|)(?!1)(\w)#c$2c#s
นี้จะได้พบกับตัวอักษรสองตัวที่มีความแตกต่างกันและติดกันในแนวนอนหรือแนวตั้งอื่น ๆ cและแทนที่พวกเขาด้วย ในเขาวงกตที่มีเส้นทางที่ประกอบด้วยทั้งตัวอักษรbอะไรจะเกิดขึ้นตั้งแต่ตัวอักษรที่เหมือนกัน แต่ทันทีที่หนึ่งของตัวอักษรจะถูกแทนที่ด้วยอีกคนหนึ่ง (เช่นz) ตัวอักษรที่และเพื่อนบ้านจะถูกแทนที่ด้วยcและทำซ้ำการประยุกต์ใช้เป็น น้ำท่วมเติมขององค์ประกอบที่เชื่อมต่อกับจากเมล็ดcz
ในกรณีนี้ฉันไม่ต้องการเติมน้ำท่วมทั้งหมด ฉันต้องการเติมแขนข้างหนึ่งเพียงข้างzเดียวดังนั้นหลังจากขั้นตอนแรกฉันก็อยากจะzหายไป ใช้งานได้แล้วกับการc$2cแทนที่ แต่ภายหลังฉันต้องการเริ่มต้นเติมน้ำท่วมตามแขนอีกข้างโดยเริ่มจากจุดเดิมและฉันไม่รู้ว่าcs อันไหนเป็นของเดิมzอีกต่อไป ดังนั้นฉันจะใช้แทน
s#(\w)(.{columns}|)(?!\1)(\w)#$&|a.$2.a#se
b | aเป็นc, b | cเป็นcและเป็นz | a {ดังนั้นในเขาวงกตที่ประกอบด้วยเส้นทางbและเมล็ดzในขั้นตอนแรกbจะถูกแทนที่ด้วยcและzจะถูกแทนที่ด้วย{ซึ่งไม่ใช่ตัวอักษรและไม่ตรงกัน\wและจะไม่ทำให้เกิดการเติมเพิ่มเติม cแต่จะทำให้น้ำท่วมต่อเติมไปและเพื่อนบ้านแขนข้างหนึ่งของเมล็ดพันธุ์ที่ได้รับการเติมเต็ม เช่นเริ่มจาก
b c
b c
bbzbb becomes bb{bb
b b
b b
ฉันสามารถแทนที่ c ทั้งหมดด้วยตัวอักษรที่ไม่ใช่ (เช่น-) และแทนที่{ด้วยzอีกครั้งเพื่อเริ่มการเติมน้ำท่วม:
- -
- -
bbzbb becomes cc{bb
b b
b b
และทำซ้ำขั้นตอนนี้จนกว่าเพื่อนบ้านทั้งหมดของเมล็ดจะถูกแปลง ถ้าฉันอีกครั้งแทนที่{ด้วยzและเติมน้ำท่วม:
- -
- -
--z-- stays --z--
- -
- -
สิ่งที่zเหลืออยู่ข้างหลังในตอนท้ายเพราะไม่มีเพื่อนบ้านที่จะเปลี่ยนแปลงด้วย ทำให้ชัดเจนว่าเกิดอะไรขึ้นในส่วนของรหัสต่อไปนี้:
/\n/ >
ค้นหา newline แรก ออฟเซ็ตเริ่มต้นมาถึงแล้ว@-
s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se
regex ที่กล่าวถึงข้างต้นด้วย@{-}จำนวนคอลัมน์ (ตั้งแต่ธรรมดา@-ทำให้สับสน parser perl และไม่ถูกแทนอย่างถูกต้อง)
&&
/\n/เสมอประสบความสำเร็จและเปลี่ยนตัวเป็นจริงตราบใดที่เรายังสามารถเติมน้ำท่วม ดังนั้นการดำเนินการส่วนหลัง&&หากการเติมน้ำท่วมของแขนข้างหนึ่งเสร็จสิ้น หากไม่ใช่ด้านซ้ายจะประเมินเป็นสตริงว่าง
y/{c/z / > 0
รีสตาร์ทการเติมน้ำท่วมและกลับ 1 ถ้าเติมน้ำท่วมก่อนหน้านี้ทำอะไร มิฉะนั้นส่งคืนสตริงว่าง โค้ดทั้งหมดนี้ห่ออยู่ข้างใน
s:|.: code :seg
ดังนั้นหากสิ่งนี้ถูกดำเนินการในสตริงเริ่มต้น$_ด้วยzที่ตำแหน่งเมล็ดชิ้นส่วนของรหัสภายในจะถูกดำเนินการหลายครั้งส่วนใหญ่กลับไม่มีอะไร แต่1ทุกครั้งที่แขนเพื่อนบ้านได้รับน้ำท่วม ได้อย่างมีประสิทธิภาพ$_ได้รับการทำลายและถูกแทนที่ด้วยเป็นจำนวนมากในฐานะที่มีส่วนประกอบที่เกี่ยวโยงกันที่แนบมากับ1 zขอให้สังเกตว่าการวนซ้ำจะต้องดำเนินการจนถึงผลรวมของขนาดส่วนประกอบ + จำนวนครั้งของอาวุธ แต่ก็ตกลงเพราะจะ "จำนวนตัวอักษรรวมถึงการขึ้นบรรทัดใหม่ * 2 + 1" ครั้ง
เขาวงกตจะถูกตัดการเชื่อมต่อหากไม่มี1(สตริงว่างเปล่า, จุดยอดที่แยกได้) หรือหากมีมากกว่า 1 แขน (มากกว่า 2 1วินาที) สิ่งนี้สามารถตรวจสอบได้โดยใช้ regex /\B/(สิ่งนี้ให้0แทนที่จะเป็น1รุ่น Perl ที่เก่ากว่ามันพิสูจน์ได้ว่าอันไหนผิด) 0แต่น่าเสียดายถ้ามันไม่ตรงนี้จะให้เป็นสตริงว่างแทน แต่s:|.: code :segได้รับการออกแบบเสมอกลับเป็นเลขคี่เช่นนั้นโดยทำ&กับ/\B/นี้จะให้หรือ01
สิ่งที่เหลืออยู่ก็คือการเดินเข้าไปในอาเรย์ทั้งหมดและในแต่ละตำแหน่งเมล็ดที่สามารถเดินได้ด้วยzและนับแขนที่เชื่อมต่อ สามารถทำได้อย่างง่ายดายด้วย:
s%b%$_="$`z$'"; code %eg
ปัญหาเดียวคือในตำแหน่งที่ไม่สามารถเดินได้ค่าเก่าจะถูกเก็บไว้ เนื่องจากเราต้องการ0ที่นั่นนั่นหมายถึงอาร์เรย์อินพุตดั้งเดิมต้อง0อยู่ในตำแหน่งที่ไม่สามารถเดินได้และ0จับคู่\wในการทดแทนเดิมและจะทำให้เกิดการเติมน้ำท่วม นั่นเป็นเหตุผลที่ฉันใช้\pLแทน (จับคู่ตัวอักษรเท่านั้น)