Якщо я намагаюся імітувати кубик Рубіка , як би ви створили структуру даних для зберігання стану куба в пам'яті, з кількістю X плиток на стороні?
Що слід врахувати:
- куб може бути будь-якого розміру
- це кубик Рубіка, тому шари можна обертати
Якщо я намагаюся імітувати кубик Рубіка , як би ви створили структуру даних для зберігання стану куба в пам'яті, з кількістю X плиток на стороні?
Що слід врахувати:
Відповіді:
Що не так із простим старим масивом розміру [6X][X]
? Вам не потрібно знати про внутрішні міні-кубики, тому що ви їх не бачите; вони не входять до складу куба. Сховайте два потворних методу за приємним і простим у використанні інтерфейсом, тестуйте його на смерть і вуаля, ви готові!
As long as you know how the six surfaces are "threaded" together
Саме це дасть вам більш міцна структура даних. Я думаю, ми сперечаємось про те саме. Сторони масиву, а сторона - це масив блоків, проте є багато цікавих властивостей щодо сторін і блоків, які допомагають з'ясувати, що "нанизування" цього терміна не дуже подобається, тому що його можна переплутати з багатопотоковою ниткою; )
Слід зазначити, що я завзятий куб швидкості, але ніколи не намагався програмно представляти кубик Рубіка в алгоритмі чи структурі даних.
Я, мабуть, створив би окремі структури даних для захоплення унікальних аспектів кожного блоку в кубі.
На кубі є 3 різних типи блоків:
Кутовий блок - він має три кольорові грані та три сусідні частини, з якими він зможе ділитися стороною в будь-який час.
Блоковий край - має два кольорові грані та має 4 суміжні частини, з якими він зможе ділитися стороною у будь-який час. У 3х3 блоках завжди є 2 центральних частини та 2 кутових частини.
Центральний блок - у кубі 3х3 цей шматок не є рухомим, проте його можна обертати. Він завжди матиме 4 сусідні крайні блоки. У більших кубиках є декілька центральних блоків, які можуть ділитися з іншим центральним блоком або краєм. Центральні блоки ніколи не примикають до кутового блоку.
Знаючи це, блок може мати список посилань на інші блоки, до яких він торкається. Я б утримував ще один список списків, який би являв собою список блоків, що представляють одну грань куба, і список, який зберігає посилання на кожну грань куба.
Кожне кубичне обличчя було б представлене як унікальне обличчя.
З цими структурами даних було б досить легко написати алгоритм, який виконує перетворення обертання на кожній грані, переміщуючи відповідні блоки у відповідні списки та виходячи з них.
EDIT: Важлива примітка, ці списки потрібно, звичайно, замовити, але я забув це згадати. Наприклад, якщо я перевертаю праву сторону, то лівий кут правого бічного блоку переміщується в правий кут правого боку і повертається за годинниковою стрілкою.
list of lists
. можливо, краще просто мати не упорядкований список блоків, до яких можна здійснити запит. і ви просто оновлюєте сусідні посилання блоку, коли здійснюєте перетворення. Якщо ви хочете переглянути список всіх блоків в обличчі, ви можете запитати свій список для всіх сусідніх блоків до центрального блоку, так?
Коли я думаю про цю проблему, я думаю про статичний куб з кольорами, що рухаються по ньому за відомими візерунками. Тому....
Об'єкт Куб містить 6 бічних об'єктів, які залишаються фіксованими з індексом 0-5. Кожна сторона містить 9 об'єктів позиції, які залишаються фіксованими з індексом 0-8. Кожна позиція містить колір.
Для простоти обробляйте кожну дію з кроком на чверть обороту. Існує 3 осі обертання, кожна в 2 можливих напрямках для загальної кількості 6 можливих дій на кубі. З цією інформацією стає досить простим завданням відобразити 6 можливих дій на кубі.
Таким чином, зелений колір в стороні 6, позиції 3, може переходити в положення 1 в сторону 1 або в сторону 2 в позицію 7, в залежності від вжитих дій. Я не вивчив цього достатньо, щоб знайти будь-які математичні переклади, але, ймовірно, з'являться шаблони, якими можна скористатися в коді.
Використовуючи структуру даних, як я можу знати, чи вирішується певний куб у певному стані? Я сам боровся з цим питанням і ще не знайшов відповіді.
Для цього ніколи не починайте з випадкового стану куба. Натомість почніть з розв’язаного стану та виконайте n дій програмно, щоб перевести куб у випадковий початковий стан. Оскільки ви вживали лише юридичних дій, щоб дійти до поточного стану, куб повинен бути вирішеним.
Я знайшов систему координат xyz як простий спосіб вирішення куба Рубіка, а матриці обертання - простий, загальний спосіб здійснення обертань.
Я створив клас Piece, що містить вектор позиції (x, y, z)
. Шматок можна обертати, застосувавши матрицю обертання до його положення (множення матричного вектора). Шматок також відстежує кольори в кортежі (cx, cy, cz)
, надаючи кольори, звернені вздовж кожної осі. Невелика кількість логіки забезпечує ці кольори належним чином оновлені під час обертання: обертання на 90 градусів у площині XY означає, що ми будемо міняти значеннями cx
та cy
.
Оскільки вся логіка обертання інкапсульована у класі Piece, Куб може зберігати не упорядкований список Шматок, а обертання можна робити в загальному вигляді. Щоб здійснити обертання лівої грані, виділіть усі шматки з x-координатою -1 та застосуйте відповідну матрицю обертання до кожного Шматка. Щоб зробити обертання всього куба, застосуйте однакову матрицю обертання до кожного шматка.
Ця реалізація проста і має кілька приємностей:
(-1, 1, 1)
), край має рівно один нуль ( (1, 0, -1)
), а центральний шматок - два нулі ( (-1, 0, 0)
).Недоліки:
ви можете використовувати простий масив (кожен елемент має відображення від 1 до 1 на квадрат на обличчі) та імітувати кожне обертання з певною перестановкою
ви можете піти лише з трьома основними перестановками: обертати фрагмент з віссю через передню поверхню, обертати куб навколо вертикальної осі та обертати куб над горизонтальною віссю через ліву та праву грані. всі інші рухи можуть бути виражені деякою конкатенацією цих трьох.
найпростіший спосіб дізнатися, чи вирішується куб, - це вирішити його (знайдіть серію перестановок, які вирішать куб), якщо в кінцевому підсумку вийдуть 2 ребра, які помінялися місцем, один перевернутий край, один перевернутий кут або 2 поміняні куточки у вас нерозбірний куб
the most straightforward way of know whether a cube is solvable is to solve it
. Ну, використовуючи запропоновану вами модель, я думаю, це правда. Але якщо ви використовуєте модель, ближчу до обертання @ maple_shaft та доріжки, ви можете швидко перевірити, чи вирішується куб 3x3x3, перевіривши суму обертів ребер mod 2 0 і кутових обертів mod 3 дорівнює 0. Потім перевіряйте парність перестановки на підраховуючи крайові свопи та кутові заміни (потрібні, щоб повернутися до вирішення), їх сума mod 2 повинна бути 0 (рівномірний паритет). Це необхідні та достатні тести, щоб довести, що куб вирішується.
Перша умова, щоб це було вирішено, полягало б у тому, щоб кожен шматок був присутній і щоб кольори на кожному шматочку могли бути використані для складання «совісного» куба. Це відносно тривіальна умова, істинність якої можна визначити простим контрольним списком. Колірна гамма на "стандартному" кубі визначена , але навіть якщо ти не маєш справу зі стандартним кубом, їх всього 6! можливі комбінації розв’язаних граней.
Після того, як ви маєте всі шматки та кольори правильно, то вирішувати, чи вирішена будь-яка фізична конфігурація. Не всі вони є. Найнаївніший спосіб перевірити це - запустити алгоритм вирішення куба і побачити, чи він закінчується вирішеним кубом. Я не знаю, чи існують химерні комбінаторні методики для визначення розчинності, не намагаючись вирішити куб.
Щодо структури даних ... це майже не має значення. Складна частина полягає в правильному перетворенні і можливості представити стан куба таким чином, що дозволяє акуратно працювати з доступними алгоритмами в літературі. Як вказує Кленовий вал, є три типи штук. Література про вирішення кубика Рубіка завжди стосується творів за їх типом. Трансформації також представлені загальними способами (дивіться позначення Singmaster ). Крім того, всі рішення, які я бачив, завжди посилаються на один фрагмент як на орієнтир (зазвичай ставлять білу центральну частину внизу).
Оскільки ви вже отримали чудові відповіді, дозвольте додати лише детальну інформацію.
Незалежно від конкретного представлення, зауважте, що лінзи - це дуже чудовий інструмент для "збільшення" на різних частинах куба. Наприклад, подивіться на функцію cycleLeft
в цьому Haskell коду . Це загальна функція, яка циклічно перетворює будь-який список довжиною 4. Код для виконання руху L виглядає приблизно так:
moveL :: Aut (RubiksCube a)
moveL =
cong cube $ cong leftCols cycleLeft
. cong leftSide rotateSideCW
Таким чином cycleLeft
діє на точку зору, яку дає leftCols
. Аналогічно, rotateSideCW
що є загальною функцією, яка бере сторону до поворотної її версії, діє на вигляд, поданий автором leftSide
. Інші кроки можна реалізувати аналогічно.
Мета цієї бібліотеки Haskell - створити гарні фотографії. Я думаю, що це вдалося:
Здається, ви задаєте два окремих питання.
- Як зобразити куб із X кількістю сторін?
Якщо ви збираєтеся імітувати куб Рубіка в реальному світі, то всі кубики Рубіка мають 6 сторін. Я думаю, що ви маєте на увазі "кількість X плиток на розмір на стороні". Кожна сторона оригінального куба Рубіка - 3х3. Інші розміри включають 4х4 (кубик професора), 5х5 та 6х6.
Я б представляв дані з 6 сторін, використовуючи "стандартний" куб вирішення позначень:
Кожна сторона - це двовимірний масив 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 відповідей, ця структура даних дозволяє вам використовувати перетин множин для визначення розташування кожного підблока в кубі. Це врятує роботу над необхідністю оновлення найближчих підблоків при зміні.