---
title: "12 Pentagons, Part 2"
description: |
  There are 12 pentagons. Why stop at dodecahedra?
format:
  html:
    html-math-method: katex
jupyter: python3
date: "2021-06-04"
date-modified: "2025-03-16"
categories:
  - geometry
  - combinatorics
  - symmetry
---

<style>
figure > p {
  text-align: center;
}

.image-wide {
  width: 384px;
  object-fit: contain;
}
</style>

```{python}
from dataclasses import dataclass, asdict

from IPython.display import Markdown
import matplotlib.pyplot as plt
from tabulate import tabulate

from goldberg.display import (
    display_conway,
    group_dict,
    hexagons_to_polyhedron,
    link_polyhedronisme,
    parameter_to_class,
    remove_repeats,
)
from goldberg.operators import (
    goldberg_parameters_to_operators,
    goldberg_operators_to_parameters,
    loeschian_norm,
)
from goldberg.tetrahedral import (
    tetrahedral_goldberg_recipes,
    tetrahedral_goldberg_antitruncations,
    double_goldberg_antitruncations
)
import goldberg.triangles as goldberg_triangles
```

This is the second part in an investigation into answering the following question:

> A soccer ball is a (roughly spherical) figure made of pentagons and hexagons, each meeting 3 at a point.
  [T]here are 12 pentagons...how many hexagons can there be?

The [post prior to this one](../1) proved the 12 pentagons portion
  as well as outlined an entire solution class: (dodecahedral) Goldberg polyhedra.

Despite these solutions being interesting in their own right, I grew preoccupied
  with finding other, more obscure solutions missed by this construction.


Twelve is Four Triples
----------------------

A key characteristic of the solution polyhedra is that each vertex is of degree three ($3V = 2E$).
It would be extraordinarily convenient if three pentagons came together at a vertex,
  or in the parlance of the previous post, a $V^3$.
Since there are 12 pentagons, there must be four vertices.

Fortunately, there exists a Platonic solid with four vertices whose symmetries we can exploit: the tetrahedron.


### Extended Goldberg Polyhedra

All vertices in the tetrahedron are of degree 3.
This qualifies it to undergo Goldberg construction[^1].
Recall the triangular plane and hexagonal paths from the previous part
  (presented again here for convenience):

[^1]:
    ::: {}
    The equation we used to obtain the "12 pentagons" figure also applies
      to the tetrahedron, with some adjustments:

    $$
    \begin{align*}
      \chi &= V - E + F_3 + F_n \\
      2n\chi
      &= 2nV - \textcolor{red}{2nE} + 2nF_3 + 2nF_n + \textcolor{blue}{0}\\
      &= 2nV
        - \textcolor{red}{\stackrel{3V = 2E}{3nV}}
        + 2nF_3
        + 2nF_n
        + \textcolor{blue}{\stackrel{3V = 3F_3 + nF_n}{
          6V
          - 6F_3
          - 2nF_n
        }} \\
      &= (6 - n)V + (2n - 6)F_3 \\
      &= 4n
    \end{align*}
    $$

    From this, it is discerned that there are 4 vertices ($n = 3$)
      or 4 trianglar faces ($n = 6$), with the rest of the faces being hexagons.
    :::

::: {.row width="100%"}
```{python}
goldberg_triangles.draw_sector((4, 2), path=True)
plt.show()
```
:::

When applying the construction to the dodecahedron, the red, green, and blue triangles were
  supposed to be part of a pentagon.
Instead, the triangles can also be considered as whole triangles bordering a sector.
Just like in the dodecahedral case,
  Class I polyhedra build hexagons in the shape of gnomons of centered hexagonal numbers,
  Class II polyhedra build them in the shape of triangular numbers,
  and Class III build them in the shape of figures with triangular symmetry.

Supposing a tetrahedron is made into a Goldberg polyhedron, where does that get us?
Well for starters, we know there are:

$$
\begin{gather*}
  {\|a + bu\|\ –\ 1 \over 6}
    \scriptsize {\text{hexagons} \over \text{sector}}
    \normalsize \cdot 3
    \scriptsize {\text{sectors} \over \text{triangle}}
    \normalsize \cdot 4 \scriptsize \text{ triangles}
    \normalsize \\[4pt]
  = 2(\|a +bu\|\ –\ 1) \text{ hexagons}
\end{gather*}
$$

The figure produced by this construction also must have
  [tetrahedral symmetry](https://en.wikipedia.org/wiki/Tetrahedral_symmetry) ($T$),
  since it was constructed from the tetrahedron.
This symmetry occurs within icosahedral symmetry, which we've already explored.

To transform this figure into a true solution, recognize that each triangle shares an edge with 3 hexagons.
If the triangle is "capped" such that all three adjacent faces are made to meet at a vertex,
  then the hexagons turn into pentagons.
There are now 12 pentagons and 12 fewer hexagons than there were previously, or $2\|a +bu\|\ –\ 14$.

This can be considered an opposite process to truncation, or "antitruncation".
Rather than selecting for the degree, this type of truncation selects for the vertex configuration:
  that of having three pentagons meeting at it ($V^3$).


### Negative Hexagons?

There is a slight problem with the above expression.
The norms of (1, 0), (1, 1), (2, 0), and (2, 1) are all less than or equal to 7,
  which implies a negative number of hexagons.
This is because the antitruncations correspond to one of the three Platonic solids with 3 faces to an vertex:

::: {layout-ncol="2"}
![
  (1, 0): T <br>
  Antitruncation: dT = T
](./polyhedronisme-T.png)

![
  (1, 1): tT <br>
  Antitruncation: T
](./polyhedronisme-K300tT.png)

![
  (2, 0): cT <br>
  Antitruncation: C
](./polyhedronisme-K300cT.png)

![
  (2, 1): wT <br>
  Antitruncation: D
](./polyhedronisme-K300wT.png)
:::

With these exceptional cases taken care of, the table of solution polyhedra of this form is as follows:

```{python}
#| label: tbl-antitruncation
#| classes: plain
#| tbl-cap: \\\* higher-order whirl needed <br> \\\*\\\* Unknown. Possibly nonexistent under standard operators

count_dodecahedral = lambda a, b: 10*loeschian_norm(a, b) - 10
count_tetrahedral = lambda a, b: 2*loeschian_norm(a, b) - 14

@dataclass
class TetrahedralSolution:
    klass: str
    parameter: str
    conway_trunc: str
    conway: str
    hexagon_count: str
    vertex_count: str
    edge_count: str
    paths: str

tet_anti_rows = [
    TetrahedralSolution(
        klass=parameter_to_class(parameter),
        parameter=str(parameter),
        conway_trunc=(
            truncated_recipe
            if truncated_recipe.find("*") == 0
            else link_polyhedronisme(
                display_conway(goldberg_parameters_to_operators[parameter], "T"),
                truncated_recipe,
            )
        ),
        hexagon_count=str(polyhedron.face_count - 12),
        vertex_count=str(polyhedron.vertex_count),
        edge_count=str(polyhedron.edge_count),
        conway=(
            antitruncation.conway
            if antitruncation.conway.find("*") == 0
            else link_polyhedronisme(
                display_conway(antitruncation.conway),
                antitruncation.conway_recipe,
            )
        ),
        paths=(
            ""
            if not antitruncation.intercluster_paths
            else f"${', '.join(
                map(str, antitruncation.intercluster_paths)
            )}$"
        )
    )
    for parameter, antitruncation in tetrahedral_goldberg_antitruncations.items()
    for truncated_recipe in (tetrahedral_goldberg_recipes[parameter].split(" = ")[-1],)
    for polyhedron in (hexagons_to_polyhedron(count_tetrahedral(*parameter)),)
]


tet_anti_headers = TetrahedralSolution(
    klass="Class",
    parameter="Parameter",
    conway_trunc="Conway (Trunc)",
    hexagon_count="$F_6$",
    edge_count="E",
    vertex_count="V",
    conway="Conway",
    paths="Paths",
)


Markdown(tabulate(
    {
        field: [name] + (remove_repeats if field == "klass" else lambda x: x)(
            [getattr(item, field) for item in tet_anti_rows]
        )
        for field, name in asdict(tet_anti_headers).items()
    },
    headers="firstrow",
    numalign="left",
))
```

The operators *g* and *j*, which I did not introduce previously, appear in the above table.
Rather than explaining their intuitive meaning, see
  [the Wikipedia article](https://en.wikipedia.org/wiki/Conway_polyhedron_notation)
  instead.

Note also that the links in the above table may have recipes do not match their entry.
Rather, the recipe is equivalent to the simpler string in the table to ensure the viewer
  can stably generate the output shape.

By leaving a pentagon from an edge which does not share a vertex with another pentagon, we can follow
  a path on the hexagons to another pentagon.
In the Class I case, this crosses two fewer edges than the parameter,
  since the edges of the triangle from the Goldberg operation have been capped.
This is also true in the Class II case, but both terms of the parameter are decreased by 1.
Class III is mostly the same as Class II, except when one of the parameters is 1.
In this case, the path is "whirled" -- it approaches the terminal pentagon from
  an edge touching another pentagon.
Also, for a whirled path *w*(*a*, *b*), both paths (*a*, *b*) and  (*a + b*, 0) have this property.

The smallest "real" tetrahedral solution has 4 hexagonal faces.
This is the
  [(order-6) truncated triakis tetrahedron](https://en.wikipedia.org/wiki/Truncated_triakis_tetrahedron),
  which corresponds nicely with its Conway notation $t_6kT$.

![
  Truncated triakis tetrahedron, $t_6kT$
](./polyhedronisme-K300t6kT.png)


### Solution Non-Exclusivity

Is it possible for the number of hexagons in a tetrahedral Goldberg solutions
  to coincide with that of a dodecahedral Goldberg solutions?
For this to be the case,

$$
\begin{align*}
  \stackrel{\text{Tetrahedral}}{2\|m + nu\| - 14}
    &= \stackrel{\text{Dodecahedral}}{10\|a + bu\| - 10}
    , \text{ for } a, b, m, n \in \mathbb{Z} \\
  \|m + nu\| - 2 &= 5\|a + bu\| \\
  \|m + nu\| &\equiv 2\ (\text{mod } 5)
\end{align*}
$$

Class I parameters have a norm which is a square number,
  but 2 is not among the squares mod 5,
  so the tetrahedral solutions will never intersect dodecahedral solutions.

Tetrahedral Class II coincidences such as (2, 2) and (3, 3) seem more plausible,
  but this turns out to be a red herring.
First, note that the norms on either side of the equation must be congruent to 0 or 1 (mod 3)[^2].
In particular, $\|m + mu\|$ is always congruent to 0 (mod 3)
  and $5\|a + bu\|$ is congruent to 0 or 2 (mod 3).
But -2 is congruent to 1, so equality is impossible.

[^2]:
    ::: {}
    Consider the equation $a^2 + ab + b^2 = 2$.
    Since 0 and 1 are the only squares mod 3, we can build a table out of each possibility:

    | $a^2$ | $b^2$ | $a^2 + ab + b^2 = 2$                                        | Possible? |
    |-------|-------|-------------------------------------------------------------|-----------|
    |     0 |     0 | $ab \equiv 2$, but *a* and *b* must be multiples of 3       |        No |
    |     0 |     1 | $ab \equiv 1$, but *a* is a multiple of 3                   |        No |
    |     1 |     0 | Same as in the above case, but for *b*                      |        No |
    |     1 |     1 | $ab \equiv 0$, but neither of *a* or *b* is a multiple of 3 |        No |

    On the other hand, if $b \equiv 0$, then the norm is $a^2$, which is either 0 or 1.
    :::

Only tetrahedral Class III collisions exist, and they must be congruent to the pairs
  (1, 2), (2, 1), (2, 2), (3, 3), (3, 4), or (4, 3) (mod 5).
Some of these can be found in the table below.

```{python}
#| classes: plain
#| tbl-cap: "Red paths denote paths between pentagons in the same \"cluster\".\
#|           <br>Blue paths are those between clusters, as from the earlier table."

# Groupings of dodecahedral and tetrahedral solutions by hexagon counts
dodecahedrals = group_dict(
    [
        ((a, b), count_dodecahedral(a, b))
        for a in range(8)
        for b in range(5)
        if a > b
    ],
    lambda x: x[1]
)
tetrahedrals = group_dict(
    [
        ((m, n), count_tetrahedral(m, n))
        for m in range(18)
        for n in range(9)
        if m > n
    ],
    lambda x: x[1]
)

# Table of collisions between both groupings
Markdown(tabulate(
    [
        [
            "<br>".join([str(j) for j, _ in dodecahedrals[i]]),
            "<br>".join([str(j) for j, _ in tetrahedrals[i]]),
            i,
        ]
        for i in sorted(dodecahedrals.keys()) if tetrahedrals.get(i) is not None
    ],
    headers=["Dodecahedral Parameter", "Tetrahedral Parameter", "$F_6$"],
    numalign="left",
))
```


Twelve is Six Pairs
-------------------

The truncated triakis tetrahedron (for simplicity, TTT) also reveals
  another possible set of solution polyhedra.
It not only has four $V^3$s -- which are produced by the antitruncation -- but also six $E^2$s.
These edges align with the six edges of the original tetrahedron.
Unfortunately, selectively preserving these edges by using standard Conway operators is difficult,
  and the only recourse is to develop solutions by hand.


### Hexagons in Triangles

It is easiest to see solutions take form on a tetrahedral net.
Every face and every vertex of a tetrahedron must be invariant under thirds of a turn,
  so when we interpolate with hexagons,
  the shape they form near those regions must be symmetric in the same way.
The easiest way to do this is by arranging hexagons in triangles.

::: {#fig-pair-solution layout-ncol="2"}
![
  Solution on tetrahedral net.
  Identical points at the edges of the figure are identified by exterior dotted lines.
](./edge_chamfer2_net.png)

![
  Equivalent planar graph.
](./edge_chamfer2_planar.png)
:::

Here, a triangle of 3 red hexagons lives at the center of each face of the original tetrahedron.
The pairs of pentagons are colored in green and live at the center of every original edge.
The remaining hexagons are colored in blue, and must be symmetric about the original vertices.
In this case, they turn out to be arranged in the same figures as the face-centered hexagons.

Like Goldberg polyhedra, we can denote this solution by a path between pentagons.
The path between those sharing an edge will always be (1, 0), so this path is unremarkable.
There also exists a path from one pentagon of a pair to another of a pair,
  starting from the edges which border the face of the base tetrahedron.
In the TTT, we get to another pentagon after crossing one edge without turning, and in the new solution,
  we get to another pentagon after crossing two edges without turning.
Thus, the former can be parametrized by (1, 0) and the latter by (2, 0).

Let's extend the figure once more before generalizing.
The hexagons in the center of the face are arranged in triangles with two at an edge, bordering a pentagon.
Keeping the pentagon in the center of the edge, we can extend the triangle of hexagons
  so that there are four at an edge:

::: {layout-ncol="2"}
![
  Second solution on tetrahedral net with identical points identified.
](./edge_chamfer3_net.png)

![
  Equivalent planar graph, after recoloring.
](./edge_chamfer3_planar.png)
:::

The left and right diagrams have slightly different colorings -- some red hexagons
  are changed into blue ones so that the blue hexagons form triangles, like in previous figures.
This makes it easier to generalize solutions, since the vertex figures steadily increase
  along triangular numbers.
However, the face figures have gone from a triangular arrangement to a hexagonal one.
Despite this, the figure does indeed have a (3, 0) path.

For a path $(n, 0)$, there are $n + 1$ polygons (both hexagons and pentagons) on the edge of a face figure.
With the pentagons, these figures make up triangles,
  so there are $\Delta_{n + 1} - 3$ hexagons on every face, where $\Delta_n$ is a triangular number.
On the vertices, every edge we cross along the path corresponds to a hexagon
  also on the edge of a triangular vertex figure, giving $\Delta_{n}$ more hexagons.
This means that a solution has $4(\Delta_{n + 1} + \Delta_{n} - 3) = 4((n + 1)^2 - 3)$ hexagons.

:::: {layout-ncol="2"}
![
  Top rows: face figures as triangular numbers.<br>
  Bottom row: vertex figures, same.
](./edge_solution_triangles.png)

::: {}

| Parameter               | $F_6$ |  V  |  E  |
|-------------------------|-------|-----|-----|
| (1, 0)                  | 4     |  28 | 42  |
| (2, 0)                  | 24    |  68 | 102 |
| (3, 0)                  | 52    | 124 | 186 |
| (4, 0)                  | 88    | 196 | 294 |
| (5, 0)                  | 132   | 284 | 426 |

:::
::::


### Whirled Solutions

In the above solutions, we never had to turn to complete our paths.
This may leave one wondering whether the parameters are written as 2-tuples to match the other tables,
  or if we can truly create solutions that incorporate turns.

One of the assumptions we made when building face figures was that there was
  an even triangular number of hexagons, with a pentagon at the center of the edges of the figure.
But the pentagons could easily border any of the other hexagons, as long as the figure had triangular symmetry.

![
  Figure with offset pentagons surrounding $\Delta_3$ hexagons.
](./edge_whirl_paths.png){.image-wide}

As shown on the above diagram, we get a figure on the faces which is similar to Class III Goldberg sectors.
This is reinforced by showing the "whirled" (2, 1) path.
Just as before (1, 2) path is also possible on this figure, if the path is taken counterclockwise.

We can indeed assemble these figures into a solution:

::: {layout-ncol="2"}
![
  Solution on tetrahedral net.
  Identical points at the edges of the figure are identified by exterior dotted lines.
](./edge_whirl_net.png)

![
  Equivalent planar graph, after recoloring. External face is colored blue.
](./edge_whirl_planar.png)
:::

Similarly to the (3, 0) solution, the face and vertex figures in the recoloring are hexagons and triangles.
However, their roles have swapped; this time, the faces are the former and the vertices are the latter.
This yields $4(7 + 3) = 40$ hexagons in total,
  which coincides with the tetrahedral antitruncation (3, 3) from earlier.

I suspect that this can be generalized, but I have yet to prove this construction works consistently.


### What about Class II?

A parallel to Class II Goldberg solution likely does *not* exist.
For both arms of the path to be equal, the hexagon we turn on must be at the center of a face.
The center of the face is equidistant from the midpoints of edges and from the vertices making it up.
The former case is the Class I solutions, which have no turn.
The latter case is impossible, because the pentagons must be placed along an edge.


Double-Goldberg
---------------

Every one of these solution figures, both constructed and otherwise,
  can be extended using one of the previously-discussed Goldberg-Coxeter Conway operators
  ($dk$, $tk$, $c_n = du_nd$, and $w$) to create another solution while preserving tetrahedral symmetry.
Some of the easily-constructible solutions based on Goldberg polyhedra are accumulated in the table below.

```{python}
#| label: tbl-double-goldberg
#| tbl-colwidths: [20, 15, 10, 10, 10, 35]
#| classes: plain

@dataclass
class DoubleTetrahedralSolution:
    parameter: str
    conway: str
    hexagon_count: str
    vertex_count: str
    edge_count: str
    paths: str


double_tet_anti_rows = [
    DoubleTetrahedralSolution(
        parameter=f"{operator}{parameter}",
        hexagon_count=str(polyhedron.face_count - 12),
        vertex_count=str(polyhedron.vertex_count),
        edge_count=str(polyhedron.edge_count),
        conway=(
            double_goldberg.conway
            if double_goldberg.conway.find("*") == 0
            else link_polyhedronisme(
                display_conway(double_goldberg.conway),
                double_goldberg.conway_recipe,
            )
        ),
        paths=(
            f"$\\textcolor{{red}}{{{
                double_goldberg.cluster_path
            }}}, \\textcolor{{blue}}{{{', '.join(
                map(str, double_goldberg.intercluster_paths)
            )}}}$"
        )
    )
    for operator, double_goldbergs in double_goldberg_antitruncations.items()
    for parameter, double_goldberg in double_goldbergs.items()
    for polyhedron in (
        hexagons_to_polyhedron(
            loeschian_norm(*goldberg_operators_to_parameters[operator])
            * (count_tetrahedral(*parameter) + 10) - 10
        ),
    )
]


double_tet_anti_headers = DoubleTetrahedralSolution(
    parameter="(Tetrahedral Goldberg) Parameter",
    conway="Conway",
    hexagon_count="$F_6$",
    edge_count="E",
    vertex_count="V",
    paths="Paths",
)


Markdown(tabulate(
    {
        field: [name] + [getattr(item, field) for item in double_tet_anti_rows]
        for field, name in asdict(double_tet_anti_headers).items()
    },
    headers="firstrow",
    numalign="left",
))
```

The same operators can also be applied to the edge-based cases,
  but since I have not computationally generated these, I will not attempt to tabulate them.
Doing so would require that I:

1.  Formalize the construction of the graph,
    preferably by writing a program which can identify identical vertices.

    - I did this step manually to sketch the figures

2.  Find good planar and spherical embeddings of the graph.

3.  (Optionally,) import and display the result in a polyhedron viewer,
    preferably one which can apply Conway notation to an arbitrary figure


Closing
-------

Tetrahedral solutions are vastly more complicated since we not restricted to
  corresponding pentagons with faces on a dodecahedron,
In decreasing the amount of symmetry, the amount of free parameters increases.
Pentagons are no longer regular, any(?) arrangement with thrice-rotational symmetry per face is valid,
  and I am unsure whether the resultant polyhedra can even be made equilateral.

Despite claiming existence of these tetrahedral solutions topologically,
  actual geometric construction of some is difficult.
In fact, I made an error while constructing one of the edge-based solutions:

![&#32;](./edge_whirl_net_bad.png){.image-wide}

The face in the center has been replaced with its chiral opposite.
You can check this by trying to consistently follow the path (2, 1) --
  along the center face, you need to follow (1, 2) instead.

As you may be able to guess, not even specifying tetrahedral symmetry is enough
  to completely classify every solution.
The [next post](../3) will discuss additional solutions, some of whose members *cannot*
  be constructed using common seed polyhedra.

Polyhedron images were generated using [*polyHédronisme*](https://levskaya.github.io/polyhedronisme/).
Nets and graphs were created with GeoGebra.
