ถ้าฉันพยายามจำลองลูกบาศก์ของรูบิคคุณจะสร้างโครงสร้างข้อมูลอย่างไรเพื่อเก็บสถานะของคิวบ์ไว้ในหน่วยความจำโดยมีไทล์ X จำนวนต่อด้าน
สิ่งที่ต้องพิจารณา:
- ลูกบาศก์สามารถมีขนาดใดก็ได้
- มันเป็นลูกบาศก์ของรูบิคดังนั้นชั้นจึงสามารถหมุนได้
ถ้าฉันพยายามจำลองลูกบาศก์ของรูบิคคุณจะสร้างโครงสร้างข้อมูลอย่างไรเพื่อเก็บสถานะของคิวบ์ไว้ในหน่วยความจำโดยมีไทล์ X จำนวนต่อด้าน
สิ่งที่ต้องพิจารณา:
คำตอบ:
มีอะไรผิดปกติกับอาร์เรย์เก่าธรรมดาขนาด[6X][X]
? คุณไม่จำเป็นต้องรู้เกี่ยวกับด้านมินิก้อนเพราะคุณไม่เห็นพวกเขา; ไม่ได้เป็นส่วนหนึ่งของสถานะคิวบ์ ซ่อนสองวิธีที่น่าเกลียดที่อยู่เบื้องหลังอินเตอร์เฟซที่ดูดีและใช้งานง่ายทดสอบหน่วยถึงความตายและ voila คุณทำเสร็จแล้ว!
As long as you know how the six surfaces are "threaded" together
ซึ่งเป็นสิ่งที่โครงสร้างข้อมูลที่แข็งแกร่งจะให้คุณ ฉันคิดว่าเรากำลังโต้เถียงในสิ่งเดียวกัน ด้านอาเรย์และด้านที่เป็นอาเรย์ของบล็อกอย่างไรก็ตามมีคุณสมบัติที่น่าสนใจมากมายเกี่ยวกับด้านข้างและบล็อกที่ช่วยให้คิดว่า "การทำเกลียว" ไม่ชอบคำนั้นเพราะมันอาจสับสนกับมัลติเธรด )
ควรสังเกตว่าฉันเป็นนักบิดความเร็วตัวยง แต่ฉันไม่เคยพยายามที่จะเป็นตัวแทนของคิวบ์ของ Rubik โดยทางโปรแกรมในอัลกอริทึมหรือโครงสร้างข้อมูล
ฉันอาจจะสร้างโครงสร้างข้อมูลแยกต่างหากเพื่อจับภาพลักษณะเฉพาะของแต่ละบล็อกในคิวบ์
มี 3 ประเภทของบล็อกที่แตกต่างกันในก้อน:
มุมบล็อก - มันมีใบหน้าสามสีและสามชิ้นที่อยู่ติดกันซึ่งมันจะแบ่งปันด้านข้างได้ตลอดเวลา
Edge Block - มันมีใบหน้าสองสีและมีชิ้นส่วนที่อยู่ติดกัน 4 ชิ้นที่จะแบ่งปันด้านข้างได้ตลอดเวลา ในบล็อก 3x3 มันมี 2 ชิ้นกลางและ 2 มุมเสมอ
บล็อกกลาง - ในลูกบาศก์ 3x3 ชิ้นส่วนนี้ไม่สามารถเคลื่อนย้ายได้ แต่สามารถหมุนได้ มันจะมีบล็อคขอบ 4 อันติดกันเสมอ ในคิวบ์ที่มีขนาดใหญ่จะมีบล็อกกลางหลายอันที่สามารถแชร์กับบล็อกกลางอื่นหรือขอบชิ้น บล็อกกึ่งกลางจะไม่ติดกับบล็อกมุม
เมื่อรู้สิ่งนี้บล็อกสามารถมีรายการของการอ้างอิงไปยังบล็อกอื่น ๆ ที่มันสัมผัส ฉันจะเก็บรายการของลิสต์อื่นซึ่งจะเป็นลิสต์ของบล็อกที่แสดงถึงคิวบ์ใบหน้าเดียวและรายการที่เก็บการอ้างอิงถึงคิวบ์ใบหน้าทุกอัน
คิวบ์ใบหน้าทุกอันจะถูกนำเสนอเป็นใบหน้าที่ไม่ซ้ำ
ด้วยโครงสร้างข้อมูลเหล่านี้จะเป็นการง่ายที่จะเขียนอัลกอริธึมที่ดำเนินการเปลี่ยนแปลงการหมุนในแต่ละหน้าย้ายบล็อกที่เหมาะสมเข้าและออกจากรายการที่เหมาะสม
แก้ไข:หมายเหตุสำคัญรายการเหล่านี้จะต้องสั่งแน่นอน แต่ฉันลืมที่จะพูดถึงว่า ตัวอย่างเช่นถ้าฉันพลิกด้านขวาจากนั้นบล็อกมุมด้านขวาด้านซ้ายจะย้ายไปที่มุมขวาของด้านขวาและหมุนตามเข็มนาฬิกา
list of lists
แต่ไม่เปลี่ยนแปลงจะเป็นที่น่าเบื่อเพราะคุณจะต้องอัปเดตการอ้างอิงไปยังบล็อกของคุณและที่อยู่ติดกัน อาจดีกว่าที่จะมีรายการบล็อกที่ไม่มีการเรียงลำดับที่คุณสามารถสืบค้นได้ และคุณเพิ่งอัปเดตการอ้างอิงบล็อกที่อยู่ติดกันเมื่อคุณทำการแปลง หากคุณต้องการรายการบล็อกทั้งหมดในหน้าคุณสามารถค้นหารายการบล็อกที่อยู่ติดกันทั้งหมดไปยังบล็อกกลางได้ใช่ไหม
เมื่อฉันคิดถึงปัญหานี้ฉันคิดว่าลูกบาศก์แบบคงที่โดยมีสีที่เคลื่อนที่ผ่านในรูปแบบที่เป็นที่รู้จัก ดังนั้น....
วัตถุ Cube ประกอบด้วยวัตถุ 6 ด้านที่ยังคงอยู่ในดัชนีคงที่ 0-5 แต่ละด้านมีวัตถุ 9 ตำแหน่งที่ยังคงมีการจัดทำดัชนีไว้ 0-8 แต่ละตำแหน่งมีสี
สำหรับความเรียบง่ายจัดการทุกการกระทำในการเปิดรอบที่เพิ่มขึ้น มีการหมุน 3 แกนแต่ละทิศทางเป็นไปได้ 2 ทิศทางสำหรับการกระทำที่เป็นไปได้ทั้งหมด 6 รายการบนคิวบ์ ด้วยข้อมูลนี้มันจะกลายเป็นงานที่ค่อนข้างง่ายในการแมปการกระทำที่เป็นไปได้ 6 อย่างบนคิวบ์
ดังนั้นสีเขียวในด้าน 6 ตำแหน่ง 3 อาจเลื่อนไปด้านข้าง 1 ตำแหน่ง 3 หรือด้าน 2 ตำแหน่ง 7 ขึ้นอยู่กับการดำเนินการ ฉันไม่ได้สำรวจเรื่องนี้มากพอที่จะค้นหาคำแปลทางคณิตศาสตร์ใด ๆ แต่รูปแบบอาจจะปรากฏว่าคุณสามารถใช้ประโยชน์จากในรหัส
การใช้โครงสร้างข้อมูลฉันจะทราบได้อย่างไรว่าลูกบาศก์บางอย่างในสถานะที่แน่นอนสามารถแก้ไขได้? ฉันดิ้นรนกับคำถามนี้ด้วยตัวเองและยังไม่พบคำตอบเลย
เมื่อต้องการทำสิ่งนี้อย่าเริ่มต้นด้วยสถานะคิวบ์แบบสุ่ม แทนที่จะเริ่มต้นด้วยรัฐแก้ไขและดำเนินการnการกระทำของโปรแกรมที่จะได้รับก้อนเข้าสู่สถานะเริ่มต้นสุ่ม เนื่องจากคุณดำเนินการทางกฎหมายเพื่อไปยังสถานะปัจจุบันเท่านั้นจึงต้องแก้ไขคิวบ์ได้
ฉันพบระบบพิกัด xyz เป็นวิธีที่ง่ายในการจัดการกับลูกบาศก์ของรูบิคและเมทริกซ์การหมุนเป็นวิธีทั่วไปที่ง่าย ๆ ในการใช้การหมุน
(x, y, z)
ฉันสร้างชั้นชิ้นที่มีเวกเตอร์ตำแหน่ง ชิ้นส่วนสามารถหมุนได้โดยใช้เมทริกซ์การหมุนกับตำแหน่ง (การคูณเมทริกซ์เวกเตอร์) The Piece ยังเก็บแทร็กของสีไว้ใน tuple (cx, cy, cz)
โดยให้สีหันไปตามแต่ละแกน จำนวนเล็กน้อยของตรรกะให้สีเหล่านี้มีการปรับปรุงอย่างเหมาะสมในระหว่างการหมุน: หมุน 90 องศาในระนาบ XY หมายความว่าเราจะสลับค่าของและcx
cy
เนื่องจากตรรกะการหมุนทั้งหมดถูกห่อหุ้มในคลาส Piece คิวบ์สามารถเก็บรายการชิ้นส่วนที่ไม่มีการเรียงลำดับและการหมุนสามารถทำได้ในแบบทั่วไป ในการหมุนใบหน้าซ้ายให้เลือกทุกชิ้นด้วยพิกัด x เป็น -1 และใช้เมทริกซ์การหมุนที่เหมาะสมกับแต่ละชิ้น ในการทำการหมุนของลูกบาศก์ทั้งหมดให้ใช้เมทริกซ์การหมุนเดียวกันกับทุกชิ้น
การนำไปใช้งานนี้ง่ายและมีสองตระกูล:
(-1, 1, 1)
) ขอบมีค่าเท่ากับหนึ่งศูนย์ ( (1, 0, -1)
) และชิ้นส่วนกึ่งกลางมีศูนย์สองศูนย์ ( (-1, 0, 0)
)ข้อเสีย:
คุณสามารถใช้อาเรย์ง่าย ๆ (แต่ละองค์ประกอบมีการแมป 1 ถึง 1 กับสี่เหลี่ยมจัตุรัสบนใบหน้า) และจำลองการหมุนแต่ละครั้งด้วยการเปลี่ยนแปลง
คุณสามารถหนีไปได้ด้วยการเปลี่ยนสับเปลี่ยนที่จำเป็นเพียง 3 อย่าง: หมุนชิ้นด้วยแกนแม้ว่าด้านหน้าด้านหน้าหมุนลูกบาศก์รอบแกนแนวตั้งและหมุนลูกบาศก์เหนือแกนแนวนอนผ่านใบหน้าซ้ายและขวา การเคลื่อนไหวอื่น ๆ ทั้งหมดสามารถแสดงออกโดยการต่อกันของทั้งสามนี้
วิธีที่ตรงไปตรงมาที่สุดในการรู้ว่าลูกบาศก์แก้ปัญหาได้หรือไม่ (หาวิธีเรียงสับเปลี่ยนแบบที่จะแก้ปัญหาลูกบาศก์) หากคุณจบลงด้วย 2 ขอบที่เปลี่ยนตำแหน่งเป็นขอบพลิกเดี่ยวมุมพลิกเดี่ยวหรือ 2 มุมที่ถูกสับเปลี่ยนคุณจะมีลูกบาศก์ที่ไม่สามารถเปลี่ยนได้
the most straightforward way of know whether a cube is solvable is to solve it
. การใช้แบบจำลองที่คุณแนะนำฉันคิดว่ามันเป็นเรื่องจริง แต่ถ้าคุณใช้แบบจำลองใกล้กับ @ maple_shaft's และการหมุนของแทร็กคุณสามารถทดสอบได้อย่างรวดเร็วว่าลูกบาศก์ 3x3x3 สามารถแก้ไขได้โดยการตรวจสอบผลรวมของ edge flips mod 2 คือ 0 และการหมุนมุม mod 3 คือ 0 จากนั้นตรวจสอบความเท่าเทียมกันของการเปลี่ยนแปลง การนับจำนวนการสลับขอบและการสลับมุม (จำเป็นต้องกลับไปแก้ไข), ผลรวม mod 2 ของพวกเขาจะต้องเป็น 0 (รวมเท่าเทียมกัน) นี่คือการทดสอบที่จำเป็นและเพียงพอเพื่อพิสูจน์ว่าลูกบาศก์สามารถแก้ไขได้
เงื่อนไขแรกที่สามารถแก้ไขได้คือแต่ละชิ้นนั้นมีอยู่และสีในแต่ละชิ้นสามารถใช้เพื่อประกอบลูกบาศก์ "sovled" นี่เป็นเงื่อนไขที่ค่อนข้างเล็กน้อยซึ่งสามารถระบุความจริงได้ด้วยรายการตรวจสอบอย่างง่าย ชุดรูปแบบสีในคิวบ์ "มาตรฐาน" ถูกกำหนดไว้แต่แม้ว่าคุณจะไม่ได้ติดต่อกับคิวบ์มาตรฐานมีเพียง 6! การรวมกันที่เป็นไปได้ของใบหน้าที่แก้ไขแล้ว
เมื่อคุณมีชิ้นส่วนและสีทั้งหมดถูกต้องแล้วมันเป็นเรื่องที่กำหนดว่าการกำหนดค่าทางกายภาพใด ๆ ที่กำหนดจะสามารถแก้ไขได้ ไม่ใช่ทั้งหมด วิธีที่ไร้เดียงสาที่สุดในการตรวจสอบสิ่งนี้คือการเรียกใช้อัลกอริทึมการแก้ไขคิวบ์และดูว่ามันสิ้นสุดลงด้วยคิวบ์ที่ถูกแก้ไขหรือไม่ ฉันไม่รู้ว่ามีเทคนิค combinatorial แฟนซีเพื่อตรวจสอบการแก้ปัญหาโดยไม่ต้องพยายามแก้ไขลูกบาศก์
สำหรับโครงสร้างข้อมูลอะไร ... ที่เกือบจะไม่สำคัญ ส่วนที่ยุ่งยากคือการแปลงให้ถูกต้องและสามารถแสดงสถานะคิวบ์ในแบบที่ช่วยให้คุณสามารถทำงานกับอัลกอริทึมที่มีอยู่ในวรรณคดีได้อย่างเรียบร้อย ดังที่ Maple-shaft ระบุว่ามีชิ้นส่วนสามประเภท วรรณกรรมเกี่ยวกับการแก้ปัญหาลูกบาศก์รูบิคมักจะอ้างอิงถึงชิ้นส่วนตามประเภทของพวกเขา การแปลงจะแสดงด้วยวิธีทั่วไป (ค้นหาสัญกรณ์ Singmaster ) นอกจากนี้วิธีแก้ปัญหาทั้งหมดที่ฉันเห็นมักจะอ้างถึงชิ้นเดียวเป็นจุดอ้างอิง (มักจะวางชิ้นกลางสีขาวที่ด้านล่าง)
เนื่องจากคุณได้รับคำตอบที่ยอดเยี่ยมแล้วให้ฉันเพิ่มรายละเอียด
โดยไม่คำนึงถึงการเป็นรูปธรรมของคุณโปรดทราบว่าเลนส์เป็นเครื่องมือที่ดีมากสำหรับ "ซูมเข้า" ในส่วนต่างๆของลูกบาศก์ ตัวอย่างเช่นดูฟังก์ชันcycleLeft
ในรหัส Haskellนี้ มันเป็นฟังก์ชั่นทั่วไปที่ cyclically อนุญาตรายการใด ๆ ของความยาว 4 รหัสสำหรับการดำเนินการย้าย L มีลักษณะดังนี้:
moveL :: Aut (RubiksCube a)
moveL =
cong cube $ cong leftCols cycleLeft
. cong leftSide rotateSideCW
จึงcycleLeft
ดำเนินการในมุมมองที่ได้รับจาก leftCols
ในทำนองเดียวกันซึ่งเป็นฟังก์ชั่นการทั่วไปด้านข้างเป็นรุ่นที่หมุนของมันดำเนินการในมุมมองที่ได้รับจากrotateSideCW
leftSide
การเคลื่อนไหวอื่น ๆ สามารถดำเนินการในลักษณะที่คล้ายกัน
เป้าหมายของห้องสมุด Haskell คือการสร้างภาพสวย ๆ ฉันคิดว่ามันประสบความสำเร็จ:
คุณดูเหมือนจะถามคำถามสองข้อแยกกัน
- วิธีการแทนลูกบาศก์ที่มีจำนวนด้าน X เป็นอย่างไร
หากคุณจะจำลองลูกบาศก์รูบิคในโลกแห่งความเป็นจริงลูกบาศก์ของรูบิคทั้งหมดจะมี 6 ด้าน ฉันคิดว่าสิ่งที่คุณหมายถึงคือ "จำนวน X กระเบื้องต่อมิติต่อด้าน" แต่ละด้านของลูกบาศก์รูบิคดั้งเดิมคือ 3x3 ขนาดอื่น ๆ รวมถึง 4x4 (ศาสตราจารย์ของ Cube), 5x5 และ 6x6
ฉันจะแทนข้อมูลด้วย 6 ด้านโดยใช้สัญลักษณ์แก้ปัญหาคิวบ์ "มาตรฐาน":
แต่ละด้านเป็นอาร์เรย์ 2 มิติของ X คูณ X
ฉันชอบความคิดของ @maple_shaft เพื่อแสดงชิ้นส่วนต่าง ๆ (มินิคิวบ์) แตกต่างกัน: ชิ้นกลาง, ขอบและมุมมีสี 1, 2, หรือ 3 สีตามลำดับ
ฉันจะแสดงความสัมพันธ์ระหว่างพวกเขาเป็นกราฟ (แบบสองทิศทาง) โดยมีขอบเชื่อมต่อชิ้นส่วนที่อยู่ติดกัน แต่ละชิ้นจะมีช่องสำหรับขอบ (การเชื่อมต่อ): 4 ช่องในชิ้นกลาง, 4 ช่องในชิ้นส่วนขอบ, 3 ช่องในชิ้นมุม อีกทางหนึ่งชิ้นกลางอาจมีการเชื่อมต่อ 4 ชิ้นกับขอบชิ้นส่วนและ 4 สำหรับชิ้นส่วนมุมแยกจากกันและ / หรือชิ้นส่วนขอบอาจมี 2 ชิ้นเชื่อมต่อกับชิ้นส่วนกลางและ 2 ถึงชิ้นส่วนแยก
อาร์เรย์เหล่านี้มีการเรียงลำดับเพื่อให้การวนซ้ำบนขอบกราฟแสดงถึงการหมุน 'เดียวกัน' เสมอโดยปรับการหมุนของลูกบาศก์ นั่นคือเช่นสำหรับชิ้นส่วนกึ่งกลางหากคุณหมุนลูกบาศก์เพื่อให้ใบหน้าอยู่ด้านบนลำดับการเชื่อมต่อจะเป็นตามเข็มนาฬิกาเสมอ ในทำนองเดียวกันสำหรับชิ้นส่วนขอบและมุม คุณสมบัตินี้มีการหมุนหน้าหลังจากนั้น
การตรวจจับเงื่อนไขที่ไม่สามารถแก้ไขได้อย่างชัดเจน (สลับเปลี่ยน / พลิกพลิกมุม) หากหวังว่าจะง่ายเช่นกันเพราะการค้นหาชิ้นส่วนบางประเภทและการวางแนวนั้นง่าย
แล้วโหนดและพอยน์เตอร์ล่ะ
สมมติว่ามี 6 ใบหน้าเสมอและ 1 โหนดนั้นหมายถึง 1 สี่เหลี่ยมจัตุรัสต่อ 1 หน้า:
r , g , b
r , g , b
r , g , b
| | |
r , g , b - r , g , b
r , g , b - r , g , b
r , g , b - r , g , b
โหนดมีตัวชี้ไปยังแต่ละโหนดถัดจากมัน การหมุนเป็นวงกลมเพียงแค่ย้ายตัวชี้ (จำนวนโหนด / จำนวนใบหน้า) -1 โหนดในกรณีนี้ 2 เนื่องจากการหมุนทั้งหมดเป็นการหมุนวนคุณเพียงแค่สร้างrotate
ฟังก์ชันเดียว เป็นการเรียกซ้ำย้ายแต่ละโหนดหนึ่งที่ว่างและตรวจสอบว่ามันเคลื่อนย้ายได้เพียงพอหรือไม่เนื่องจากมันจะรวบรวมจำนวนโหนดและมีใบหน้าสี่หน้าเสมอ หากไม่มีให้เพิ่มจำนวนครั้งที่ย้ายค่าแล้วหมุนโทรอีกครั้ง
อย่าลืมว่ามันมีการเชื่อมโยงเป็นสองเท่าดังนั้นโปรดอัปเดตโหนดแหลมใหม่เช่นกัน จะมีการย้ายจำนวนโหนดความสูง * ความกว้างเสมอโดยมีการอัปเดตตัวชี้หนึ่งตัวต่อโหนดดังนั้นควรมีการปรับปรุงจำนวนตัวชี้ความสูง * กว้าง * 2
เนื่องจากโหนดทั้งหมดชี้ไปที่กันและกันเพียงแค่เดินวนไปรอบ ๆ เพื่ออัพเดตแต่ละโหนดเมื่อคุณเข้ามา
สิ่งนี้ควรใช้กับคิวบ์ขนาดใดก็ได้โดยไม่มีเคสขอบหรือตรรกะที่ซับซ้อน มันเป็นเพียงแค่ตัวชี้เดิน / อัปเดต
จากประสบการณ์ส่วนตัวโดยใช้ชุดเพื่อติดตามแต่ละส่วนการหมุนของคิวบ์ทำงานได้ดี แต่ละคิวบ์ย่อยจะมีสามชุดซึ่งไม่มีขนาดเท่ากับรูบิคคิวบ์ เพื่อหาลูกบาศก์ย่อยที่ลูกบาศก์รูบิคคุณแค่หาจุดตัดของทั้งสามเซต (ผลลัพธ์คือหนึ่งลูกบาศก์ย่อย) หากต้องการย้ายให้ลบลูกย่อยที่ได้รับผลกระทบจากชุดที่เกี่ยวข้องในการย้ายแล้ววางกลับเข้าไปในชุดที่นำพวกเขาไปเป็นผลมาจากการย้าย
ลูกบาศก์ 4 คูณ 4 จะมี 12 ชุด 6 ชุดสำหรับใบหน้า 6 หน้าและ 6 ชุดสำหรับวงดนตรีหกวงที่ไปรอบ ๆ ลูกบาศก์ ใบหน้าแต่ละคนมี 16 ลูกย่อยและแต่ละวงมี 12 ลูกย่อย มีลูกบาศก์ย่อยทั้งหมด 56 ก้อน คิวบ์ย่อยแต่ละอันจะเก็บข้อมูลเกี่ยวกับสีและทิศทางของสี ลูกบาศก์รูบิคนั้นเป็นอาร์เรย์ขนาด 4 คูณ 4 คูณ 4 โดยแต่ละองค์ประกอบมีข้อมูลซึ่งประกอบด้วย 3 ชุดที่กำหนดคิวบ์ย่อยที่ตำแหน่งนั้น
ซึ่งแตกต่างจาก 11 คำตอบอื่น ๆ โครงสร้างข้อมูลนี้มีคุณใช้จุดตัดของชุดเพื่อกำหนดตำแหน่งของแต่ละบล็อกย่อยในคิวบ์ สิ่งนี้จะบันทึกงานที่ต้องอัปเดตบล็อกย่อยใกล้เมื่อมีการเปลี่ยนแปลง