JBAujogue commited on
Commit
a478bce
·
1 Parent(s): 2d5d0cd

first cube class

Browse files
Files changed (2) hide show
  1. README.md +14 -2
  2. src/rubik/cube.py +88 -0
README.md CHANGED
@@ -14,8 +14,20 @@ pre-commit install
14
 
15
  ## Basic usage
16
 
17
- ```shell
18
- python -m rubik hello "World"
 
 
 
 
 
 
 
 
 
 
 
 
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])