Welcome, guest | Sign In | My Account | Store | Cart

I have four cubes (in real) with different colors on their sides as a puzzle with the final goal to place each cube side by side that way that on each visible side (except the two ends) you can see four different colors.

I have placed the cubes as they are (side by side) writing down the current colors (see function main). The CubesChecker class is searching for one solution. You don't see the operation on how to rotate but knowing the final state it's really easy to do it yourself then.

Python, 178 lines
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 """ @author Thomas Lehmann @file four_cubes_problem.py There are four cubes with concrete colors on their sides and the goal is to place each cube in one row that way, that along the row each side presents four different colors: - - - - |W| |R| |G| |B| (front view) - - - - Of course four different colors are also required at the top view at the bottom view and at the back view. Background: I have those four cubes in real and I have been seeking for the solution without manual try. """ import random class Color: """ represents a kind of enum for all used colors """ GREEN = 0 RED = 1 WHITE = 2 BLUE = 3 MAX = 4 @staticmethod def name(value): return ["GREEN", "RED", "WHITE", "BLUE"][value] class Cube: def __init__(self, front, back, left, right, top, bottom): """ initializes all sides of a cube with colors """ self.front = front self.back = back self.left = left self.right = right self.top = top self.bottom = bottom def __eq__(self, other): """ compares this cube and another for to be equal """ return self.front == other.front \ and self.back == other.back \ and self.left == other.left \ and self.right == other.right \ and self.top == other.top \ and self.bottom == other.bottom def __hash__(self): """ unique key for this instance """ return hash((self.front, self.back, self.left, self.right, self.top, self.bottom)) def clone(self): """ provides a copy of this instance """ return Cube(self.front, self.back, self.left, self.right, self.top, self.bottom) def __str__(self): """ does print the current cube setup (colors) """ return "front:" + Color.name(self.front) + "," + \ "back:" + Color.name(self.back) + "," + \ "left:" + Color.name(self.left) + "," + \ "right:" + Color.name(self.right) + "," + \ "top:" + Color.name(self.top) + "," + \ "bottom:" + Color.name(self.bottom) def getCombinations(self): """ I know: there should be 24 combinations """ cubes = set() cubes.add(self.clone()) cube = self.clone() while not len(cubes) == 24: mode = random.randint (0, 4) if 0 == mode: cube.rotateLeft() elif 1 == mode: cube.rotateRight() elif 2 == mode: cube.rotateTop() elif 3 == mode: cube.rotateBottom() cubes.add(cube.clone()) return cubes def rotateLeft(self): """ does rotate the cube to the left """ help = self.left self.left = self.front self.front = self.right self.right = self.back self.back = help return self def rotateRight(self): """ does rotate the cube to the right """ help = self.right self.right = self.front self.front = self.left self.left = self.back self.back = help return self def rotateTop(self): """ does rotate the cube to the top """ help = self.top self.top = self.front self.front = self.bottom self.bottom = self.back self.back = help return self def rotateBottom(self): """ does rotate the cube to the bottom """ help = self.bottom self.bottom = self.front self.front = self.top self.top = self.back self.back = help return self class CubesChecker: def __init__(self, cubes): self.originalCubes = cubes @staticmethod def isValidState(cubes): """ ensure the rule: four different colors on each side """ frontColors = set() backColors = set() topColors = set() bottomColors = set() for cube in cubes: frontColors.add(cube.front) backColors.add(cube.back) topColors.add(cube.top) bottomColors.add(cube.bottom) return len(frontColors) == Color.MAX \ and len(backColors) == Color.MAX \ and len(topColors) == Color.MAX \ and len(bottomColors) == Color.MAX def calculate(self, position = 0, cubes = []): """ find the cubes final state """ if len(cubes) == Color.MAX: if CubesChecker.isValidState(cubes): for cube in cubes: print(cube) return True else: return False for cube in self.originalCubes[position].getCombinations(): if self.calculate(position+1, cubes + [cube]): return True return False def main(): """ there are four cubes with concrete colors on their sides and the goal is to place each cube in one row that way that along the row each side presents four different colors """ # ----------- ----------- ----------- ----------- ----------- ----------- # front back left right top bottom # ----------- ----------- ----------- ----------- ----------- ----------- cubes = [ Cube(Color.GREEN, Color.WHITE, Color.GREEN, Color.RED, Color.WHITE, Color.BLUE), Cube(Color.WHITE, Color.RED , Color.WHITE, Color.GREEN, Color.BLUE, Color.RED), Cube(Color.RED, Color.RED, Color.RED , Color.GREEN, Color.BLUE, Color.WHITE), Cube(Color.BLUE, Color.RED, Color.GREEN, Color.GREEN, Color.WHITE, Color.BLUE) ] cubesChecker = CubesChecker(cubes) cubesChecker.calculate() if __name__ == "__main__": main()

Here's the printed solution:

>C:\Python32\pythonw.exe -u "four_cubes_problem.py"
front:WHITE,back:GREEN,left:WHITE,right:BLUE,top:GREEN,bottom:RED
front:RED,back:BLUE,left:RED,right:WHITE,top:WHITE,bottom:GREEN
front:GREEN,back:RED,left:RED,right:RED,top:BLUE,bottom:WHITE
front:BLUE,back:WHITE,left:GREEN,right:GREEN,top:RED,bottom:BLUE
>Exit code: 0
 Created by Thomas Lehmann on Mon, 11 Feb 2013 (MIT)