Spaces:
Sleeping
Sleeping
first cube class
Browse files- README.md +14 -2
- src/rubik/cube.py +88 -0
README.md
CHANGED
@@ -14,8 +14,20 @@ pre-commit install
|
|
14 |
|
15 |
## Basic usage
|
16 |
|
17 |
-
```
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
```
|
20 |
|
21 |
## Roadmap
|
|
|
14 |
|
15 |
## Basic usage
|
16 |
|
17 |
+
```python
|
18 |
+
from cubik import Cube
|
19 |
+
|
20 |
+
cube = Cube.from_default(['U', 'L', 'C', 'R', 'B', 'D'], size = 3)
|
21 |
+
print(cube)
|
22 |
+
# UUU
|
23 |
+
# UUU
|
24 |
+
# UUU
|
25 |
+
# LLL CCC RRR BBB
|
26 |
+
# LLL CCC RRR BBB
|
27 |
+
# LLL CCC RRR BBB
|
28 |
+
# DDD
|
29 |
+
# DDD
|
30 |
+
# DDD
|
31 |
```
|
32 |
|
33 |
## Roadmap
|
src/rubik/cube.py
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from dataclasses import dataclass
|
2 |
+
|
3 |
+
import torch
|
4 |
+
|
5 |
+
|
6 |
+
@dataclass
|
7 |
+
class Cube:
|
8 |
+
"""
|
9 |
+
A 5D tensor filled with 0 or 1. Dimensions have the following interpretation:
|
10 |
+
- X coordinate (from 0 to self.size - 1, from Left to Right).
|
11 |
+
- Y coordinate (from 0 to self.size - 1, from Back to Front).
|
12 |
+
- Z coordinate (from 0 to self.size - 1, from Down to Up).
|
13 |
+
- Face (from 0 to 5, with 0 = "Up", 1 = "Left", 2 = "Front", 3 = "Right", 4 = "Back", 5 = "Down").
|
14 |
+
- Color (from 0 to 6, 0 being the "dark" color, the rest according to order given in "colors" attribute).
|
15 |
+
"""
|
16 |
+
|
17 |
+
tensor: torch.Tensor
|
18 |
+
colors: list[str]
|
19 |
+
size: int
|
20 |
+
|
21 |
+
@classmethod
|
22 |
+
def from_default(cls, colors: list[str], size: int) -> "Cube":
|
23 |
+
"""
|
24 |
+
Create Cube from a given list of 6 colors and size.
|
25 |
+
Example:
|
26 |
+
cube = Cube.from_default(['U', 'L', 'C', 'R', 'B', 'D'], size = 3)
|
27 |
+
"""
|
28 |
+
assert (num := len(set(colors))) == 6, f"Expected 6 distinct colors, got {num}"
|
29 |
+
assert isinstance(size, int) and size > 1, (
|
30 |
+
f"Expected non-zero integrer size, got {size}"
|
31 |
+
)
|
32 |
+
|
33 |
+
# build tensor filled with 0's, and fill the faces with 1's
|
34 |
+
n = size - 1
|
35 |
+
tensor = torch.zeros([size, size, size, 6, 7], dtype=torch.int8)
|
36 |
+
tensor[:, :, n, 0, 1] = 1 # up
|
37 |
+
tensor[0, :, :, 1, 2] = 1 # left
|
38 |
+
tensor[:, 0, :, 2, 3] = 1 # front
|
39 |
+
tensor[n, :, :, 3, 4] = 1 # right
|
40 |
+
tensor[:, n, :, 4, 5] = 1 # back
|
41 |
+
tensor[:, :, 0, 5, 6] = 1 # down
|
42 |
+
return cls(tensor, colors, size)
|
43 |
+
|
44 |
+
def to_grid(self) -> list[list[list[str]]]:
|
45 |
+
"""
|
46 |
+
Convert Cube into a 3D grid representation.
|
47 |
+
"""
|
48 |
+
n = self.size - 1
|
49 |
+
grid = [
|
50 |
+
self.tensor[:, :, n, 0, :].argmax(dim=-1), # up
|
51 |
+
self.tensor[0, :, :, 1, :].argmax(dim=-1), # left
|
52 |
+
self.tensor[:, 0, :, 2, :].argmax(dim=-1), # front
|
53 |
+
self.tensor[n, :, :, 3, :].argmax(dim=-1), # right
|
54 |
+
self.tensor[:, n, :, 4, :].argmax(dim=-1), # back
|
55 |
+
self.tensor[:, :, 0, 5, :].argmax(dim=-1), # down
|
56 |
+
]
|
57 |
+
return [
|
58 |
+
[[self.colors[i - 1] for i in row] for row in face.tolist()]
|
59 |
+
for face in grid
|
60 |
+
]
|
61 |
+
|
62 |
+
def __str__(self):
|
63 |
+
"""
|
64 |
+
Compute a string representation of a cube.
|
65 |
+
Example:
|
66 |
+
cube = Cube.from_default(['U', 'L', 'C', 'R', 'B', 'D'], size = 3)
|
67 |
+
print(cube)
|
68 |
+
# UUU
|
69 |
+
# UUU
|
70 |
+
# UUU
|
71 |
+
# LLL CCC RRR BBB
|
72 |
+
# LLL CCC RRR BBB
|
73 |
+
# LLL CCC RRR BBB
|
74 |
+
# DDD
|
75 |
+
# DDD
|
76 |
+
# DDD
|
77 |
+
"""
|
78 |
+
grid = self.to_grid()
|
79 |
+
void = " " * self.size
|
80 |
+
top = "\n".join(" ".join([void, "".join(row), void, void]) for row in grid[0])
|
81 |
+
middle = "\n".join(
|
82 |
+
" ".join("".join(grid[face_i][row_i]) for face_i in range(1, 5))
|
83 |
+
for row_i in range(self.size)
|
84 |
+
)
|
85 |
+
bottom = "\n".join(
|
86 |
+
" ".join((void, "".join(row), void, void)) for row in grid[-1]
|
87 |
+
)
|
88 |
+
return "\n".join([top, middle, bottom])
|