UPDATE! การปรับปรุงประสิทธิภาพครั้งใหญ่! n = 7 เสร็จสมบูรณ์ในเวลาไม่ถึง 10 นาที! ดูคำอธิบายที่ด้านล่าง!
มันสนุกดีที่จะเขียน นี่คือตัวแก้ปัญหาแบบ brute-force สำหรับปัญหานี้ที่เขียนใน Funciton บาง factoids:
- ยอมรับจำนวนเต็มใน STDIN ช่องว่างภายนอกใด ๆ จะทำลายมันรวมถึงการขึ้นบรรทัดใหม่หลังจากจำนวนเต็ม
- มันใช้ตัวเลข 0 ถึงn - 1 (ไม่ใช่ 1 ถึงn )
- มันเติมตาราง“ย้อนกลับ” เพื่อให้คุณได้รับการแก้ปัญหาที่แถวด้านล่างอ่านมากกว่าที่แถวบนสุดอ่าน
3 2 1 0
0 1 2 3
- มันส่งออกอย่างถูกต้อง
0
(ทางออกเดียว) สำหรับn = 1
- เอาท์พุทที่ว่างเปล่าสำหรับn = 2 และn = 3
- เมื่อคอมไพล์เป็น exe จะใช้เวลาประมาณ8¼นาทีสำหรับn = 7 (ประมาณหนึ่งชั่วโมงก่อนการปรับปรุงประสิทธิภาพ) หากไม่มีการรวบรวม (ใช้ล่าม) จะใช้เวลาประมาณ 1.5 เท่าดังนั้นการใช้คอมไพเลอร์จึงคุ้มค่า
- นี่เป็นครั้งแรกที่ฉันเขียนโปรแกรม Funciton ทั้งหมดโดยไม่ต้องเขียนโปรแกรมด้วยภาษาหลอกก่อน ฉันเขียนเป็น C # จริงก่อน
- (อย่างไรก็ตามนี่ไม่ใช่ครั้งแรกที่ฉันทำการเปลี่ยนแปลงเพื่อปรับปรุงประสิทธิภาพของบางสิ่งบางอย่างใน Funciton ครั้งแรกที่ฉันทำนั่นคือในฟังก์ชันแฟคทอเรียลการสลับลำดับตัวถูกดำเนินการของการคูณทำให้แตกต่างกันอย่างมากเนื่องจากอัลกอริทึมการคูณทำงานอย่างไรในกรณีที่คุณอยากรู้)
โดยไม่ต้องกังวลใจเพิ่มเติม:
┌────────────────────────────────────┐ ┌─────────────────┐
│ ┌─┴─╖ ╓───╖ ┌─┴─╖ ┌──────┐ │
│ ┌─────────────┤ · ╟─╢ Ӂ ╟─┤ · ╟───┤ │ │
│ │ ╘═╤═╝ ╙─┬─╜ ╘═╤═╝ ┌─┴─╖ │ │
│ │ └─────┴─────┘ │ ♯ ║ │ │
│ ┌─┴─╖ ╘═╤═╝ │ │
│ ┌────────────┤ · ╟───────────────────────────────┴───┐ │ │
┌─┴─╖ ┌─┴─╖ ┌────╖ ╘═╤═╝ ┌──────────┐ ┌────────┐ ┌─┴─╖│ │
│ ♭ ║ │ × ╟───┤ >> ╟───┴───┘ ┌─┴─╖ │ ┌────╖ └─┤ · ╟┴┐ │
╘═╤═╝ ╘═╤═╝ ╘══╤═╝ ┌─────┤ · ╟───────┴─┤ << ╟─┐ ╘═╤═╝ │ │
┌───────┴─────┘ ┌────╖ │ │ ╘═╤═╝ ╘══╤═╝ │ │ │ │
│ ┌─────────┤ >> ╟─┘ │ └───────┐ │ │ │ │ │
│ │ ╘══╤═╝ ┌─┴─╖ ╔═══╗ ┌─┴─╖ ┌┐ │ │ ┌─┴─╖ │ │
│ │ ┌┴┐ ┌───────┤ ♫ ║ ┌─╢ 0 ║ ┌─┤ · ╟─┤├─┤ ├─┤ Ӝ ║ │ │
│ │ ╔═══╗ └┬┘ │ ╘═╤═╝ │ ╚═╤═╝ │ ╘═╤═╝ └┘ │ │ ╘═╤═╝ │ │
│ │ ║ 1 ╟───┬┘ ┌─┴─╖ └───┘ ┌─┴─╖ │ │ │ │ │ ┌─┴─╖ │
│ │ ╚═══╝ ┌─┴─╖ │ ɓ ╟─────────────┤ ? ╟─┘ │ ┌─┴─╖ │ ├─┤ · ╟─┴─┐
│ ├─────────┤ · ╟─┐ ╘═╤═╝ ╘═╤═╝ ┌─┴────┤ + ╟─┘ │ ╘═╤═╝ │
┌─┴─╖ ┌─┴─╖ ╘═╤═╝ │ ╔═╧═╕ ╔═══╗ ┌───╖ ┌─┴─╖ ┌─┴─╖ ╘═══╝ │ │ │
┌─┤ · ╟─┤ · ╟───┐ └┐ └─╢ ├─╢ 0 ╟─┤ ⌑ ╟─┤ ? ╟─┤ · ╟──────────────┘ │ │
│ ╘═╤═╝ ╘═╤═╝ └───┐ ┌┴┐ ╚═╤═╛ ╚═╤═╝ ╘═══╝ ╘═╤═╝ ╘═╤═╝ │ │
│ │ ┌─┴─╖ ┌───╖ │ └┬┘ ┌─┴─╖ ┌─┘ │ │ │ │
│ ┌─┴───┤ · ╟─┤ Җ ╟─┘ └────┤ ? ╟─┴─┐ ┌─────────────┘ │ │
│ │ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ │ │╔════╗╔════╗ │ │
│ │ │ ┌──┴─╖ ┌┐ ┌┐ ┌─┴─╖ ┌─┴─╖ │║ 10 ║║ 32 ║ ┌─────────────────┘ │
│ │ │ │ << ╟─┤├─┬─┤├─┤ · ╟─┤ · ╟─┘╚══╤═╝╚╤═══╝ ┌──┴──┐ │
│ │ │ ╘══╤═╝ └┘ │ └┘ ╘═╤═╝ ╘═╤═╝ │ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖ │
│ │ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖ ╔═╧═╕ └─┤ ? ╟─┤ · ╟─┤ % ║ │
│ └─────┤ · ╟─┤ · ╟──┤ Ӂ ╟──┤ ɱ ╟─╢ ├───┐ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ │
│ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ ╘═══╝ ╚═╤═╛ ┌─┴─╖ ┌─┴─╖ │ └────────────────────┘
│ └─────┤ │ └───┤ ‼ ╟─┤ ‼ ║ │ ┌──────┐
│ │ │ ╘═══╝ ╘═╤═╝ │ │ ┌────┴────╖
│ │ │ ┌─┴─╖ │ │ │ str→int ║
│ │ └──────────────────────┤ · ╟───┴─┐ │ ╘════╤════╝
│ │ ┌─────────╖ ╘═╤═╝ │ ╔═╧═╗ ┌──┴──┐
│ └──────────┤ int→str ╟──────────┘ │ ║ ║ │ ┌───┴───┐
│ ╘═════════╝ │ ╚═══╝ │ │ ┌───╖ │
└───────────────────────────────────────────────────────┘ │ └─┤ × ╟─┘
┌──────────────┐ ╔═══╗ │ ╘═╤═╝
╔════╗ │ ╓───╖ ┌───╖ │ ┌───╢ 0 ║ │ ┌─┴─╖ ╔═══╗
║ −1 ║ └─╢ Ӝ ╟─┤ × ╟──┴──────┐ │ ╚═╤═╝ └───┤ Ӂ ╟─╢ 0 ║
╚═╤══╝ ╙───╜ ╘═╤═╝ │ │ ┌─┴─╖ ╘═╤═╝ ╚═══╝
┌─┴──╖ ┌┐ ┌───╖ ┌┐ ┌─┴──╖ ╔════╗ │ │ ┌─┤ ╟───────┴───────┐
│ << ╟─┤├─┤ ÷ ╟─┤├─┤ << ║ ║ −1 ║ │ │ │ └─┬─╜ ┌─┐ ┌─────┐ │
╘═╤══╝ └┘ ╘═╤═╝ └┘ ╘═╤══╝ ╚═╤══╝ │ │ │ └───┴─┘ │ ┌─┴─╖ │
│ └─┘ └──────┘ │ │ └───────────┘ ┌─┤ ? ╟─┘
└──────────────────────────────┘ ╓───╖ └───────────────┘ ╘═╤═╝
┌───────────╢ Җ ╟────────────┐ │
┌────────────────────────┴───┐ ╙───╜ │
│ ┌─┴────────────────────┐ ┌─┴─╖
┌─┴─╖ ┌─┴─╖ ┌─┴─┤ · ╟──────────────────┐
│ ♯ ║ ┌────────────────────┤ · ╟───────┐ │ ╘═╤═╝ │
╘═╤═╝ │ ╘═╤═╝ │ │ │ ┌───╖ │
┌─────┴───┘ ┌─────────────────┴─┐ ┌───┴───┐ ┌─┴─╖ ┌─┴─╖ ┌─┤ × ╟─┴─┐
│ │ ┌─┴─╖ │ ┌───┴────┤ · ╟─┤ · ╟──────────┤ ╘═╤═╝ │
│ │ ┌───╖ ┌───╖ ┌──┤ · ╟─┘ ┌─┴─┐ ╘═╤═╝ ╘═╤═╝ ┌─┴─╖ │ │
│ ┌────┴─┤ ♭ ╟─┤ × ╟──┘ ╘═╤═╝ │ ┌─┴─╖ ┌───╖└┐ ┌──┴─╖ ┌─┤ · ╟─┘ │
│ │ ╘═══╝ ╘═╤═╝ ┌───╖ │ │ │ × ╟─┤ Ӝ ╟─┴─┤ ÷% ╟─┐ │ ╘═╤═╝ ┌───╖ │
│ ┌─────┴───┐ ┌────┴───┤ Ӝ ╟─┴─┐ │ ╘═╤═╝ ╘═╤═╝ ╘══╤═╝ │ │ └───┤ Ӝ ╟─┘
│ ┌─┴─╖ ┌───╖ │ │ ┌────╖ ╘═╤═╝ │ └───┘ ┌─┴─╖ │ │ └────┐ ╘═╤═╝
│ │ × ╟─┤ Ӝ ╟─┘ └─┤ << ╟───┘ ┌─┴─╖ ┌───────┤ · ╟───┐ │ ┌─┴─╖ ┌───╖ │ │
│ ╘═╤═╝ ╘═╤═╝ ╘══╤═╝ ┌───┤ + ║ │ ╘═╤═╝ ├──┴─┤ · ╟─┤ × ╟─┘ │
└───┤ └────┐ ╔═══╗ ┌─┴─╖ ┌─┴─╖ ╘═╤═╝ │ ╔═══╗ ┌─┴─╖ ┌─┴─╖ ╘═╤═╝ ╘═╤═╝ │
┌─┴─╖ ┌────╖ │ ║ 0 ╟─┤ ? ╟─┤ = ║ ┌┴┐ │ ║ 0 ╟─┤ ? ╟─┤ = ║ │ │ ┌────╖ │
│ × ╟─┤ << ╟─┘ ╚═══╝ ╘═╤═╝ ╘═╤═╝ └┬┘ │ ╚═══╝ ╘═╤═╝ ╘═╤═╝ │ └─┤ << ╟─┘
╘═╤═╝ ╘═╤══╝ ┌┐ ┌┐ │ │ └───┘ ┌─┴─╖ ├──────┘ ╘═╤══╝
│ └────┤├──┬──┤├─┘ ├─────────────────┤ · ╟───┘ │
│ └┘┌─┴─╖└┘ │ ┌┐ ┌┐ ╘═╤═╝ ┌┐ ┌┐ │
└────────────┤ · ╟─────────┘ ┌─┤├─┬─┤├─┐ └───┤├─┬─┤├────────────┘
╘═╤═╝ │ └┘ │ └┘ │ └┘ │ └┘
└───────────────┘ │ └────────────┘
คำอธิบายของรุ่นแรก
รุ่นแรกใช้เวลาประมาณหนึ่งชั่วโมงในการแก้ปัญหาn = 7 ต่อไปนี้อธิบายส่วนใหญ่ว่ารุ่นที่ทำงานช้านี้ ที่ด้านล่างฉันจะอธิบายสิ่งที่เปลี่ยนแปลงฉันทำเพื่อให้ได้ภายใน 10 นาที
การเที่ยวชมเป็นบิต
โปรแกรมนี้ต้องการบิต มันต้องการบิตจำนวนมากและมันต้องการในตำแหน่งที่ถูกต้องทั้งหมด โปรแกรมเมอร์ Funciton ที่มีประสบการณ์รู้อยู่แล้วว่าหากคุณต้องการบิตnคุณสามารถใช้สูตรได้
ซึ่งใน Funciton สามารถแสดงเป็น
เมื่อทำการปรับประสิทธิภาพให้เหมาะสมฉันพบว่าฉันสามารถคำนวณค่าเดียวกันได้เร็วขึ้นโดยใช้สูตรนี้:
ฉันหวังว่าคุณจะยกโทษให้ฉันว่าฉันไม่ได้อัปเดตกราฟิกสมการทั้งหมดในโพสต์นี้ตามลำดับ
ตอนนี้สมมติว่าคุณไม่ต้องการบล็อกบิตต่อเนื่องกัน ในความเป็นจริงคุณต้องการnบิตในช่วงปกติทุก ๆk -th เช่น:
LSB
↓
00000010000001000000100000010000001
└──┬──┘
k
สูตรนี้ค่อนข้างตรงไปตรงมาเมื่อคุณรู้:
ในโค้ดฟังก์ชันӜ
ใช้ค่าnและkและคำนวณสูตรนี้
การติดตามหมายเลขที่ใช้
มีn ²ตัวเลขในตารางสุดท้ายและตัวเลขแต่ละตัวสามารถใด ๆ ของnที่เป็นไปได้ค่า ในการติดตามว่าอนุญาตให้ใช้หมายเลขใดในแต่ละเซลล์เราจะรักษาหมายเลขที่ประกอบด้วยn ³บิตโดยมีการตั้งค่าบิตเพื่อระบุว่ามีการใช้ค่าเฉพาะ เริ่มแรกตัวเลขนี้คือ 0 อย่างชัดเจน
อัลกอริทึมเริ่มต้นที่มุมล่างขวา หลังจาก“ เดา” หมายเลขแรกคือ 0 เราต้องติดตามความจริงที่ว่า 0 ไม่ได้รับอนุญาตในเซลล์ใด ๆ ในแถวคอลัมน์และเส้นทแยงมุมเดียวกัน:
LSB (example n=5)
↓
10000 00000 00000 00000 10000
00000 10000 00000 00000 10000
00000 00000 10000 00000 10000
00000 00000 00000 10000 10000
10000 10000 10000 10000 10000
↑
MSB
ด้วยเหตุนี้เราคำนวณค่าสี่ค่าต่อไปนี้:
แถวปัจจุบัน:เราต้องการn bits ทุกบิตn -th (หนึ่งต่อเซลล์) แล้วเปลี่ยนเป็นแถวปัจจุบันrโดยจำได้ว่าทุกแถวมีn ²บิต:
คอลัมน์ปัจจุบัน:เราต้องการn bits ทุก ๆn ²-th บิต (หนึ่งต่อแถว) แล้วเปลี่ยนเป็นคอลัมน์cปัจจุบันโดยจำได้ว่าทุกคอลัมน์มีn bits:
เส้นทแยงมุมไปข้างหน้า:เราต้องการบิตnทุก ๆ ... (คุณให้ความสนใจหรือไม่ด่วนคิดออก!) ... n ( n +1) - บิตที่ (ทำได้ดีมาก!) แต่ถ้าเราอยู่บน เส้นทแยงมุมไปข้างหน้า:
เส้นทแยงมุมถอยหลัง:สองสิ่งที่นี่ ก่อนอื่นเราจะรู้ได้อย่างไรว่าเราอยู่ในแนวทแยงย้อนหลัง? ในทางคณิตศาสตร์เงื่อนไขคือc = ( n - 1) - rซึ่งเหมือนกับc = n + (- r - 1) เฮ้นั่นทำให้คุณนึกถึงบางสิ่ง? ถูกต้องมันเป็นส่วนประกอบสองอย่างดังนั้นเราจึงสามารถใช้การปฏิเสธบิต (มีประสิทธิภาพมากใน Funciton) แทนการลดลง ประการที่สองสูตรด้านบนสมมติว่าเราต้องการบิตที่สำคัญน้อยที่สุดที่จะตั้งค่า แต่ในแนวทแยงหลังเราไม่ได้ดังนั้นเราต้องเลื่อนขึ้นโดย ... คุณรู้หรือไม่? ... ถูกต้องn ( n - 1)
นี่ก็เป็นสิ่งเดียวที่เราอาจหารด้วย 0 ถ้าn = 1 อย่างไรก็ตาม Funciton ไม่สนใจ 0 ÷ 0 เป็นเพียง 0 คุณไม่รู้หรอ
ในโค้ดฟังก์ชันҖ
(อันล่างสุด) รับnและดัชนี (ซึ่งคำนวณจากrและcตามการหารและส่วนที่เหลือ) คำนวณค่าสี่ค่าเหล่านี้และor
รวมเข้าด้วยกัน
อัลกอริทึมแรงเดรัจฉาน
อัลกอริทึมแรงเดรัจฉานจะดำเนินการโดยӁ
(ฟังก์ชั่นที่ด้านบน) ใช้n (ขนาดกริด), ดรรชนี (ซึ่งในกริดที่เรากำลังวางตัวเลขอยู่) และใช้ (จำนวนที่มีn ³บิตบอกเราว่าเราสามารถวางตัวเลขใดในแต่ละเซลล์)
ฟังก์ชันนี้คืนค่าลำดับของสตริง แต่ละสตริงเป็นวิธีแก้ปัญหาแบบเต็มของกริด มันเป็นตัวแก้ปัญหาที่สมบูรณ์ มันจะส่งคืนการแก้ปัญหาทั้งหมดถ้าคุณปล่อยให้มัน แต่มันกลับมาเป็นลำดับที่ขี้เกียจประเมิน
หากดัชนีมีค่าถึง 0 เราได้เติมกริดทั้งหมดสำเร็จแล้วดังนั้นเราจึงส่งคืนลำดับที่มีสตริงว่าง (โซลูชันเดียวที่ไม่ครอบคลุมเซลล์ใด ๆ ) สตริงว่างคือ0
และเราใช้ฟังก์ชั่นห้องสมุด⌑
เพื่อเปลี่ยนให้เป็นลำดับองค์ประกอบเดียว
เช็คที่อธิบายไว้ในการปรับปรุงประสิทธิภาพด้านล่างเกิดขึ้นที่นี่
หากดัชนียังไม่ถึง 0 เราจะลดมันลง 1 เพื่อให้ได้ดัชนีที่ตอนนี้เราต้องวางตัวเลข (เรียกว่าix )
เราใช้♫
เพื่อสร้างลำดับขี้เกียจที่มีค่าจาก 0 ถึงn - 1
จากนั้นเราใช้ɓ
(monadic bind) กับแลมบ์ดาที่ทำสิ่งต่อไปนี้ตามลำดับ:
- ดูครั้งแรกที่บิตที่เกี่ยวข้องในการดำเนินการที่จะตัดสินใจว่าจำนวนที่ถูกต้องที่นี่หรือไม่ เราสามารถวางหมายเลขi ได้หากถูกยึด & (1 << ( n × ix ) << i ) ยังไม่ได้ตั้งค่า หากตั้งไว้ให้ส่งคืน
0
(ลำดับที่ว่างเปล่า)
- ใช้
Җ
ในการคำนวณบิตที่สอดคล้องกับแถวคอลัมน์และแนวทแยงปัจจุบัน เปลี่ยนได้โดยผมและจากนั้นor
ก็เข้าสู่การดำเนินการ
- ซ้ำเรียก
Ӂ
เพื่อดึงการแก้ปัญหาทั้งหมดสำหรับเซลล์ที่เหลือผ่านมันใหม่นำและ decremented ix ส่งคืนลำดับของสตริงที่ไม่สมบูรณ์ แต่ละสตริงมีอักขระix (กริดเติมได้ถึงดัชนีix )
- ใช้
ɱ
(แผนที่) เพื่อค้นหาคำตอบที่พบและใช้‼
เพื่อเชื่อมiเข้ากับท้ายแต่ละรายการ ต่อท้าย newline ถ้าindexมีหลายตัวเป็นnหรือเว้นวรรค
สร้างผลลัพธ์
โปรแกรมหลักเรียกӁ
(ตัวค้นหาสัตว์เดรัจฉาน) ด้วยn , index = n ² (จำไว้ว่าเราเติมกริดกลับไปด้านหลัง) และนำมา = 0 (ตอนแรกไม่มีอะไรทำ) หากผลลัพธ์นี้เป็นลำดับว่างเปล่า (ไม่พบวิธีแก้ไข) ให้ส่งออกสตริงว่าง มิฉะนั้นเอาท์พุทสตริงแรกในลำดับ โปรดทราบว่านี่หมายความว่ามันจะประเมินเฉพาะองค์ประกอบแรกของลำดับซึ่งเป็นสาเหตุที่นักแก้ปัญหาไม่ดำเนินการต่อจนกว่าจะพบโซลูชันทั้งหมด
การปรับปรุงประสิทธิภาพ
(สำหรับผู้ที่อ่านคำอธิบายเวอร์ชันเก่าอยู่แล้ว: โปรแกรมไม่สร้างลำดับของลำดับที่ต้องแยกเป็นสตริงสำหรับเอาท์พุตอีกต่อไปมันเพิ่งสร้างลำดับของสตริงโดยตรงฉันได้แก้ไขคำอธิบายตามนั้น แต่นั่นไม่ใช่การปรับปรุงที่สำคัญมันมาที่นี่)
บนเครื่องของฉันคอมไพล์ exe ของรุ่นแรกใช้เวลา 1 ชั่วโมงในการแก้ปัญหาอย่างมากn = 7 นี่ไม่ใช่ภายในระยะเวลาที่กำหนด 10 นาทีดังนั้นฉันจึงไม่ได้พัก (อันที่จริงเหตุผลที่ฉันไม่ได้พักเพราะฉันมีความคิดนี้เกี่ยวกับวิธีเร่งความเร็วให้ใหญ่ขึ้น)
ขั้นตอนวิธีการดังกล่าวข้างต้นจะหยุดการค้นหาและ backtracks ของมันทุกครั้งที่พบเซลล์ที่บิตทั้งหมดในการดำเนินการจำนวนจะถูกตั้งค่าแสดงให้เห็นว่าไม่มีอะไรที่สามารถใส่ลงในมือถือนี้
อย่างไรก็ตามขั้นตอนวิธีการจะยังคงลมๆแล้งๆกรอกตารางขึ้นไปเซลล์ที่บิตทุกคนเป็นชุด มันจะได้เร็วขึ้นมากถ้ามันสามารถที่จะหยุดเร็วที่สุดเท่าที่ใดๆ เพื่อที่จะเต็มไปด้วยในมือถือแล้วได้ทุกบิตชุดที่แล้วแสดงให้เห็นว่าเราไม่เคยสามารถแก้ส่วนที่เหลือของตารางไม่ว่าสิ่งที่หมายเลขเราใส่ใน มัน. แต่อย่างไรคุณได้อย่างมีประสิทธิภาพตรวจสอบว่าใด ๆเซลล์มีของnบิตตั้งโดยไม่ต้องผ่านทั้งหมดของพวกเขา?
เคล็ดลับเริ่มต้นด้วยการเพิ่มบิตเดียวต่อเซลล์ไปยังหมายเลขที่ถ่าย แทนที่จะเป็นสิ่งที่แสดงไว้ด้านบนตอนนี้จะเป็นดังนี้:
LSB (example n=5)
↓
10000 0 00000 0 00000 0 00000 0 10000 0
00000 0 10000 0 00000 0 00000 0 10000 0
00000 0 00000 0 10000 0 00000 0 10000 0
00000 0 00000 0 00000 0 10000 0 10000 0
10000 0 10000 0 10000 0 10000 0 10000 0
↑
MSB
แทนที่จะเป็นn ³ตอนนี้มีบิตn ² ( n + 1) ในจำนวนนี้ ฟังก์ชั่นที่เติมแถว / คอลัมน์ / แนวทแยงปัจจุบันมีการเปลี่ยนแปลงตามจริง (จริง ๆ แล้วเขียนใหม่ทั้งหมดเพื่อความซื่อสัตย์) ฟังก์ชั่นที่จะยังคงเติมเพียงn0
บิตต่อเซลล์แม้ว่าดังนั้นบิตพิเศษที่เราเพิ่งเพิ่มจะเป็น
ทีนี้สมมติว่าเราผ่านการคำนวณไปครึ่งทางแล้วเราเพิ่งวางไว้1
ในเซลล์ตรงกลางและจำนวนที่นำมามีลักษณะดังนี้:
current
LSB column (example n=5)
↓ ↓
11111 0 10010 0 01101 0 11100 0 11101 0
00011 0 11110 0 01101 0 11101 0 11100 0
11111 0 11110 0[11101 0]11100 0 11100 0 ← current row
11111 0 11111 0 11111 0 11111 0 11111 0
11111 0 11111 0 11111 0 11111 0 11111 0
↑
MSB
อย่างที่คุณเห็นเซลล์บนซ้าย (ดัชนี 0) และเซลล์กลางซ้าย (ดัชนี 10) ตอนนี้เป็นไปไม่ได้ เราจะตรวจสอบเรื่องนี้ได้อย่างมีประสิทธิภาพมากที่สุดได้อย่างไร?
พิจารณาตัวเลขที่บิตที่ 0 ของแต่ละเซลล์ถูกตั้งค่า แต่ขึ้นอยู่กับดัชนีปัจจุบันเท่านั้น ตัวเลขดังกล่าวนั้นง่ายต่อการคำนวณโดยใช้สูตรที่คุ้นเคย:
เราจะได้อะไรถ้าเราเพิ่มตัวเลขทั้งสองเข้าด้วยกัน
LSB LSB
↓ ↓
11111 0 10010 0 01101 0 11100 0 11101 0 10000 0 10000 0 10000 0 10000 0 10000 0 ╓───╖
00011 0 11110 0 01101 0 11101 0 11100 0 ║ 10000 0 10000 0 10000 0 10000 0 10000 0 ║
11111 0 11110 0 11101 0 11100 0 11100 0 ═══╬═══ 10000 0 10000 0 00000 0 00000 0 00000 0 ═════ ╓─╜
11111 0 11111 0 11111 0 11111 0 11111 0 ║ 00000 0 00000 0 00000 0 00000 0 00000 0 ═════ ╨
11111 0 11111 0 11111 0 11111 0 11111 0 00000 0 00000 0 00000 0 00000 0 00000 0 o
↑ ↑
MSB MSB
ผลลัพธ์คือ:
OMG
↓
00000[1]01010 0 11101 0 00010 0 00011 0
10011 0 00001 0 11101 0 00011 0 00010 0
═════ 00000[1]00001 0 00011 0 11100 0 11100 0
═════ 11111 0 11111 0 11111 0 11111 0 11111 0
11111 0 11111 0 11111 0 11111 0 11111 0
อย่างที่คุณเห็นการเพิ่มล้นเข้าไปในบิตพิเศษที่เราเพิ่ม แต่เฉพาะถ้าบิตทั้งหมดสำหรับเซลล์นั้นถูกตั้งค่า! ดังนั้นสิ่งที่เหลืออยู่ที่ต้องทำคือการปิดบังบิตเหล่านั้น (สูตรเดียวกันกับด้านบน แต่ << n ) และตรวจสอบว่าผลลัพธ์เป็น 0:
00000[1]01010 0 11101 0 00010 0 00011 0 ╓╖ 00000 1 00000 1 00000 1 00000 1 00000 1 ╓─╖ ╓───╖
10011 0 00001 0 11101 0 00011 0 00010 0 ╓╜╙╖ 00000 1 00000 1 00000 1 00000 1 00000 1 ╓╜ ╙╖ ║
00000[1]00001 0 00011 0 11100 0 11100 0 ╙╥╥╜ 00000 1 00000 1 00000 0 00000 0 00000 0 ═════ ║ ║ ╓─╜
11111 0 11111 0 11111 0 11111 0 11111 0 ╓╜╙╥╜ 00000 0 00000 0 00000 0 00000 0 00000 0 ═════ ╙╖ ╓╜ ╨
11111 0 11111 0 11111 0 11111 0 11111 0 ╙──╨─ 00000 0 00000 0 00000 0 00000 0 00000 0 ╙─╜ o
ถ้ามันไม่เป็นศูนย์กริดเป็นไปไม่ได้และเราสามารถหยุดได้
- สกรีนช็อตแสดงวิธีแก้ปัญหาและเวลาทำงานสำหรับ n = 4 ถึง 7