Twizzle is a program for exploring some twisty puzzles. Fundamentally, it creates and manipulates a permutation representation of a specific subset of twisty puzzles; from this, it provides a simulator of these puzzles, integration with ksolve, twsearch, and GAP, as well as basic algorithms such as Schreier-Sims.

The puzzles it supports are those that can be created by starting with one of the five Platonic solids and creating flat cut planes that are aligned with vertices, faces, or corners of those solids in a fully symmetric way. It does not support bandaging or jumbling at all. This is sufficient to describe puzzles such as the nxnxn Rubik's cubes, pyraminx, megaminx, skewb, pentultimate, starminx I and II, and many more.

It is not intended (yet) to be a fully general permutation puzzle simulator, like pCubes or gelatinbrain; instead, by focusing on this simple set of puzzles I hope to quickly build general optimal solvers, multiple-phase solvers, and other tools.

Twizzle is written in TypeScript, a variant of JavaScript, and thus runs either in the browser or from the command line.

These are the basic components of the system:


PuzzleGeometry takes care of generating all relevant and necessary puzzle descriptions from a simple geometric description. This description is composed a single character representing one of the Platonic solids:

followed by a space and then followed by as many sets of cutting planes as desired. Each cutting plane is described by a geometric feature that it is aligned with:

followed by a distance from the origin (center of the puzzle) for that cutting plane. Here are some sample descriptions:

Geometry Common name
c f 0.333 3x3x3 Rubik's cube
c f 0 2x2x2 Rubik's cube
c f 0 f 0.5 4x4x4 Rubik's cube
c f .8 f .6 f .4 f .2 f 0 10x10x10 Rubik's cube
c v 0 Skewb
d f 0 Pentultimate
d f 0.7 Megaminx
o f 0.333333333333 FTO
d f 0.447213595499989 Pyraminx crystal

For some of these puzzles the large number of digits is required to prevent the formation of spurious infinitesimal faces. PuzzleGeometry automatically considers any points within 1e-9 of each other to be coincident. Puzzles can combine vertex, face, and edge moves arbitrarily.

PuzzleGeometry includes a default 2D net unfolding for each of the five Platonic solids, a default face naming scheme, a default color scheme, a default face precedence order, and a default 3D rendering. The face names must be prefix-free (that is, no face name can be the prefix of another face name). Edges are named (non-uniquely) as the concatenation of two face names, and vertices are named (non-uniquely) as the concatenation of three to five face names, depending on how many planes come together at the vertex. The faces in a vertex name can start with any face, but they must proceed clockwise around the vertex (so on the cube, URF is fine, but UFR is not.)

Since all the cutting planes are aligned with faces, edges, or vertices, the grips (axis of rotations for moves) are also associated with these; this is the basis of the move notation. Thus, on the 3x3x3 cube, U is a minimal clockwise rotation of the up face; on the helicopter cube, UF is a minimal clockwise rotation of the edge joining the up and front faces. Jumbling is not supported so this minimal rotation is a 180 degree rotation on edges. On the skewb, moves are URF and so on.

Moves on the puzzle correspond to rotations of contiguous slices of the puzzle; each slice is a set of cubies between two adjacent cutting planes that share the same axis of rotation. Move notation is generally given by defining grips, which name the axes (typically with two opposing grips). The slices are then numbered from 1 on the outside to however many slices there are on that axis.

Alg Move Notation

Sequences of moves are parsed by the alg algorithm parser, and support SiGN notation. In SiGN notation a move is described by three components: the prefix, family, and amount, of which only the family is mandatory. The prefix tells which slices to turn, the family describes the grip, and the amount describes how to rotate. The family is the name of a grip; if it is given in upper case, it is (by default) a slice move; if it is given in lower case, it is a block move. If the family ends in v, then it is a puzzle rotation (very wide move).

If the prefix is omitted then it defaults to the first slice for a slice move, or the first two slices for a block move. If the prefix is a single integer, it says what single slice to turn for a slice move, or how many consecutive outer slices to turn for a block move. If the prefix is a range, it gives the range of slices to turn.

If the amount is omitted, it describes a minimal (doctrinaire) clockwise rotation. If the amount is given as a number, it describes a multiple of that minimal move. If the amount is a prime character, it describes a minimal (doctrinaire) counter-clockwise rotation. If the amount is a prime character followed by a number, it describes a counter-clockwise minimal move repeated that number times.

On the helicopter cube, for any grip, there are a total of three slices, and the order of rotation is 2 (if we only consider doctrinaire moves) so FU == 1FU == 3DB' == 3DB and 2FU == 2DB' == 2DB (in this case).

The alg parser also supports sequences of moves, grouping with parentheses, conjugating by enclosing in brackets with the two components separated by a comma, commutation by enclosing in brackets with the two components separated by a colon, and negation and repetition by appending a number and/or a prime character to any group, commutator, or conjugation. Thus, the following are legal sequences on the 3x3x3:

R U R' U R U2 R'
[R' D R F D F', U2]
(U F R)'3

Spaces are required between moves to disambiguate them.

Twisty Algorithm Display

The basic UI for twizzle is provided by twisty, which combines a three-dimensional representation with a ksolve-style puzzle representation to provide puzzle and algorithm display and playback. Puzzlegeometry generates the three-dimensional representation and the ksolve or kpuzzle description, and Twizzle provides a simple UI on top of this for its extended features. Note that unlike twizzle, twisty is not constrained to only support the very specific set of puzzles generated by puzzlegeometry.

Twizzle User Interface

The twizzle UI provides access to a puzzlegeometry's features. The basic UI provides a control line with puzzle selection, a scramble button, a reset button, a button to enable extended options, a dropdown list with additional actions, a dropdown list to select keyboard or bluetooth input, and a help button. Below this group of controls is a puzzle display with a scrubber and VCR controls, and a large textarea for algorithm input.

Selecting the options button enables a number of additional controls. First is a puzzle geometry description which can be edited to create new puzzles or modify existing ones. Next is a set of checkboxes that affect the behavior of the UI and/or the actions buttons. The first four checkboxes affect the UI; the ones after that only affect the output of the action dropdowns. The first three checkboxes allow you to turn on and off edges, corners, and centers on the puzzle (although it does not permit you to independently enable or disable specific subtypes of edges or centers). The block moves option indicates preference for outer block moves over slice moves. The optimize checkbox attempts to simplify the permutation representation of the puzzle when generating ksolve or GAP output, which may make some operations in those programs much faster. The all moves option generates moves of all slices, including (for instance) slice moves on the 3x3x3; normally the center slice moves of puzzles with an odd number of layers are omitted. The no ori option omits orientation information. The vertex move option is for tetrahedron and indicates outer face moves should be avoided. The 3D option affects the type of SVG generated in the actions dropdown. The last two checkboxes affect 3D rendering; the side-by-side checkbox switches between showing the back at full size to the right, or showing the back smaller and in the upper right corner. The show foundation checkbox renders the back of stickers in black.

The actions in the action dropdown are as follows. The ksolve option generates a ksolve representation and opens a window with this text. The get scramble option will generate a scramble representation (once this works). The Schreier-Sims option runs that algorithm to calculate the state space of the puzzle; for large puzzles this may take a very long time. The canon sequence option runs a canonical sequence analysis; this does not (yet) take into account rotation reductions. The GAP option generates a permutation representation suitable for use in GAP. The SVG option generates an SVG image of the puzzle (but only in the solved state).

On the right side of the main display is the large algorithm textbox that can be edited normally. Moves you enter with the mouse will be automatically appended to this box, and possibly merged with the previous move if possible (but only in a very simple way). If there is a syntax error in the algorithm box the box will be red and the puzzle will be reset to solved, but editing will still work.

On the left side of the main display is the interactive display of the puzzle itself. If you hover on a particular face, the face name will be displayed. If you click near a grip, a counter-clockwise (left) move will be executed on the outermost layer of that grip; if you right-click, a clockwise move will be executed. The shift key when applied to a move will rotate either the second slice (with block moves unselected) or both the outer and the second slice (with block moves selected). Holding down the control key will do a full puzzle rotation around that grip (and this will show up as a move).

It is not presently possible to do (for instance) a x, y, or z single rotation on a skewb.

Below the puzzle representation are a set of control widgets. The horizontal bar has a scrubber knob that you can use to advance the algorithm to any particular point. Below this is a widget to turn on and off full-screen display (although doing a move with full-screen on currently kills full-screen), rewind, go back a move, animate or stop the animation, go forward a move, and go to the end. Any move made on the puzzle with the mouse automatically resets the puzzle display to the end (the only way to insert a move other than at the end or to do any other sort of editing is textually in the text input box).

PuzzleGeometry Command Line

Puzzlegeometry can also be used from the command line. Usage is as follows:

node dist/bin/puzzle-geometry-bin.js [options] [puzzle]

where puzzle is either the name of the one of the predefined puzzles (see the dropdown in twizzle) or a puzzle geometry description such as c f 0.3333. The options are as follows:

-q, --quiet:  be less verbose
-v, --verbose:  be more verbose
--ksolve:  generate ksolve output
--gap:  generate gap output
--svg:  generate svg output
--ss:  execute the Schreier-Sims algorithm
--canon:  do the canonical analysis
--optimize:  optimize the representation
--allmoves:  include moves for all slices
--outerblockmoves:  prefer outer block moves to slice moves
--vertexmoves:  prefer vertex moves to face moves on tetrahedron
--nocorners:  disable corners
--noedges:  disable edges
--nocenters:  disable centers
--moves movelist:  only include moves listed; moves separated by commas

The GAP output consists of a set of move definitions (all starting with M_) followed by a definition of Gen that is a list of all moves, and a variable ip which contains a set of tuples of identical pieces. To calculate the size of the supergroup (that is, not taking into account full-puzzle rotations or identical pieces), use the GAP command Size(Group(Gen));. To calculate how much this is reduced by identical pieces, use the GAP command Size(Stabilizer(Group(Gen), ip, OnTuplesSets));.

Twizzle is being developed by Tomas Rokicki and Lucas Garron. You can follow our progress at