by Marek14 » Fri Feb 12, 2021 11:27 am
And here's my writeup:
Dualization algorithm:
!!!Step 0: The output
0 | 0 | 0' 1' 2' 2' 1' 0' 6' 7' 8' 7' 6' | 0'' |
Tiling data info:
Number of edges: 14
Desired vertex weight: 60
Right neighbors: [0,1,3,4,5,6,7,8,9,10,11,12,2,13]
Left neighbors: [0,1,12,2,3,4,5,6,7,8,9,10,11,13]
Left vertex weights: [5,5,12,5,5,5,5,5,12,12,12,12,12,12]
Mirrors: [1,0,7,6,5,4,3,2,12,11,10,9,8,13]
Edge types: [70,70,77,70,70,70,70,161,168,168,168,168,168,168]
Match types: [70,70,161,70,70,70,70,77,168,168,168,168,168,168]
Cone points allowed: true
Connectivity required: true
Canonical solutions: 1
(0 1')[0'][2'](6' 7')(8' 0'')
[0,1,2,3,4,5,6,7,8,9,10,11,12,13]: (id)
0 1 2 3 4 5 6 | 0 1 2 3 4 5 6 | 0' 1' 2' 3' 4' 5' 6' | 0' 1' 2' 3' 4' 5' 6' |
Tiling data info:
Number of edges: 28
Desired vertex weight: 84
Right neighbors: [1,2,3,4,5,6,0,13,7,8,9,10,11,12,15,16,17,18,19,20,14,27,21,22,23,24,25,26]
Left neighbors: [6,0,1,2,3,4,5,8,9,10,11,12,13,7,20,14,15,16,17,18,19,22,23,24,25,26,27,21]
Left vertex weights: [21,12,21,21,28,12,28,12,21,21,28,12,28,21,21,12,21,21,21,21,28,12,21,21,21,21,28,21]
Mirrors: [7,8,9,10,11,12,13,0,1,2,3,4,5,6,21,22,23,24,25,26,27,14,15,16,17,18,19,20]
Edge types: [369,621,630,833,376,824,637,621,369,630,637,824,376,833,369,621,630,630,630,833,637,621,369,630,630,630,637,833]
Match types: [621,369,630,637,824,376,833,369,621,630,833,376,824,637,621,369,630,630,630,637,833,369,621,630,630,630,833,637]
Cone points allowed: true
Connectivity required: true
Canonical solutions: 4
(0 1)(2 3')(3 6')(4 5)(6 5')(0' 1')(2')(4')
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]: (id)
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')(3')(4')
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]: (id)
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')[3' 4']
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]: (id)
(0 1)[2 3'](3 6')(4 5)(6 5')(0' 1')[2' 4']
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]: (id)
This is what the output from the solver looks like these days. I'm using two examples. First is a hybrid between tilings {12,10} and {5,12}, with a (5,5,5,5,5,5,12,12,12,12,12) vertex as an in-between. The second is a set of 4 solutions that combine vertices of type (3,4,4,7,4,3,7) and (3,4,4,4,4,7,4), both belonging to what I call "the {4,7} class", based on replacing two squares in {4,7} vertex with a combination of a triangle and a heptagon.
!!!Step 1: Creating a skelet of vertex symbols.
The most basic unit we're working with is the half-edge. That's just what it says: a half of an edge with one vertex attached. The half-edge is described using three pieces of data: the edge index, the vertex index, and the mirror symbol.
The tiling has a number of distinct vertex class. The vertex index is vertex class of vertex that is on the half-edge in question. Each vertex class has a number of halfedges that come out of the vertex; edge index is the number of the half-edge on the vertex.
Let's look at the first row of the solution for the {4,7} class:
0 1 2 3 4 5 6 | 0 1 2 3 4 5 6 | 0' 1' 2' 3' 4' 5' 6' | 0' 1' 2' 3' 4' 5' 6' |
This row describes the vertices. There are edge indexes from 0 to 6 on two vertices: 0 (no symbol) and 1 (marked by prime (')).
But why is each of these doubled? That is because these vertices are chiral, i.e. there are no axes of symmetry that would pass through them. So the first set of numbers 0-6 describes one chirality of vertex 0, and the second describes the other chirality. The row of numbers printed in the solution is there so I could understand at a glance the symmetries of vertices in the tiling.
To build the "vertex skelet", I start by putting each symbol on its own row.
0
1
2
3
4
5
6
*0
*1
*2
*3
*4
*5
*6
0'
1'
2'
3'
4'
5'
6'
*0'
*1'
*2'
*3'
*4'
*5'
*6'
I've also added the mirror symbols here. A mirror symbol's function is just to distinguish between enantiomers of the same half-edge. Half-edge 0 is the mirror image of the half-edge *0.
Now let's do the same to the {12,10} class solution:
0 | 0 | 0' 1' 2' 2' 1' 0' 6' 7' 8' 7' 6' | 0'' |
0
*0
0'
1'
2'
*2'
*1'
*0'
6'
7'
8'
*7'
*6'
0''
There are couple more concepts to explain here. First, there are three vertex classes, and class 2 is marked by two primes (''). If we have even more, we *could* probably start to just add more and more primes, but that would quickly get unwieldy. So I've actually made two notations for marking the half-edges. A half-edge 1 of class 3 can be marked as either 1''' or 1@3.
The standard use is that the @ notation is used from class 4 onwards. It's much better for bigger class numbers, but small number of primes seems simpler to me for smaller classes. Especially class 0 where there is no symbol.
Second, the vertices of this tiling are of orders, respectively, 10, 11, and 12. But, as you might have noticed, only vertex class 1 actually has 11 distinct symbols. This is because the other two vertices possess rotational symmetry.
Rotational symmetry means that the actual size of the vertex is reduced to one of its factors. In this case, both the vertex 0 of degree 10 and vertex 2 of degree 12 are reduced to degree 1, signifying that all half-edges from these vertices are identical. It's not just those vertices that have rotational symmetry: any symmetry of vertex that is recorded here is automatically a symmetry of the whole tiling.
Third, you will notice that only one vertex class (0) is chiral. The other two are represented by only one group of numbers each, meaning that they have reflection symmetry.
Let's look at class 1 first. Instead of the numbers going from 0 to 10, they are grouped around mirrors. You can see that there is one mirror in this vertex passing between half-edges 2' and 3' (or 2'and *2'), and the other passes *through* the half-edge 8'. Each half-edge has the same index it would normally have, *except* if it's a mirror image of a half-edge somewhere before it, in which case it's marked as the mirror of that half-edge.
Finally, half-edges 8' and 0'' only appear once in the whole thing. These half-edges have mirrors passing through them, so they are their own mirror images. That means we should assign them a third type of mirror symbol:
Mirror symbol 0 <-> Mirror symbol 1(*)
Mirror symbol 2 (self-corresponding)
Only mirror symbol 1 is actually printed, but internally, all 3 should be used because we need a way to transform a half-edge into its mirror image -- and this is done by changing 0 to 1, 1 to 0, or leaving 2 unchanged.
So now we know the symmetries of the three vertex classes of the {12,10} solution: class 0 vertices have rotational symmetry of order 10 (but no reflection symmetry, meaning that they still occur in two chiral versions), class 1 vertices have reflection symmetry and class 2 vertices have full dodecagonal symmetry -- 12 axes of symmetry coupled with rotational symmetry of order 12. Note that in this notation, a vertex can be only displayed with *one* axis of reflection. If it has two or more, then it automatically has rotational symmetry as well and it will be reduced in size to its factor.
Now that we have listed the half-edges, we will expand them into *vertex symbols*:
0/0(12)-
*0/*0(12)-
0'/1'(12)-
1'/2'(12)-
2'/*2'(12)-
*2'/*1'(12)-
*1'/*0'(12)-
*0'/6'(5)-
6'/7'(5)-
7'/8'(5)-
8'/*7'(5)-
*7'/*6'(5)-
*6'/0'(5)-
0''/0''(5)-
and
(3,4,4,7,4,3,7) and (3,4,4,4,4,7,4)
0/1(7)-
1/2(4)-
2/3(4)-
3/4(3)-
4/5(7)-
5/6(3)-
6/0(4)-
*0/*6(4)-
*1/*0(7)-
*2/*1(4)-
*3/*2(4)-
*4/*3(3)-
*5/*4(7)-
*6/*5(3)-
0'/1'(7)-
1'/2'(4)-
2'/3'(4)-
3'/4'(4)-
4'/5'(4)-
5'/6'(3)-
6'/0'(4)-
*0'/*6'(4)-
*1'/*0'(7)-
*2'/*1'(4)-
*3'/*2'(4)-
*4'/*3'(4)-
*5'/*4'(4)-
*6'/*5'(3)-
For vertices with reflection symmetry, we simply append the next half-edge in sequence (cyclically, so the final half-edge is appended with the first one). For chiral vertices, two cycles will be created, with the second one (made from mirror symbol 1, i.e. starred, half-edges) appends the *previous* half-edge. That way, we get, say, vertex symbol 4/5 and its mirror image *5/*4.
Now, what's the number in parentheses? That's the polygon marker. I use them because when I do this by hand, these markers tell me when I've made some sort of a mistake. These symbols, you see, are concatenated to form the regular polygonal tiles of the tiling, and if it's done correctly, the polygon marker on all symbols from the same tile will be the same.
How do we obtain that? Well, look at these two lines in the solution:
0 | 0 | 0' 1' 2' 2' 1' 0' 6' 7' 8' 7' 6' | 0'' |
Tiling data info:
Number of edges: 14
***Desired vertex weight: 60
Right neighbors: [0,1,3,4,5,6,7,8,9,10,11,12,2,13]
Left neighbors: [0,1,12,2,3,4,5,6,7,8,9,10,11,13]
***Left vertex weights: [5,5,12,5,5,5,5,5,12,12,12,12,12,12]
Mirrors: [1,0,7,6,5,4,3,2,12,11,10,9,8,13]
Edge types: [70,70,77,70,70,70,70,161,168,168,168,168,168,168]
Match types: [70,70,161,70,70,70,70,77,168,168,168,168,168,168]
Cone points allowed: true
Connectivity required: true
Canonical solutions: 1
(0 1')[0'][2'](6' 7')(8' 0'')
[0,1,2,3,4,5,6,7,8,9,10,11,12,13]: (id)
The "Left vertex weights" line assigns each half-edge a number. 0 is assigned 5, *0 is also assigned 5, 0' is assigned 12, etc. These describe angles between this half-edge and its predecessor. "Desired vertex weight" is simply how many angle units form the full angle. This allows us to use integers as angle measures regardless of what type of tiling we work with.
So the correct polygon marker to attach to a particular vertex symbol edge is found as follows:
1) Find the *second* half-edge in the symbol and its global index.
2) Find the Left vertex weights value for this global index.
3) Divide Desired vertex weight by this number and you have your polygon marker.
Note that if we simply create some sort of correspondence between global index of the half-edge and its string representation, the "Right neighbors" row can be used to directly create vertex symbols because it directly tells you the second half-edge in the symbol.
!!!Step 2: Assemble the vertex symbols into polygons.
In the previous step, we only worked with the first part of solution. That is just the description of the problem. Now we need to actually use the solutions that were found by the program.
Let's look at the {12,5} class solution:
Canonical solutions: 1
(0 1')[0'][2'](6' 7')(8' 0'')
[0,1,2,3,4,5,6,7,8,9,10,11,12,13]: (id)
And the {4,7} class solutions:
Canonical solutions: 4
(0 1)(2 3')(3 6')(4 5)(6 5')(0' 1')(2')(4')
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]: (id)
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')(3')(4')
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]: (id)
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')[3' 4']
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]: (id)
(0 1)[2 3'](3 6')(4 5)(6 5')(0' 1')[2' 4']
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]: (id)
"Canonical solutions" row simply tells you how many solutions were found. "Canonical" is there because if the vertex has any sort of symmetry, you can get multiple solutions that have the same structure and can be transformed one into another by some sort of symmetry operation on the half-edges. Canonical solutions weeds that out: each canonical solution is guaranteed to be unique.
Next, you have each solution, composed of the solution string (based on Conway's notation), followed by enumerated symmetries of that solution.
OK, why are the symmetries there? They are, basically, a reality check. A proper solution should have *no* symmetries apart from the identity. If there are more than that, it means that the solution can be simplified, either by replacing some vertices with more symmetrical versions or by combining multiple identical vertices into a single class. So any solution with more than one row of symmetries can be safely ignored unless you specifically search for such things (for example when exploring various colorings, etc.).
Now, an unfortunate fact. Presence of multiple symmetry rows is sufficient condition for the solution to be a copy of a simpler solution, but *not* the necessary condition. I don't know what the actual necessary condition is. In other words, it's still possible to get solutions that are copies, even if you weed out the symmetrical ones; they won't be eliminated completely.
But these particular solutions are the simplest in their group, so they have no symmetries. So we associate each Conway (solution) string with the vertex skelet we've built in Step 1:
(0 1')[0'][2'](6' 7')(8' 0'')
0/0(12)-
*0/*0(12)-
0'/1'(12)-
1'/2'(12)-
2'/*2'(12)-
*2'/*1'(12)-
*1'/*0'(12)-
*0'/6'(5)-
6'/7'(5)-
7'/8'(5)-
8'/*7'(5)-
*7'/*6'(5)-
*6'/0'(5)-
0''/0''(5)-
(0 1)(2 3')(3 6')(4 5)(6 5')(0' 1')(2')(4')
0/1(7)-
1/2(4)-
2/3(4)-
3/4(3)-
4/5(7)-
5/6(3)-
6/0(4)-
*0/*6(4)-
*1/*0(7)-
*2/*1(4)-
*3/*2(4)-
*4/*3(3)-
*5/*4(7)-
*6/*5(3)-
0'/1'(7)-
1'/2'(4)-
2'/3'(4)-
3'/4'(4)-
4'/5'(4)-
5'/6'(3)-
6'/0'(4)-
*0'/*6'(4)-
*1'/*0'(7)-
*2'/*1'(4)-
*3'/*2'(4)-
*4'/*3'(4)-
*5'/*4'(4)-
*6'/*5'(3)-
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')(3')(4')
0/1(7)-
1/2(4)-
2/3(4)-
3/4(3)-
4/5(7)-
5/6(3)-
6/0(4)-
*0/*6(4)-
*1/*0(7)-
*2/*1(4)-
*3/*2(4)-
*4/*3(3)-
*5/*4(7)-
*6/*5(3)-
0'/1'(7)-
1'/2'(4)-
2'/3'(4)-
3'/4'(4)-
4'/5'(4)-
5'/6'(3)-
6'/0'(4)-
*0'/*6'(4)-
*1'/*0'(7)-
*2'/*1'(4)-
*3'/*2'(4)-
*4'/*3'(4)-
*5'/*4'(4)-
*6'/*5'(3)-
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')[3' 4']
0/1(7)-
1/2(4)-
2/3(4)-
3/4(3)-
4/5(7)-
5/6(3)-
6/0(4)-
*0/*6(4)-
*1/*0(7)-
*2/*1(4)-
*3/*2(4)-
*4/*3(3)-
*5/*4(7)-
*6/*5(3)-
0'/1'(7)-
1'/2'(4)-
2'/3'(4)-
3'/4'(4)-
4'/5'(4)-
5'/6'(3)-
6'/0'(4)-
*0'/*6'(4)-
*1'/*0'(7)-
*2'/*1'(4)-
*3'/*2'(4)-
*4'/*3'(4)-
*5'/*4'(4)-
*6'/*5'(3)-
(0 1)[2 3'](3 6')(4 5)(6 5')(0' 1')[2' 4']
0/1(7)-
1/2(4)-
2/3(4)-
3/4(3)-
4/5(7)-
5/6(3)-
6/0(4)-
*0/*6(4)-
*1/*0(7)-
*2/*1(4)-
*3/*2(4)-
*4/*3(3)-
*5/*4(7)-
*6/*5(3)-
0'/1'(7)-
1'/2'(4)-
2'/3'(4)-
3'/4'(4)-
4'/5'(4)-
5'/6'(3)-
6'/0'(4)-
*0'/*6'(4)-
*1'/*0'(7)-
*2'/*1'(4)-
*3'/*2'(4)-
*4'/*3'(4)-
*5'/*4'(4)-
*6'/*5'(3)-
Next, we will weave the polygons according to the solutions. Let's illustrate on the simplest one:
(0 1')[0'][2'](6' 7')(8' 0'')
0/0(12)-
*0/*0(12)-
0'/1'(12)-
1'/2'(12)-
2'/*2'(12)-
*2'/*1'(12)-
*1'/*0'(12)-
*0'/6'(5)-
6'/7'(5)-
7'/8'(5)-
8'/*7'(5)-
*7'/*6'(5)-
*6'/0'(5)-
0''/0''(5)-
Start with the first vertex symbol, "0/0(12)-". The second half-edge is 0. The Conway string contains this half-edge in (0 1'). That means that we need to search for the vertex symbol that starts with 1' and append it:
(0 1')[0'][2'](6' 7')(8' 0'')
0/0(12)-1'/2'(12)-
*0/*0(12)-
0'/1'(12)-
2'/*2'(12)-
*2'/*1'(12)-
*1'/*0'(12)-
*0'/6'(5)-
6'/7'(5)-
7'/8'(5)-
8'/*7'(5)-
*7'/*6'(5)-
*6'/0'(5)-
0''/0''(5)-
Now, what comes after 2'? The solution says "[2']", which means that 2' should be followed by 2', but mirrored (brackets indicate mirroring):
(0 1')[0'][2'](6' 7')(8' 0'')
0/0(12)-1'/2'(12)-*2'/*1'(12)-
*0/*0(12)-
0'/1'(12)-
2'/*2'(12)-
*1'/*0'(12)-
*0'/6'(5)-
6'/7'(5)-
7'/8'(5)-
8'/*7'(5)-
*7'/*6'(5)-
*6'/0'(5)-
0''/0''(5)-
Now the last symbol is *1'. 1' is present in (0 1'). Parentheses indicate no mirroring, meaning that *1' is followed by *0:
(0 1')[0'][2'](6' 7')(8' 0'')
0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-
0'/1'(12)-
2'/*2'(12)-
*1'/*0'(12)-
*0'/6'(5)-
6'/7'(5)-
7'/8'(5)-
8'/*7'(5)-
*7'/*6'(5)-
*6'/0'(5)-
0''/0''(5)-
*0 is followed by *1' by rule (0 1') again...
(0 1')[0'][2'](6' 7')(8' 0'')
0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-
0'/1'(12)-
2'/*2'(12)-
*0'/6'(5)-
6'/7'(5)-
7'/8'(5)-
8'/*7'(5)-
*7'/*6'(5)-
*6'/0'(5)-
0''/0''(5)-
*0' is followed by 0' by rule [0']:
(0 1')[0'][2'](6' 7')(8' 0'')
0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-0'/1'(12)-
2'/*2'(12)-
*0'/6'(5)-
6'/7'(5)-
7'/8'(5)-
8'/*7'(5)-
*7'/*6'(5)-
*6'/0'(5)-
0''/0''(5)-
And 1' is, by rule (0 1'), followed by 0. But 0 is the start of this whole row, which means we have completed the polygon.
By polygon marker (12) -- and notice that all vertex symbols have the same symbol -- this should be a dodecagon. however, the sequence closed after only 6 steps. That is not a problem. It simply means that the complete dodecagon will repeat the sequence twice. It has, thus, *multiplicity* of 2. This will be important later.
*** The number of vertex symbols in polygon sequence must be equal to either the polygon marker or to one of its factors, and all polygon markers in the sequence must be the same. ***
This is basically the only condition for the solution to be valid. This is what the program searches for.
(Technically, I ensure this with the "Edge types" and "Match types" rows in the solution header because this is simply one special case of much broader capability of the program.)
Now that we have a polygon, we can quickly assemble the others:
(0 1')[0'][2'](6' 7')(8' 0'')
0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-0'/1'(12)-
2'/*2'(12)-
*0'/6'(5)-7'/8'(5)-0''/0''(5)-8'/*7'(5)-*6'/0'(5)-
6'/7'(5)-
*7'/*6'(5)-
The space at the beginning of the line is just a visual indicator that this is a complete polygon. As we can see, we have 5 tiles altogether: two dodecagons (with multiplicities 2 and 12) and three pentagons (with multiplicities 1, 5, and 5).
So, once again: Each part of the Conway string, enclosed in parentheses or brackets, represents a rule how to combine the half-edges.
(x) means: x is followed by x, *x is followed by *x
(x y) means: x is followed by y, y is followed by x, *x is followed by *y, *y is followed by *x
[x] means: x is followed by *x, *x is followed by x
[x y] means: x is followed by *y, y is followed by *x, *x is followed by y, *y is followed by x
Self-mirrored half-edges will only ever appear in (x) and (x y) symbols and they can only combine with themselves or with other self-mirrored half-edges.
Let's assemble the {4,7} solutions as well:
(0 1)(2 3')(3 6')(4 5)(6 5')(0' 1')(2')(4')
0/1(7)-
1/2(4)-3'/4'(4)-4'/5'(4)-6/0(4)-
2/3(4)-6'/0'(4)-1'/2'(4)-2'/3'(4)-
3/4(3)-5/6(3)-5'/6'(3)-
4/5(7)-
*0/*6(4)-*5'/*4'(4)-*4'/*3'(4)-*2/*1(4)-
*1/*0(7)-
*3/*2(4)-*3'/*2'(4)-*2'/*1'(4)-*0'/*6'(4)-
*4/*3(3)-*6'/*5'(3)-*6/*5(3)-
*5/*4(7)-
0'/1'(7)-
*1'/*0'(7)-
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')(3')(4')
0/1(7)-
1/2(4)-*2'/*1'(4)-*0'/*6'(4)-6/0(4)-
2/3(4)-*5'/*4'(4)-*4'/*3'(4)-*3'/*2'(4)-
3/4(3)-5/6(3)-*6'/*5'(3)-
4/5(7)-
*0/*6(4)-6'/0'(4)-1'/2'(4)-*2/*1(4)-
*1/*0(7)-
*3/*2(4)-2'/3'(4)-3'/4'(4)-4'/5'(4)-
*4/*3(3)-5'/6'(3)-*6/*5(3)-
*5/*4(7)-
0'/1'(7)-
*1'/*0'(7)-
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')[3' 4']
0/1(7)-
1/2(4)-*2'/*1'(4)-*0'/*6'(4)-6/0(4)-
2/3(4)-*5'/*4'(4)-3'/4'(4)-*3'/*2'(4)-
3/4(3)-5/6(3)-*6'/*5'(3)-
4/5(7)-
*0/*6(4)-6'/0'(4)-1'/2'(4)-*2/*1(4)-
*1/*0(7)-
*3/*2(4)-2'/3'(4)-*4'/*3'(4)-4'/5'(4)-
*4/*3(3)-5'/6'(3)-*6/*5(3)-
*5/*4(7)-
0'/1'(7)-
*1'/*0'(7)-
(0 1)[2 3'](3 6')(4 5)(6 5')(0' 1')[2' 4']
0/1(7)-
1/2(4)-*3'/*2'(4)-4'/5'(4)-6/0(4)-
2/3(4)-6'/0'(4)-1'/2'(4)-*4'/*3'(4)-
3/4(3)-5/6(3)-5'/6'(3)-
4/5(7)-
*0/*6(4)-*5'/*4'(4)-2'/3'(4)-*2/*1(4)-
*1/*0(7)-
*3/*2(4)-3'/4'(4)-*2'/*1'(4)-*0'/*6'(4)-
*4/*3(3)-*6'/*5'(3)-*6/*5(3)-
*5/*4(7)-
0'/1'(7)-
*1'/*0'(7)-
!!!Step 3: Collating and numbering
Now that we have all the polygons of the tiling, we have to put them to some sort of order and assign them index numbers. First part here is the collating.
You see, sometimes a polygon has a reflection symmetry and sometimes it doesn't. If it doesn't, its enantiomers will appear on two different lines, and ideally, we want to put them next to each other.
How to determine whether the polygon has a reflection symmetry? Well, all you need to do is to take the first vertex symbol and mirror it, i.e. mirror each half-edge and swap their order. A mirror of 0/1 is *1/*0. A mirror of 7'/8' from the {12,10} solution is 8'/*7' because 8' is a self-mirrored half-edge which is not changed by mirroring. 2'/*2' is mirrored into 2'/*2'again -- that's a self-mirrored vertex form.
Now look for this mirrored vertex symbol. Is it in the same polygon? Then the polygon has reflection symmetry. Is it in another polygon? Then that's the mirror image of the polygon you're looking at and it should be moved close to it.
And after that, you just assign indexes. My result for our solutions looks like this:
(0 1')[0'][2'](6' 7')(8' 0'')
0: 0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-0'/1'(12)-
1: 2'/*2'(12)-
2: *0'/6'(5)-7'/8'(5)-0''/0''(5)-8'/*7'(5)-*6'/0'(5)-
3/4: 6'/7'(5)-
*7'/*6'(5)-
(0 1)(2 3')(3 6')(4 5)(6 5')(0' 1')(2')(4')
0: 0/1(7)-
*1/*0(7)-
1: 1/2(4)-3'/4'(4)-4'/5'(4)-6/0(4)-
*0/*6(4)-*5'/*4'(4)-*4'/*3'(4)-*2/*1(4)-
2: 2/3(4)-6'/0'(4)-1'/2'(4)-2'/3'(4)-
*3/*2(4)-*3'/*2'(4)-*2'/*1'(4)-*0'/*6'(4)-
3: 3/4(3)-5/6(3)-5'/6'(3)-
*4/*3(3)-*6'/*5'(3)-*6/*5(3)-
4: 4/5(7)-
*5/*4(7)-
5: 0'/1'(7)-
*1'/*0'(7)-
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')(3')(4')
0: 0/1(7)-
*1/*0(7)-
1: 1/2(4)-*2'/*1'(4)-*0'/*6'(4)-6/0(4)-
*0/*6(4)-6'/0'(4)-1'/2'(4)-*2/*1(4)-
2: 2/3(4)-*5'/*4'(4)-*4'/*3'(4)-*3'/*2'(4)-
*3/*2(4)-2'/3'(4)-3'/4'(4)-4'/5'(4)-
3: 3/4(3)-5/6(3)-*6'/*5'(3)-
*4/*3(3)-5'/6'(3)-*6/*5(3)-
4: 4/5(7)-
*5/*4(7)-
5: 0'/1'(7)-
*1'/*0'(7)-
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')[3' 4']
0: 0/1(7)-
*1/*0(7)-
1: 1/2(4)-*2'/*1'(4)-*0'/*6'(4)-6/0(4)-
*0/*6(4)-6'/0'(4)-1'/2'(4)-*2/*1(4)-
2: 2/3(4)-*5'/*4'(4)-3'/4'(4)-*3'/*2'(4)-
*3/*2(4)-2'/3'(4)-*4'/*3'(4)-4'/5'(4)-
3: 3/4(3)-5/6(3)-*6'/*5'(3)-
*4/*3(3)-5'/6'(3)-*6/*5(3)-
4: 4/5(7)-
*5/*4(7)-
5: 0'/1'(7)-
*1'/*0'(7)-
(0 1)[2 3'](3 6')(4 5)(6 5')(0' 1')[2' 4']
0: 0/1(7)-
*1/*0(7)-
1: 1/2(4)-*3'/*2'(4)-4'/5'(4)-6/0(4)-
*0/*6(4)-*5'/*4'(4)-2'/3'(4)-*2/*1(4)-
2: 2/3(4)-6'/0'(4)-1'/2'(4)-*4'/*3'(4)-
*3/*2(4)-3'/4'(4)-*2'/*1'(4)-*0'/*6'(4)-
3: 3/4(3)-5/6(3)-5'/6'(3)-
*4/*3(3)-*6'/*5'(3)-*6/*5(3)-
4: 4/5(7)-
*5/*4(7)-
5: 0'/1'(7)-
*1'/*0'(7)-
OK, what's going on here? Well, here's one thing that must be taken into account: there is, conceptually, a difference between tilings that contain tiles with reflection symmetry and tilings that don't.
This is not related to the way HyperRogue implements these tilings. Long story short, if there is at least one tile with reflection symmetry, then I have to implement tiles *without* reflection symmetry as two separate tiles (one for each enantiomer) to make it work correctly. But if *no* tile has reflection symmetry, then I can implement just one enantiomer of each as a tile, and it will be fine. So, at this point, the further steps will be a little different based on whether we have reflection symmetry or not.
Tilings without reflection symmetry on tiles might be actually chiral (it's a necessary conditon), but also, they might not be. They may even still have reflection symmetry, just not through tiles (so, the only mirrors allowed are those that lie wholly within edges).
As for the way you order the tiles, it doesn't really matter. I like to keep them as close to their original order as possible, but you can easily sort them by polygon size or by any other criteria.
!!!Step 4: Building a new Conway string
Now that we have tiles of the tiling, we match their edges together to create a new Conway string. In *.tes files, these strings describe how edges match, i.e. where you will end up if you leave a particular polygon through a particular edge.
The original solution is actually also concepted as edge-based -- instead of putting vertices together, we can also put together tiles that are dual to those vertices. It's all the same.
So, starting with the {12,10} solution,
(0 1')[0'][2'](6' 7')(8' 0'')
0: 0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-0'/1'(12)-
1: 2'/*2'(12)-
2: *0'/6'(5)-7'/8'(5)-0''/0''(5)-8'/*7'(5)-*6'/0'(5)-
3/4: 6'/7'(5)-
*7'/*6'(5)-
we build a new Conway string.
Let's rewrite these polygons a bit:
0: 1'(12)-0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-0'/
1: *2'(12)-2'/
2: 0'(5)-*0'/6'(5)-7'/8'(5)-0''/0''(5)-8'/*7'(5)-*6'/
3/4: 7'(5)-6'/
*6'(5)-*7'/
We just take the last half-edge of the polygon and move it to the front. Now, the polygon is no longer formed from vertex symbols separated by dashes, but from edge symbols separated by slashes! So, for example, the edge 0 (0th edge of the 0th polygon) is "1'-0", edge 1 is "0-1'", edge 3'' is "0''-8'", etc. (This is just a visualization, you don't have to actually do it physically, you just need to understand what each edge *is*.)
Two edges match if they have the same half-edges, but in the opposite order. So "1'-0" matches "0-1'".
This is confusing because I use the same naming scheme for edges of the polygons as for half-edges on the vertices. Sorry about that.
Let's write the edges in clearer way:
0/6: 1'-0/
1/7: 0-1'/
2/8: 2'-*2'/
3/9: *1'-*0/
4/10: *0-*1'/
5/11: *0'-0'/
0'/1'/2'/3'/4'/5'/6'/7'/8'/9'/10'/11': *2'-2'/
0'': 0'-*0'/
1'': 6'-7'/
2'': 8'-0''/
3'': 0''-8'/
4'': *7'-*6'/
0'''/1'''/2'''/3'''/4''': 7'-6'/
0@4/1@4/2@4/3@4/4@4: *6'-*7'/
And here is where multiplicity comes into play. The polygon 0, for example, is a dodecagon, but it only has 6 vertex/edge symbols, so it has multiplicity of 2. That means that its edge 0 is also edge 6, edge 1 is also edge 7, etc. The polygon 1, dodecagon with multiplicity 12, has its only edge represented as 12 edges ranging from 0' to 11'.
This has to do with HyperRogue not representing the tiles with symmetries. Representing the same edge with different numbers is a bit of a kluge, but the important thing is that it works.
Now that we have this representation, we can match edges together:
0/6: 1'-0/ + 1/7: 0-1'/
2/8: 2'-*2'/ + 0'/1'/2'/3'/4'/5'/6'/7'/8'/9'/10'/11': *2'-2'/
3/9: *1'-*0/ + 4/10: *0-*1'/
5/11: *0'-0'/ + 0'': 0'-*0'/
1'': 6'-7'/ + 0'''/1'''/2'''/3'''/4''': 7'-6'/
2'': 8'-0''/ + 3'': 0''-8'/
4'': *7'-*6'/ + 0@4/1@4/2@4/3@4/4@4: *6'-*7'/
And therefore form the Conway string:
(0 1)(6 7)
(2 0')(8 1')(2 2')(8 3')(2 4')(8 5')(2 6')(8 7')(2 8')(8 9')(2 10')(8 11')
(3 4)(9 10)
(5 0'')(11 0'')
(1'' 0''')(1'' 1''')(1'' 2''')(1'' 3''')(1'' 4''')
(2'' 3'')
(4'' 0@4)(4'' 1@4)(4'' 2@4)(4'' 3@4)(4'' 4@4)
There's no edge in this example that would be matched with itself (for that, it would have to be composed of two identical half-edges), but if it was, it would be represented by a symbol of form (x).
With the multiplicities, the only real rule is that *each* representation of the edge must be in there somewhere. The way I do it is that I start with symbol containing the first edge on both sides, then advance both by one in each subsequent symbol (wrapping the shorter list back to the first element), until both lists are exhausted -- so there should be the same number of symbols as is the number of elements in the longer list of edges.
The final part is just to concatenate all that into one long string. This is how the final solution looks in my reference files:
(0 1')[0'][2'](6' 7')(8' 0'')
0: 0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-0'/1'(12)-[0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-0'/1'(12)]
1: 2'/*2'(12)-[2'/*2'(12)-2'/*2'(12)-2'/*2'(12)-2'/*2'(12)-2'/*2'(12)-2'/*2'(12)-2'/*2'(12)-2'/*2'(12)-2'/*2'(12)-2'/*2'(12)-2'/*2'(12)]
2: *0'/6'(5)-7'/8'(5)-0''/0''(5)-8'/*7'(5)-*6'/0'(5)
3/4: 6'/7'(5)-[6'/7'(5)-6'/7'(5)-6'/7'(5)-6'/7'(5)]
*7'/*6'(5)-[*7'/*6'(5)-*7'/*6'(5)-*7'/*6'(5)-*7'/*6'(5)]
(0 1)(6 7)(2 0')(8 1')(2 2')(8 3')(2 4')(8 5')(2 6')(8 7')(2 8')(8 9')(2 10')(8 11')(3 4)(9 10)(5 0'')(11 0'')(1'' 0''')(1'' 1''')(1'' 2''')(1'' 3''')(1'' 4''')(2'' 3'')(4'' 0@4)(4'' 1@4)(4'' 2@4)(4'' 3@4)(4'' 4@4)
I write the polygons in this way, with brackets denoting repeating part and without the final dash to signify that they are complete. But those brackets are becoming more and more unwieldy, maybe it could look like this in the future?
(0 1')[0'][2'](6' 7')(8' 0'')
0: [0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-0'/1'(12)]x2
1: [2'/*2'(12)]x12
2: *0'/6'(5)-7'/8'(5)-0''/0''(5)-8'/*7'(5)-*6'/0'(5)
3/4: [6'/7'(5)]x5
[*7'/*6'(5)]x5
(0 1)(6 7)(2 0')(8 1')(2 2')(8 3')(2 4')(8 5')(2 6')(8 7')(2 8')(8 9')(2 10')(8 11')(3 4)(9 10)(5 0'')(11 0'')(1'' 0''')(1'' 1''')(1'' 2''')(1'' 3''')(1'' 4''')(2'' 3'')(4'' 0@4)(4'' 1@4)(4'' 2@4)(4'' 3@4)(4'' 4@4)
Anyway, on to build the {4,7}-class solutions:
(0 1)(2 3')(3 6')(4 5)(6 5')(0' 1')(2')(4')
0: 0/1(7)-
*1/*0(7)-
1: 1/2(4)-3'/4'(4)-4'/5'(4)-6/0(4)-
*0/*6(4)-*5'/*4'(4)-*4'/*3'(4)-*2/*1(4)-
2: 2/3(4)-6'/0'(4)-1'/2'(4)-2'/3'(4)-
*3/*2(4)-*3'/*2'(4)-*2'/*1'(4)-*0'/*6'(4)-
3: 3/4(3)-5/6(3)-5'/6'(3)-
*4/*3(3)-*6'/*5'(3)-*6/*5(3)-
4: 4/5(7)-
*5/*4(7)-
5: 0'/1'(7)-
*1'/*0'(7)-
Since this is a solution without reflection symmetries, the sequence will be a bit different. First, we can safely ignore the mirror images:
(0 1)(2 3')(3 6')(4 5)(6 5')(0' 1')(2')(4')
0: 0/1(7)-
1: 1/2(4)-3'/4'(4)-4'/5'(4)-6/0(4)-
2: 2/3(4)-6'/0'(4)-1'/2'(4)-2'/3'(4)-
3: 3/4(3)-5/6(3)-5'/6'(3)-
4: 4/5(7)-
5: 0'/1'(7)-
Then we separate the edges (again, this is illustrative, can be just done in your head/computer):
0: 1-0/
1: 0-1/2-3'/4'-4'/5'-6/
2: 3'-2/3-6'/0'-1'/2'-2'/
3: 6'-3/4-5/6-5'/
4: 5-4/
5: 1'-0'/
0/1/2/3/4/5/6: 1-0/
0': 0-1/
1': 2-3'/
2': 4'-4'/
3': 5'-6/
0'': 3'-2/
1'': 3-6'/
2'': 0'-1'/
3'': 2'-2'/
0''': 6'-3/
1''' 4-5/
2''' 6-5'/
0@4/1@4/2@4/3@4/4@4/5@4/6@4: 5-4/
0@5/1@5/2@5/3@5/4@5/5@5/6@5: 1'-0'/
0/1/2/3/4/5/6: 1-0/ + 0': 0-1/
1': 2-3'/ + 0'': 3'-2/
2': 4'-4'/ ~combined with itself
3': 5'-6/ + 2''' 6-5'/
1'': 3-6'/ + 0''': 6'-3/
2'': 0'-1'/ + 0@5/1@5/2@5/3@5/4@5/5@5/6@5: 1'-0'/
3'': 2'-2'/ ~combined with itself
1''' 4-5/ + 0@4/1@4/2@4/3@4/4@4/5@4/6@4: 5-4/
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')
(1' 0'')
(2')
(3' 2''')
(1'' 0''')
(2'' 0@5)(2'' 1@5)(2'' 2@5)(2'' 3@5)(2'' 4@5)(2'' 5@5)(2'' 6@5)
(3'')
(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
Let's try this for the remaining three solutions:
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')(3')(4')
0: 0/1(7)-
*1/*0(7)-
1: 1/2(4)-*2'/*1'(4)-*0'/*6'(4)-6/0(4)-
*0/*6(4)-6'/0'(4)-1'/2'(4)-*2/*1(4)-
2: 2/3(4)-*5'/*4'(4)-*4'/*3'(4)-*3'/*2'(4)-
*3/*2(4)-2'/3'(4)-3'/4'(4)-4'/5'(4)-
3: 3/4(3)-5/6(3)-*6'/*5'(3)-
*4/*3(3)-5'/6'(3)-*6/*5(3)-
4: 4/5(7)-
*5/*4(7)-
5: 0'/1'(7)-
*1'/*0'(7)-
0: 1-0/
1: 0-1/2-*2'/*1'-*0'/*6'-6/
2: *2'-2/3-*5'/*4'-*4'/*3'-*3'/
3: *5'-3/4-5/6-*6'/
4: 5-4/
5: 1'-0'/
0/1/2/3/4/5/6: 1-0/
0': 0-1/
1': 2-*2'/
2': *1'-*0'/
3': *6'-6/
0'': *2'-2/
1'': 3-*5'/
2'': *4'-*4'/
3'': *3'-*3'/
0''': *5'-3/
1''': 4-5/
2''': 6-*6'/
0@4/1@4/2@4/3@4/4@4/5@4/6@4: 5-4/
0@5/1@5/2@5/3@5/4@5/5@5/6@5: 1'-0'/
0/1/2/3/4/5/6: 1-0/ + 0': 0-1/
1': 2-*2'/ + 0'': *2'-2/
2': *1'-*0'/ X 0@5/1@5/2@5/3@5/4@5/5@5/6@5: 1'-0'/
3': *6'-6/ + 2''': 6-*6'/
1'': 3-*5'/ + 0''': *5'-3/
2'': *4'-*4'/ ~combined with itself
3'': *3'-*3'/ ~combined with itself
1''': 4-5/ + 0@4/1@4/2@4/3@4/4@4/5@4/6@4: 5-4/
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')
(1' 0'')
[2' 0@5][2' 1@5][2' 2@5][2' 3@5][2' 4@5][2' 5@5][2' 6@5]
(3' 2''')
(1'' 0''')
(2'')
(3'')
(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
---
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')[3' 4']
0: 0/1(7)-
*1/*0(7)-
1: 1/2(4)-*2'/*1'(4)-*0'/*6'(4)-6/0(4)-
*0/*6(4)-6'/0'(4)-1'/2'(4)-*2/*1(4)-
2: 2/3(4)-*5'/*4'(4)-3'/4'(4)-*3'/*2'(4)-
*3/*2(4)-2'/3'(4)-*4'/*3'(4)-4'/5'(4)-
3: 3/4(3)-5/6(3)-*6'/*5'(3)-
*4/*3(3)-5'/6'(3)-*6/*5(3)-
4: 4/5(7)-
*5/*4(7)-
5: 0'/1'(7)-
*1'/*0'(7)-
0: 1-0/
1: 0-1/2-*2'/*1'-*0'/*6'-6/
2: *2'-2/3-*5'/*4'-3'/4'-*3'/
3: *5'-3/4-5/6-*6'/
4: 5-4/
5: 1'-0'/
0/1/2/3/4/5/6: 1-0/
0': 0-1/
1': 2-*2'/
2': *1'-*0'/
3': *6'-6/
0'': *2'-2/
1'': 3-*5'/
2'': *4'-3'/
3'': 4'-*3'/
0''': *5'-3/
1''': 4-5/
2''': 6-*6'/
0@4/1@4/2@4/3@4/4@4/5@4/6@4: 5-4/
0@5/1@5/2@5/3@5/4@5/5@5/6@5: 1'-0'/
0/1/2/3/4/5/6: 1-0/ + 0': 0-1/
1': 2-*2'/ + 0'': *2'-2/
2': *1'-*0'/ X 0@5/1@5/2@5/3@5/4@5/5@5/6@5: 1'-0'/
3': *6'-6/ + 2''': 6-*6'/
1'': 3-*5'/ + 0''': *5'-3/
2'': *4'-3'/ X 3'': 4'-*3'/
1''': 4-5/ + 0@4/1@4/2@4/3@4/4@4/5@4/6@4: 5-4/
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')
(1' 0'')
[2' 0@5][2' 1@5][2' 2@5][2' 3@5][2' 4@5][2' 5@5][2' 6@5]
(3' 2''')
(1'' 0''')
[2'' 3'']
(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
---
(0 1)[2 3'](3 6')(4 5)(6 5')(0' 1')[2' 4']
0: 0/1(7)-
*1/*0(7)-
1: 1/2(4)-*3'/*2'(4)-4'/5'(4)-6/0(4)-
*0/*6(4)-*5'/*4'(4)-2'/3'(4)-*2/*1(4)-
2: 2/3(4)-6'/0'(4)-1'/2'(4)-*4'/*3'(4)-
*3/*2(4)-3'/4'(4)-*2'/*1'(4)-*0'/*6'(4)-
3: 3/4(3)-5/6(3)-5'/6'(3)-
*4/*3(3)-*6'/*5'(3)-*6/*5(3)-
4: 4/5(7)-
*5/*4(7)-
5: 0'/1'(7)-
*1'/*0'(7)-
0: 1-0/
1: 0-1/2-*3'/*2'-4'/5'-6/
2: *3'-2/3-6'/0'-1'/2'-*4'/
3: 6'-3/4-5/6-5'/
4: 5-4/
5: 1'-0'/
0/1/2/3/4/5/6: 1-0/
0': 0-1/
1': 2-*3'/
2': *2'-4'/
3': 5'-6/
0'': *3'-2/
1'': 3-6'/
2'': 0'-1'/
3'': 2'-*4'/
0''': 6'-3/
1''': 4-5/
2''': 6-5'/
0@4/1@4/2@4/3@4/4@4/5@4/6@4: 5-4/
0@5/1@5/2@5/3@5/4@5/5@5/6@5: 1'-0'/
0/1/2/3/4/5/6: 1-0/ + 0': 0-1/
1': 2-*3'/ + 0'': *3'-2/
2': *2'-4'/ X 3'': 2'-*4'/
3': 5'-6/ + 2''': 6-5'/
1'': 3-6'/ + 0''': 6'-3/
2'': 0'-1'/ + 0@5/1@5/2@5/3@5/4@5/5@5/6@5: 1'-0'/
1''': 4-5/ + 0@4/1@4/2@4/3@4/4@4/5@4/6@4: 5-4/
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')
(1' 0'')
[2' 3'']
(3' 2''')
(1'' 0''')
(2'' 0@5)(2'' 1@5)(2'' 2@5)(2'' 3@5)(2'' 4@5)(2'' 5@5)(2'' 6@5)
(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
---
You might have noticed the X symbol in these three. Since we eliminated the mirror images, an edge of form x-y has either a partner of form y-x (signalized by "+"), OR a partner of form *x-*y (signalized by "X"). In the second case, the symbol will have brackets instead of parentheses. Note that if there is a tile with reflection symmetry, all symbols will use parentheses.
And so we have final form of the five solutions we've been working on:
(0 1')[0'][2'](6' 7')(8' 0'')
0: [0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-0'/1'(12)]x2
1: [2'/*2'(12)]x12
2: *0'/6'(5)-7'/8'(5)-0''/0''(5)-8'/*7'(5)-*6'/0'(5)
3/4: [6'/7'(5)]x5
[*7'/*6'(5)]x5
(0 1)(6 7)(2 0')(8 1')(2 2')(8 3')(2 4')(8 5')(2 6')(8 7')(2 8')(8 9')(2 10')(8 11')(3 4)(9 10)(5 0'')(11 0'')(1'' 0''')(1'' 1''')(1'' 2''')(1'' 3''')(1'' 4''')(2'' 3'')(4'' 0@4)(4'' 1@4)(4'' 2@4)(4'' 3@4)(4'' 4@4)
(0 1)(2 3')(3 6')(4 5)(6 5')(0' 1')(2')(4')
0: [0/1(7)]x7
[*1/*0(7)]x7
1: 1/2(4)-3'/4'(4)-4'/5'(4)-6/0(4)
*0/*6(4)-*5'/*4'(4)-*4'/*3'(4)-*2/*1(4)
2: 2/3(4)-6'/0'(4)-1'/2'(4)-2'/3'(4)
*3/*2(4)-*3'/*2'(4)-*2'/*1'(4)-*0'/*6'(4)
3: 3/4(3)-5/6(3)-5'/6'(3)
*4/*3(3)-*6'/*5'(3)-*6/*5(3)
4: [4/5(7)]x7
[*5/*4(7)]x7
5: [0'/1'(7)]x7
[*1'/*0'(7)]x7
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')(2')(3' 2''')(1'' 0''')(2'' 0@5)(2'' 1@5)(2'' 2@5)(2'' 3@5)(2'' 4@5)(2'' 5@5)(2'' 6@5)(3'')(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')(3')(4')
0: [0/1(7)]x7
[*1/*0(7)]x7
1: 1/2(4)-*2'/*1'(4)-*0'/*6'(4)-6/0(4)
*0/*6(4)-6'/0'(4)-1'/2'(4)-*2/*1(4)
2: 2/3(4)-*5'/*4'(4)-*4'/*3'(4)-*3'/*2'(4)
*3/*2(4)-2'/3'(4)-3'/4'(4)-4'/5'(4)
3: 3/4(3)-5/6(3)-*6'/*5'(3)
*4/*3(3)-5'/6'(3)-*6/*5(3)
4: [4/5(7)]x7
[*5/*4(7)]x7
5: [0'/1'(7)]x7
[*1'/*0'(7)]x7
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')[2' 0@5][2' 1@5][2' 2@5][2' 3@5][2' 4@5][2' 5@5][2' 6@5](3' 2''')(1'' 0''')(2'')(3'')(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')[3' 4']
0: [0/1(7)]x7
[*1/*0(7)]x7
1: 1/2(4)-*2'/*1'(4)-*0'/*6'(4)-6/0(4)
*0/*6(4)-6'/0'(4)-1'/2'(4)-*2/*1(4)
2: 2/3(4)-*5'/*4'(4)-3'/4'(4)-*3'/*2'(4)
*3/*2(4)-2'/3'(4)-*4'/*3'(4)-4'/5'(4)
3: 3/4(3)-5/6(3)-*6'/*5'(3)
*4/*3(3)-5'/6'(3)-*6/*5(3)
4: [4/5(7)]x7
[*5/*4(7)]x7
5: [0'/1'(7)]x7
[*1'/*0'(7)]x7
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')[2' 0@5][2' 1@5][2' 2@5][2' 3@5][2' 4@5][2' 5@5][2' 6@5](3' 2''')(1'' 0''')[2'' 3''](1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
(0 1)[2 3'](3 6')(4 5)(6 5')(0' 1')[2' 4']
0: [0/1(7)]x7
[*1/*0(7)]x7
1: 1/2(4)-*3'/*2'(4)-4'/5'(4)-6/0(4)
*0/*6(4)-*5'/*4'(4)-2'/3'(4)-*2/*1(4)
2: 2/3(4)-6'/0'(4)-1'/2'(4)-*4'/*3'(4)
*3/*2(4)-3'/4'(4)-*2'/*1'(4)-*0'/*6'(4)
3: 3/4(3)-5/6(3)-5'/6'(3)
*4/*3(3)-*6'/*5'(3)-*6/*5(3)
4: [4/5(7)]x7
[*5/*4(7)]x7
5: [0'/1'(7)]x7
[*1'/*0'(7)]x7
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')[2' 3''](3' 2''')(1'' 0''')(2'' 0@5)(2'' 1@5)(2'' 2@5)(2'' 3@5)(2'' 4@5)(2'' 5@5)(2'' 6@5)(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
Yeah, except for one esthetic correction. The first {4,7}-class solution, "(0 1)(2 3')(3 6')(4 5)(6 5')(0' 1')(2')(4')" is chiral. You can see that because its edge-based Conway string never uses brackets even though it's allowed to. Note that the original vertex solution also uses no brackets. But the second solution from that class, "(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')(3')(4')" looks different -- its vertex and edge Conway strings both use brackets. But if we look closely, vertex string has brackets around combinations of tiles 0 and 1, and *only* those. The solution is still chiral. So, I make a small change on its final edge solution. From this:
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')[2' 0@5][2' 1@5][2' 2@5][2' 3@5][2' 4@5][2' 5@5][2' 6@5](3' 2''')(1'' 0''')(2'')(3'')(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
To this:
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')(2' 0@5)(2' 1@5)(2' 2@5)(2' 3@5)(2' 4@5)(2' 5@5)(2' 6@5)(3' 2''')(1'' 0''')(2'')(3'')(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
I have basically exchanged tile 5 with its mirror image because by doing that, I have completely eliminated brackets from the solution. Otherwise, HyperRogue would use different color for tile 5, since it would use its mirror image instead of the basic version. This correction is, of course, nowhere near required -- it just makes the solution look a bit nicer.
Similar for the third {4,7} solution. It, too, contains substring "[2' 0@5][2' 1@5][2' 2@5][2' 3@5][2' 4@5][2' 5@5][2' 6@5]", and I can reduce the amount of brackets by exchanging tile 5 with its mirror image. Note that in this case, brackets will *not* be eliminated completely; the tiling as a whole is not chiral, and so it has to use both enantiomers of each tile.
This "reduce brackets as much as possible" step is not really rigorous and I myself do it inconsistently.
Anyway, here are the solutions again, after this correction:
(0 1')[0'][2'](6' 7')(8' 0'')
0: [0/0(12)-1'/2'(12)-*2'/*1'(12)-*0/*0(12)-*1'/*0'(12)-0'/1'(12)]x2
1: [2'/*2'(12)]x12
2: *0'/6'(5)-7'/8'(5)-0''/0''(5)-8'/*7'(5)-*6'/0'(5)
3/4: [6'/7'(5)]x5
[*7'/*6'(5)]x5
(0 1)(6 7)(2 0')(8 1')(2 2')(8 3')(2 4')(8 5')(2 6')(8 7')(2 8')(8 9')(2 10')(8 11')(3 4)(9 10)(5 0'')(11 0'')(1'' 0''')(1'' 1''')(1'' 2''')(1'' 3''')(1'' 4''')(2'' 3'')(4'' 0@4)(4'' 1@4)(4'' 2@4)(4'' 3@4)(4'' 4@4)
(0 1)(2 3')(3 6')(4 5)(6 5')(0' 1')(2')(4')
0: [0/1(7)]x7
[*1/*0(7)]x7
1: 1/2(4)-3'/4'(4)-4'/5'(4)-6/0(4)
*0/*6(4)-*5'/*4'(4)-*4'/*3'(4)-*2/*1(4)
2: 2/3(4)-6'/0'(4)-1'/2'(4)-2'/3'(4)
*3/*2(4)-*3'/*2'(4)-*2'/*1'(4)-*0'/*6'(4)
3: 3/4(3)-5/6(3)-5'/6'(3)
*4/*3(3)-*6'/*5'(3)-*6/*5(3)
4: [4/5(7)]x7
[*5/*4(7)]x7
5: [0'/1'(7)]x7
[*1'/*0'(7)]x7
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')(2')(3' 2''')(1'' 0''')(2'' 0@5)(2'' 1@5)(2'' 2@5)(2'' 3@5)(2'' 4@5)(2'' 5@5)(2'' 6@5)(3'')(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')(3')(4')
0: [0/1(7)]x7
[*1/*0(7)]x7
1: 1/2(4)-*2'/*1'(4)-*0'/*6'(4)-6/0(4)
*0/*6(4)-6'/0'(4)-1'/2'(4)-*2/*1(4)
2: 2/3(4)-*5'/*4'(4)-*4'/*3'(4)-*3'/*2'(4)
*3/*2(4)-2'/3'(4)-3'/4'(4)-4'/5'(4)
3: 3/4(3)-5/6(3)-*6'/*5'(3)
*4/*3(3)-5'/6'(3)-*6/*5(3)
4: [4/5(7)]x7
[*5/*4(7)]x7
5: [0'/1'(7)]x7
[*1'/*0'(7)]x7
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')(2' 0@5)(2' 1@5)(2' 2@5)(2' 3@5)(2' 4@5)(2' 5@5)(2' 6@5)(3' 2''')(1'' 0''')(2'')(3'')(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
(0 1)[2 2'][3 5'](4 5)[6 6'](0' 1')[3' 4']
0: [0/1(7)]x7
[*1/*0(7)]x7
1: 1/2(4)-*2'/*1'(4)-*0'/*6'(4)-6/0(4)
*0/*6(4)-6'/0'(4)-1'/2'(4)-*2/*1(4)
2: 2/3(4)-*5'/*4'(4)-3'/4'(4)-*3'/*2'(4)
*3/*2(4)-2'/3'(4)-*4'/*3'(4)-4'/5'(4)
3: 3/4(3)-5/6(3)-*6'/*5'(3)
*4/*3(3)-5'/6'(3)-*6/*5(3)
4: [4/5(7)]x7
[*5/*4(7)]x7
5: [0'/1'(7)]x7
[*1'/*0'(7)]x7
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')(2' 0@5)(2' 1@5)(2' 2@5)(2' 3@5)(2' 4@5)(2' 5@5)(2' 6@5)(3' 2''')(1'' 0''')[2'' 3''](1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
(0 1)[2 3'](3 6')(4 5)(6 5')(0' 1')[2' 4']
0: [0/1(7)]x7
[*1/*0(7)]x7
1: 1/2(4)-*3'/*2'(4)-4'/5'(4)-6/0(4)
*0/*6(4)-*5'/*4'(4)-2'/3'(4)-*2/*1(4)
2: 2/3(4)-6'/0'(4)-1'/2'(4)-*4'/*3'(4)
*3/*2(4)-3'/4'(4)-*2'/*1'(4)-*0'/*6'(4)
3: 3/4(3)-5/6(3)-5'/6'(3)
*4/*3(3)-*6'/*5'(3)-*6/*5(3)
4: [4/5(7)]x7
[*5/*4(7)]x7
5: [0'/1'(7)]x7
[*1'/*0'(7)]x7
(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')[2' 3''](3' 2''')(1'' 0''')(2'' 0@5)(2'' 1@5)(2'' 2@5)(2'' 3@5)(2'' 4@5)(2'' 5@5)(2'' 6@5)(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)
!!!Step 5: Building *.tes file
Let's go right ahead and show the syntax of *.tes file for the {12,10}-class solution:
## {12,10} class hybrid, (12,12,12,12,12,12,12,12,12,12)+(5,5,5,5,5,5,12,12,12,12,12)+(5,5,5,5,5,5,5,5,5,5,5,5), R10AS12
h2.
distunit(edge(12,10))
let(u5 = regangle(1, 5))
let(u12 = regangle(1, 12))
unittile(u12,u12,u12,u12,u12,u12,u12,u12,u12,u12,u12,u12)
unittile(u12,u12,u12,u12,u12,u12,u12,u12,u12,u12,u12,u12)
unittile(u5,u5,u5,u5,u5)
unittile(u5,u5,u5,u5,u5)
unittile(u5,u5,u5,u5,u5)
conway("(0 1)(6 7)(2 0')(8 1')(2 2')(8 3')(2 4')(8 5')(2 6')(8 7')(2 8')(8 9')(2 10')(8 11')(3 4)(9 10)(5 0'')(11 0'')(1'' 0''')(1'' 1''')(1'' 2''')(1'' 3''')(1'' 4''')(2'' 3'')(4'' 0@4)(4'' 1@4)(4'' 2@4)(4'' 3@4)(4'' 4@4)")
The first row is the header, a comment line starting with ## that describes what this is about. When I build multiple solutions from the same setting, I generally use ", solution " and append the appropriate number.
"h2." specifies that this is hyperbolic tiling. If we had spherical or Euclidean tiling, we could also display it, but we'd have to change this row.
"distunit" specifies how we measure the distance in the hyperbolic plane. In this case, the edge of {12,10} is set as a unit. We combine several different vertices, but they all share this edge, so any of them can be used.
The "let" rows define angular measures. "regangle(1, 5)" means "take a regular pentagon of side 1 (as measured by previously used distunit command), and compute its inner angle".
Actually, in this case, both pentagons and dodecagons have rational angles and they can be written directly, but that's not the usual case, so I'm leaving it as it is for now.
Next, the "unittile" rows. They are in the same order as polygons in the solution and I think it can be seen pretty clearly how they work. One defines a dodecagon using 12 angles of size u12, the other defines a pentagon using 5 angles of size u5. Each polygon in the solution gets its own unittile definition; the solution uses two dodecagons and three pentagons.
Finally, the "conway" row which has the final version of the solution string.
And that's it! Once built this way, this should work!
Let's do files for the four {4,7}-class solutions:
## {4,7} class hybrid, (3,4,4,7,4,3,7)+(3,4,4,4,4,7,4), solution 1
h2.
distunit(edge(4,7))
let(u3 = regangle(1, 3))
let(u4 = regangle(1, 4))
let(u7 = regangle(1, 7))
unittile(u7,u7,u7,u7,u7,u7,u7)
unittile(u4,u4,u4,u4)
unittile(u4,u4,u4,u4)
unittile(u3,u3,u3)
unittile(u7,u7,u7,u7,u7,u7,u7)
unittile(u7,u7,u7,u7,u7,u7,u7)
conway("(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')(2')(3' 2''')(1'' 0''')(2'' 0@5)(2'' 1@5)(2'' 2@5)(2'' 3@5)(2'' 4@5)(2'' 5@5)(2'' 6@5)(3'')(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)")
## {4,7} class hybrid, (3,4,4,7,4,3,7)+(3,4,4,4,4,7,4), solution 2
h2.
distunit(edge(4,7))
let(u3 = regangle(1, 3))
let(u4 = regangle(1, 4))
let(u7 = regangle(1, 7))
unittile(u7,u7,u7,u7,u7,u7,u7)
unittile(u4,u4,u4,u4)
unittile(u4,u4,u4,u4)
unittile(u3,u3,u3)
unittile(u7,u7,u7,u7,u7,u7,u7)
unittile(u7,u7,u7,u7,u7,u7,u7)
conway("(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')(2' 0@5)(2' 1@5)(2' 2@5)(2' 3@5)(2' 4@5)(2' 5@5)(2' 6@5)(3' 2''')(1'' 0''')(2'')(3'')(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)")
## {4,7} class hybrid, (3,4,4,7,4,3,7)+(3,4,4,4,4,7,4), solution 3
h2.
distunit(edge(4,7))
let(u3 = regangle(1, 3))
let(u4 = regangle(1, 4))
let(u7 = regangle(1, 7))
unittile(u7,u7,u7,u7,u7,u7,u7)
unittile(u4,u4,u4,u4)
unittile(u4,u4,u4,u4)
unittile(u3,u3,u3)
unittile(u7,u7,u7,u7,u7,u7,u7)
unittile(u7,u7,u7,u7,u7,u7,u7)
conway("(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')(2' 0@5)(2' 1@5)(2' 2@5)(2' 3@5)(2' 4@5)(2' 5@5)(2' 6@5)(3' 2''')(1'' 0''')[2'' 3''](1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)")
## {4,7} class hybrid, (3,4,4,7,4,3,7)+(3,4,4,4,4,7,4), solution 4
h2.
distunit(edge(4,7))
let(u3 = regangle(1, 3))
let(u4 = regangle(1, 4))
let(u7 = regangle(1, 7))
unittile(u7,u7,u7,u7,u7,u7,u7)
unittile(u4,u4,u4,u4)
unittile(u4,u4,u4,u4)
unittile(u3,u3,u3)
unittile(u7,u7,u7,u7,u7,u7,u7)
unittile(u7,u7,u7,u7,u7,u7,u7)
conway("(0 0')(1 0')(2 0')(3 0')(4 0')(5 0')(6 0')(1' 0'')[2' 3''](3' 2''')(1'' 0''')(2'' 0@5)(2'' 1@5)(2'' 2@5)(2'' 3@5)(2'' 4@5)(2'' 5@5)(2'' 6@5)(1''' 0@4)(1''' 1@4)(1''' 2@4)(1''' 3@4)(1''' 4@4)(1''' 5@4)(1''' 6@4)")