Consider adding a `push back` operation to `Alg`
Steps to reproduce the issue
Let's define the following transform for some sequence of moves M0, M1, M2, M3, R, where M# is an arbitrary move and R is usually a rotation but could be an arbitrary move. Then let's define an arbitrary operator called "push back" that does the following thing:
M0 M1 M2 M3 ⬷ R ≡ R M0' M1' M2' M3'
if it is possible to compute M0', M1', ..., Mn' such that the cube state generated by the sequence M0 M1 M2 M3 R is identical to the cube state generated by R M0' M1' M2' M3'.
Observed behaviour
I couldn't find such an operator in cubing.js
Expected behaviour
It'd be great to have an operation like this for the purpose of rewriting algs from different angles, or for the purpose of creating a canonical form of any given algorithm. For example, R L and L R are equivalent, but this can be hard to determine; but if one decided that R turns should always appear first, the new operator could be used to turn all such instances into R L.
That isn't, however, the use case I actually have. The use case I actually have is that the user has completed a roux solve on a bluetooth cube with no gyro. When I break down their solve, I can see what they did for first block, and conclude how they must be holding the cube; then I can rewrite the solution from that angle to give them a better reconstruction. Even when the code gets some other thing wrong the resulting reconstruction is usually better than viewing it from a WG orientation, for example here where the l move messes it up, it is still reasonably watchable.
L B R2 F2 L' F' D' L2' U' L B2' U2 R2 L2' U' F2 D' D2 L2' D L2' U' // Scramble
x2 y' R D' M2 U L2 U2 D2 R2 M' B // First block
D2 R D' L2 l' L U L' B R B R // Square
L U L' B' L U L' // Last pair
B' R B R' U' R B R' B' R' U R2 B' R' // CMLL
M' B M B M' M2 B' M B2 M B' M2 B M2 B2 // LSE
This effect is achieved by taking x2 y' and using the push back operator on the solution to rewrite it from the new angle.
Environment
All platforms.
🖼 Screenshots
No response
Additional info
No response
Here are the (very few) test cases I used to validate my implementation:
L ⬷ R ≡ R L
D L ⬷ R ≡ D R L
D L ⬷ x ≡ x F L
U L F R D B ⬷ y y y y ≡ y y y y U L F R D B
This also turns out to be great for rewriting algs to favour certain moves. For example, in Roux once the left block is solved it should not be moved, and we can fairly safely rewrite any L, L', l, or l' move as r, r', R, or R', using the new operator to rewrite the rest of the solution with an x or x' rotation applied and discarded. The end result is a solve reconstruction that is quite close to what the user actually did.