CJam, 33 32 20 19 17 ไบต์
รุ่นที่ปรับปรุงใหม่พร้อมการรองรับอย่างมากจาก @ Sp3000 และ @ MartinBüttner:
qN/_z]{:e`z,3<}/|
ลองออนไลน์
การมีส่วนร่วม
- @ Sp3000 แนะนำการลดความซับซ้อนที่สำคัญให้กับอัลกอริทึมดั้งเดิมของฉัน
- @ MartinBüttnerใช้ทักษะการตีกอล์ฟที่บ้าคลั่งของเขากับวิธีการแก้ไขซึ่งเกือบจะส่งผลให้รหัสสั้นกว่าที่ฉันคิดไว้แม้หลังจากพิจารณาถึงความเรียบง่าย
อัลกอริทึมและการพิสูจน์
ต่อไปนี้จะอธิบายถึงเกณฑ์สำหรับปริศนาที่เลื่อนออกจากกันในแนวนอน กรณีแนวตั้งสามารถกำหนดได้โดยดูที่คอลัมน์แทนที่จะเป็นแถวหรือย้ายเมทริกซ์อักขระและดูแถวอีกครั้ง
ฉันจะใช้คำว่า "ยืด" สำหรับลำดับสูงสุดของตัวอักษรเดียวกัน ตัวอย่างเช่นแถวต่อไปนี้มี 1, 2 และ 3 ทอดยาวตามลำดับ:
AAAAAAAA
BBBAAAAA
AABBBAAA
ฉันจะใช้คำว่า "interlocked" เป็นแถว / ตัวต่อที่ไม่สามารถเลื่อนออกจากกันได้
สังเกตที่สำคัญคือปริศนาสามารถเลื่อนออกจากกันและถ้าหากทุกคนมีแถวที่มากที่สุด 2 เหยียด หรือกลับก็จะประสานและถ้าหากมีแถวใด ๆ ที่มีมากกว่า 2 เหยียด
ต่อไปนี้อาจไม่ถือว่าเป็นข้อพิสูจน์ทางคณิตศาสตร์ที่เข้มงวด แต่ฉันเชื่อว่ามันเป็นคำอธิบายที่น่าเชื่อถือว่าทำไมต้องเป็นเช่นนี้
มันง่ายที่จะเห็นว่าตัวต่อถูกเชื่อมต่อกันถ้ามันมีแถวมากกว่า 2 แนว ดูแถวที่มี 3 เหยียด:
BBBAAB
เห็นได้ชัดว่ามันป้องกันปริศนาจากการเลื่อนแยกเนื่องจากการA
ยืดถูกล็อกระหว่างการB
เหยียด ซึ่งหมายความว่าแถวนั้นเชื่อมต่อกันซึ่งจะทำให้ตัวต่อทั้งหมดประสานกัน
ทิศทางตรงกันข้ามของการพิสูจน์นั้นค่อนข้างชัดเจน เราจำเป็นต้องแสดงให้เห็นว่าไม่มีปริศนาเชื่อมต่อกันที่ทุกแถวมีเพียง 1 หรือ 2 แถวเท่านั้น เริ่มต้นด้วยการสังเกตสองสามข้อ:
- แถวที่มีการยืดเพียง 1 อันไม่ได้ช่วยไขปริศนาที่เชื่อมต่อกันเนื่องจากสามารถเลื่อนไปในทิศทางใดก็ได้โดยไม่เกิดการชน
- หากแถวทั้งหมดที่มี 2 เหยียดมีคำสั่งเหมือนกัน
A
และB
ปริศนาจะไม่เชื่อมประสานกันอย่างชัดเจน ในกรณีนี้A
เซลล์ทั้งหมดจะอยู่ด้านซ้ายของB
เซลล์ทั้งหมดหรือในทางกลับกันและไม่มีการชนกันเมื่อเลื่อนทั้งสองชิ้นออกจากกัน
กรณีที่ยุ่งยากเท่านั้นจะเป็นปริศนาที่เรามีแถวที่มีลำดับที่แตกต่างกัน 2 อัน ฉันจะแสดงให้เห็นว่าปริศนาดังกล่าวไม่มีอยู่ภายใต้ข้อกำหนดที่กำหนด หากต้องการแสดงสิ่งนี้ให้ดูที่ตัวต่อบางส่วนที่มีการกำหนดค่านี้ซึ่ง.
เป็นสัญลักษณ์แทน:
.......
AAABBBB
.......
BBAAAAA
.......
ตอนนี้สเปคบอกว่าทั้งสองA
และB
เซลล์มีการเชื่อมต่อในปริศนาที่ถูกต้องทั้งหมด ในการทำให้A
เซลล์เชื่อมต่อในปริศนาบางส่วนด้านบนเรามีสองตัวเลือก:
เราวนรอบหนึ่งในB
ตัวอย่าง:
..AAAAAA
AAABBBBA
.......A
BBAAAAAA
........
ในการทำเช่นนี้เราหลีกเลี่ยงไม่ได้ที่จะขยายหนึ่งในแถวให้มี 3 แนวดังนั้นเราจะไม่ไขปริศนาที่ถูกต้องที่ทุกแถวมีแนวยืดได้ไม่เกิน 2 แถว
เราเชื่อมต่อพวกเขาบนเส้นทางตรง:
.......
AAABBBB
..A....
BBAAAAA
.......
A
เซลล์ตอนนี้เพียงแค่เชื่อมต่อและยังคงไม่มีแถวที่มีมากกว่า 2 เหยียด อย่างไรก็ตามB
เซลล์จำเป็นต้องเชื่อมต่ออย่างง่ายดาย เส้นทางตรงถูกบล็อกโดยA
เซลล์ที่เชื่อมต่อแล้วและวิธีเดียวในการเชื่อมต่อB
เซลล์คือการวนรอบหนึ่งในA
เซลล์ที่ยืดออก สิ่งนี้นำไปสู่กรณีที่ 1 ซึ่งเราไม่สามารถทำได้โดยไม่ต้องสร้างแถวยาว 3 แถว
เมื่อต้องการนับการยืดการใช้งานใช้ตัวดำเนินการ CJam RLE
คำอธิบายของรหัส
qN/ Get input and split at newlines.
_z Make a transposed copy.
] Wrap the original and transposed puzzle in an array so that we can
loop over the two.
{ Start of loop over original and transposed puzzle.
:e` Apply RLE to all rows.
z, Transpose the matrix with the RLE rows, and take the element count of the
result. Or in other words, take the column count. This will be the length
of the longest row after RLE.
3< Check the length for less than 3.
}/ End of loop over original and transposed puzzle.
| Or the results of the two.