Skip to content

Commit fb4338b

Browse files
authored
burik:0.1.0 (#2708)
1 parent 4a5b1f4 commit fb4338b

File tree

12 files changed

+1079
-0
lines changed

12 files changed

+1079
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
« Copyright © 2025 Gabin Calmet
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4+
5+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software. »
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Burik — A Typst Library for easy Rubik's Cube tutorials edition
2+
3+
**Burik** is a Typst library specifically designed to facilitate the creation of tutorials for **3x3 Rubik's Cube** solving.
4+
5+
Burik was first designed to make life easier for tutorial creators, as it allows algorithms manipulation in strings and algorithms visualization with parametrizable drawing functions from different point of view.
6+
7+
There is also an interest for the tutorial's user as there is no possible mismatch between the written algorithm and the displayed image.
8+
9+
## Installation
10+
11+
To use this package, simply add the following code to your document:
12+
13+
`#import "@preview/burik:0.1.0"`
14+
15+
You can check the example file for more details.
16+
17+
18+
## Use Example
19+
20+
````typ
21+
#import "@preview/burik:0.1.0"
22+
23+
#f2l("f R' f'")
24+
#oll("r U R' U R U2 r'")
25+
#pll("R' U R' U' R3 U' R' U R U R2")
26+
````
27+
<table>
28+
<tr> Click on the image to open an example file </tr>
29+
<td>
30+
<p align="center">
31+
<a href="./example.typ">
32+
<img src="./thumbnail.png">
33+
</a>
34+
</p>
35+
</td>
36+
</table>
37+
38+
## How it works ?
39+
40+
When you pass an algorithm to Burik, it inverts it and executes it on a solved cube. As a result, you obtain the configuration in which executing the non-inverted algorithm is useful.
41+
42+
## Moves
43+
44+
Moves used to encode an algorithm on the Rubik's Cube are the standard ones (visit [J Perm](https://jperm.net/3x3/moves) for +) :
45+
46+
- `F, B, R, L, U, D` for the 6 classical moves
47+
- `f, b, r, l, u, d` for the 6 wide moves
48+
- `E, S, M` for the 3 slice moves
49+
- `x, y, z` for the 3 cube rotations
50+
51+
In each case, you can use `', 2, 3, ` to indicate the number of turns.
52+
53+
## Algorithms
54+
55+
For Burik, an algorithm is a string of moves separated by a space. For instance `"R U R' U R U2 R' U"` can be interpreted as an algorithm.
56+
57+
Algorithms come with tool functions that can be used to create new algorithms or for easier manipulation :
58+
59+
- `conc(A, B)` returns `C` such that `C = A + B`
60+
61+
- `invert(A)` returns `A'` such that `A + A' = " "`
62+
63+
- `enclose(A, B)` returns `C` such that `C = B + A + B'` (or `C + B = B + A`)
64+
65+
- `simplify(A)` returns `A'` such that `A = A'` and that `A'`̀ has no useless moves
66+
67+
## Colors
68+
69+
There are seven parametrizable colors in RGB hexadecimal code in `cubes.typ`
70+
71+
- white for stickers from the `U` face
72+
- yellow for stickers from the `D` face
73+
- red for stickers from the `R` face
74+
- orange for stickers from the `L` face
75+
- green for stickers from the `F` face
76+
- blue for stickers from the `B` face
77+
- black for every non-colorized stickers
78+
79+
## Cubes
80+
81+
Cubes are dictionnaries with 6 keys `u, d, f, b, r, l` for the six faces, and each value is an array of 9 colors.
82+
83+
There are 3 predefined cubes in `cubes.typ` and they all have white on top and green in front :
84+
85+
- `pll_cube` is a fully solved cube
86+
87+
- `oll_cube` has solved white face, two first layers and yellow face (black stickers on the last layer permutation)
88+
89+
- `f2l_cube` has solved white face and two first layers. The last layer and the yellow face is in black.
90+
91+
There is no assertion that the cubes that you may create from scrath using the same method are solvable, so you must be careful when doing so. I would recommend using the predefined cubes as much as possible.
92+
93+
## Drawing
94+
95+
There are 3 drawing functions :
96+
97+
- `draw_pattern` for drawing the 6 faces of the cube as the pattern of a cube (useful for debugging or scramble checking)
98+
99+
- `draw_last_layer` for drawing the last layer with reduced stickers for the side pieces (useful for OLL, PLL and every last layer algorithm)
100+
101+
- `draw_3d_cube` for drawing the cube in perpective with a view on faces `F, U, R` (useful for F2L)
102+
103+
And there also 3 illustrating functions :
104+
105+
- `pll` to illustrate PLL algorithms, by default this is in the last face point of view, with yellow face on top, green in front, and starting with the `pll_cube` as the target configuration. You can choose to display black arrows on the yellow face to illustrate ongoing permutations.
106+
107+
- `oll` to illustrate OLL algorithms, by default this is in the last face point of view, with yellow face on top, green in front, and starting with the `oll_cube` as the target configuration.
108+
109+
- `f2l` to illustrate F2L algorithms, by default this is in the 3D view, with yellow face on top, green in front, and starting with the `f2l_cube` as the target configuration.
110+
111+
## License
112+
113+
This project is licensed under the MIT License. You can find the full text in the `LICENSE` file included in this repository.
114+
115+
## Future Work
116+
117+
There are no current versions that include other cube shapes than 3x3 (like 2x2, 4x4, 5x5, ...) or other puzzle shapes (like megaminx, skewb, ...).
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#import "@preview/burik:0.1.0": *
2+
3+
= Burik — A Typst Library for easy Rubik's Cube tutorials edition
4+
#v(1em)
5+
*Burik* is a Typst library specifically designed to facilitate the creation of tutorials for *3x3 Rubik's Cube* solving.
6+
7+
Burik was first designed to make life easier for tutorial creators, as it allows algorithms manipulation in strings and algorithms visualization with parametrizable drawing functions from different point of view.
8+
9+
There is also an interest for the tutorial's user as there is no possible mismatch between the written algorithm and the displayed image.
10+
11+
== Installation
12+
13+
To use this package, clone this #link("https://github.com/Gcalmet/burik", "GitHub repository") or add this line at the beginning of your document in the webapp :
14+
15+
````typ
16+
#import "@preview/burik:0.1.0"
17+
````
18+
19+
== Use example
20+
21+
````typ
22+
#import "@preview/burik:0.1.0"
23+
#f2l("f R' f'")
24+
#oll("r U R' U R U2 r'")
25+
#pll("R' U R' U' R3 U' R' U R U R2")
26+
````
27+
28+
#f2l("f R' f'")
29+
#oll("r U R' U R U2 r'")
30+
#pll("R' U R' U' R3 U' R' U R U R2")
31+
32+
You can check the #link("example.typ", "example file") for more usage examples.
33+
34+
== How does it work ?
35+
36+
When you pass an algorithm to Burik, it inverts it and executes the inverted algorithm on a solved cube. As a result, it obtains a configuration in which executing the non-inverted algorithm is useful.
37+
38+
== Moves
39+
40+
Moves used to encode an algorithm on the Rubik's Cube are the standard ones (visit #link("https://jperm.net/3x3/moves", "J Perm website") for more details).
41+
42+
43+
// link to the website
44+
45+
- #raw("F, B, R, L, U, D") for the 6 classical moves
46+
- #raw("f, b, r, l, u, d ") for the 6 wide moves
47+
- #raw("E, S, M ") for the 3 slice moves
48+
- #raw("x, y, z") for the 3 cube rotations
49+
50+
In each case, you can use #raw(" ', 2, 3, ") to indicate the number of turns.
51+
52+
== Algorithms
53+
54+
For Burik, an algorithm is a string of moves separated by a space. For instance `"R U R' U R U2 R' U"` can be interpreted as an algorithm.
55+
56+
Algorithms come with tool functions that can be used to create new algorithms or for easier manipulation :
57+
58+
- `conc(A, B)` returns `C` such that `C = A + B`
59+
60+
- `invert(A)` returns `A'` such that `A + A' = " "`
61+
62+
- `enclose(A, B)` returns `C` such that `C = B + A + B'`
63+
64+
- `simplify(A)` returns `A'` such that `A = A'` and that `A'`̀ has no useless moves
65+
66+
== Colors
67+
68+
There are seven parametrizable colors in RGB hexadecimal code in `cubes.typ`
69+
70+
- #text(color.white, "white") for stickers from the `U` face
71+
- #text(color.yellow, "yellow") for stickers from the `D` face
72+
- #text(color.red, "red") for stickers from the `R` face
73+
- #text(color.orange, "orange") for stickers from the `L` face
74+
- #text(color.green, "green") for stickers from the `F` face
75+
- #text(color.blue, "blue") for stickers from the `B` face
76+
- #text(color.black, "black") for every non-colorized stickers
77+
78+
== Cubes
79+
80+
Cubes are dictionnaries with 6 keys ` u, d, f, b, r, l ` for the six faces, and each value is an array of 9 colors.
81+
82+
There are 3 predefined cubes in `cubes.typ` and they all have white on top and green in front :
83+
84+
- `pll-cube` is a fully solved cube
85+
86+
- `oll-cube` has solved white face, two first layers and yellow face (black stickers on the last layer permutation)
87+
88+
- `f2l-cube` has solved white face and two first layers. The last layer and the yellow face is in black.
89+
90+
There is no assertion that the cubes that you may create from scrath using the same method are solvable, so you must be careful when doing so. I would recommend using the predefined cubes as much as possible.
91+
92+
== Drawing
93+
94+
There are 3 drawing functions :
95+
96+
- `draw-pattern` for drawing the 6 faces of the cube as the pattern of a cube (useful for debugging or scramble checking)
97+
98+
- `draw-last-layer` for drawing the last layer with reduced stickers for the side pieces (useful for OLL, PLL and every last layer algorithm)
99+
100+
- `draw-3d-cube` for drawing the cube in perpective with a view on faces `F, U, R` (useful for F2L)
101+
102+
And there also 3 illustrating functions :
103+
104+
- `pll` to illustrate PLL algorithms, by default this is in the last face point of view, with yellow face on top, green in front, and starting with the `pll-cube` as the target configuration. You can choose to display black arrows on the yellow face to illustrate ongoing permutations.
105+
106+
- `oll` to illustrate OLL algorithms, by default this is in the last face point of view, with yellow face on top, green in front, and starting with the `oll-cube` as the target configuration.
107+
108+
- `f2l` to illustrate F2L algorithms, by default this is in the 3D view, with yellow face on top, green in front, and starting with the `f2l-cube` as the target configuration.
109+
110+
== License
111+
112+
This project is licensed under the MIT License. You can find the full text in the `LICENSE` file included in this repository.
113+
114+
== Future Work
115+
116+
There are no current versions that include other cube shapes than 3x3 (like 2x2, 4x4, 5x5, ...) or other puzzle shapes (like megaminx, skewb, ...).
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#import "cubes.typ" : *
2+
#import "moves.typ" : *
3+
4+
#let move-value = move => {
5+
if move.ends-with("'") {
6+
(move.slice(0, -1), -1)
7+
} else if move.ends-with("2") {
8+
(move.slice(0, -1), 2)
9+
} else {
10+
(move, 1)
11+
}
12+
}
13+
14+
#let value-to-move = (face, value) => {
15+
let v = calc.rem(value,4)
16+
if v == 0 {
17+
none
18+
} else if v == 1 {
19+
face
20+
} else if v == 2 {
21+
face + "2"
22+
} else {
23+
face + "'"
24+
}
25+
}
26+
27+
#let simplify = algo => {
28+
let moves = algo.split(" ")
29+
let changed = true
30+
31+
while changed {
32+
let i = 0
33+
let new-moves = ()
34+
changed = false
35+
36+
while i < moves.len() {
37+
if i < moves.len() - 1 {
38+
let a = moves.at(i)
39+
let b = moves.at(i + 1)
40+
let (face-a, val-a) = move-value(a)
41+
let (face-b, val-b) = move-value(b)
42+
43+
if face-a == face-b {
44+
let merged = value-to-move(face-a, val-a + val-b)
45+
if merged != none {
46+
new-moves.push(merged)
47+
}
48+
i += 2
49+
changed = true
50+
continue
51+
}
52+
}
53+
new-moves.push(moves.at(i))
54+
i += 1
55+
}
56+
57+
moves = new-moves
58+
}
59+
moves.join(" ")
60+
}
61+
62+
#let apply-sequence = (cube, sequence) => sequence.fold(cube, apply-move)
63+
64+
#let invert-move = move => {
65+
if move.ends-with("'") {
66+
move.slice(0,-1)
67+
} else if move.ends-with("2") {
68+
move
69+
} else if move.ends-with("3") {
70+
move.slice(0,-1)
71+
} else {
72+
move + "'"
73+
}
74+
}
75+
76+
#let invert-algo = algo-array => {
77+
algo-array.rev().map(invert-move)
78+
}
79+
80+
#let invert = str => str.split(" ").rev().map(invert-move).join(" ")
81+
82+
#let conc = (algo1, algo2) => {
83+
simplify(algo1 + " " + algo2)
84+
}
85+
86+
#let enclose = (algo, prefix) => {
87+
conc(prefix, conc(algo, invert(prefix)))
88+
}
89+
90+
#let find-permutation(cube)={
91+
let permut = ()
92+
93+
let edges = ("U" : cube.u.at(7), "L" : cube.l.at(5), "R" : cube.r.at(3), "D" : cube.d.at(1))
94+
95+
let corners = ("LU" : cube.l.at(2), "RU" : cube.u.at(8), "RD" : cube.r.at(6) , "LD" : cube.d.at(0))
96+
97+
let centers = ("U" : cube.u.at(4), "L" : cube.l.at(4), "R" : cube.r.at(4), "D" : cube.d.at(4), "LU" : cube.l.at(4), "RU" : cube.u.at(4), "RD" : cube.r.at(4), "LD":cube.d.at(4))
98+
99+
for (edge1, color1) in edges.pairs() {
100+
for (edge2, color2) in edges.pairs() {
101+
if color1 == centers.at(edge2) and edge1 != edge2{
102+
permut.push((edge1, edge2))
103+
}
104+
}
105+
}
106+
107+
for (corner1, color1) in corners.pairs() {
108+
for (corner2, color2) in corners.pairs() {
109+
if color1 == centers.at(corner2) and corner1 != corner2{
110+
permut.push((corner1, corner2))
111+
}
112+
}
113+
}
114+
115+
permut
116+
}

0 commit comments

Comments
 (0)