diff --git a/posts/pentagons/2/index.qmd b/posts/pentagons/2/index.qmd
index 19a4557..8be6eaa 100644
--- a/posts/pentagons/2/index.qmd
+++ b/posts/pentagons/2/index.qmd
@@ -33,8 +33,6 @@ import matplotlib.pyplot as plt
from tabulate import tabulate
from goldberg.common import (
- GoldbergData,
- GoldbergOperator,
hexagons_to_polyhedron,
group_dict,
link_polyhedronisme,
diff --git a/posts/pentagons/3/goldberg b/posts/pentagons/3/goldberg
new file mode 120000
index 0000000..8089557
--- /dev/null
+++ b/posts/pentagons/3/goldberg
@@ -0,0 +1 @@
+../1/goldberg
\ No newline at end of file
diff --git a/posts/pentagons/3/index.qmd b/posts/pentagons/3/index.qmd
index c1e6993..c259d1f 100644
--- a/posts/pentagons/3/index.qmd
+++ b/posts/pentagons/3/index.qmd
@@ -12,27 +12,11 @@ categories:
- geometry
- combinatorics
- symmetry
-# Get rid of the figure label
-crossref:
- fig-title: ""
- fig-labels: " "
- tbl-title: ""
- tbl-labels: " "
- title-delim: ""
- custom:
- - key: fig
- kind: float
- reference-prefix: Figure
- space-before-numbering: false
- - key: tbl
- kind: float
- reference-prefix: Table
- space-before-numbering: false
---
```{python}
-#| echo: false
-from dataclasses import dataclass
+from dataclasses import dataclass, asdict
import itertools
from typing import Callable, TypeAlias
@@ -52,28 +35,91 @@ from IPython.display import Markdown
import sympy
from tabulate import tabulate
-@dataclass
-class PolyData:
- hexagon_count: int
- vertex_count: int
- edge_count: int
+from goldberg.common import (
+ hexagons_to_polyhedron,
+ group_dict,
+ link_polyhedronisme,
+)
+from goldberg.operators import (
+ t_param,
+ GoldbergOperator,
+ goldberg_operators,
+ goldberg_operators_to_parameters,
+ loeschian_numbers,
+ loeschian_norm,
+)
- @classmethod
- def from_hexagons(cls, hexagon_count: int):
- return cls(
- hexagon_count=hexagon_count,
- vertex_count=2*hexagon_count + 20,
- edge_count=3*hexagon_count + 30,
+n_param, aux_t_param, temp_param = sympy.symbols("n T' x")
+from_base_case = lambda x: (t_param * (x + 10) - 10)
+
+@dataclass
+class MiniConwayTable:
+ conway: str
+ hexagon_count: str
+ vertex_count: str
+ edge_count: str
+
+as_maybe_tex = lambda x: x if isinstance(x, int) or not x.has_free(t_param) else f"${sympy.latex(x)}$"
+as_maybe_recipe_link = lambda x, recipe: x if recipe is None else link_polyhedronisme(x, recipe)
+
+def display_mini_conway_table(
+ base_case_hexagons: int,
+ base_case_name: str,
+ recipes: dict[str, str] = {},
+) -> Markdown:
+ headers = MiniConwayTable(
+ "Conway",
+ "$F_6$",
+ "V",
+ "E",
)
+ rows = [
+ MiniConwayTable(
+ conway=recipe,
+ hexagon_count=str(as_maybe_tex(polyhedron.face_count - 12)),
+ vertex_count=str(as_maybe_tex(polyhedron.vertex_count)),
+ edge_count=str(as_maybe_tex(polyhedron.edge_count)),
+ )
+ # base row list
+ for operator in ["", "dk", "c", "w", "tk", "g_T"]
+ # try lookup (a, b) tuple in parameter dict
+ for maybe_parameter in (goldberg_operators_to_parameters.get(operator),)
+ # combinatorially construct polyhedron from the base case and (maybe) the parameter
+ for polyhedron in (
+ (
+ hexagons_to_polyhedron(base_case_hexagons)
+ if operator == ""
+ else hexagons_to_polyhedron(
+ from_base_case(base_case_hexagons).expand().subs(
+ # if the lookup failed, leave the T parameter free
+ t_param,
+ loeschian_norm(*maybe_parameter)
+ if maybe_parameter is not None
+ else t_param
+ )
+ )
+ ),
+ )
+ # pull the recipe from the `recipes` dict
+ for recipe in (
+ as_maybe_recipe_link(
+ f"${operator + base_case_name.split(' ')[-1]}$"
+ if operator == ""
+ else f"${base_case_name}$",
+ recipes.get(operator),
+ ),
+ )
+ ]
-@dataclass
-class GoldbergData:
- parameter: tuple[int, int]
- conway: str
-
- parameter_link: str | None = None
- conway_recipe: str | None = None
+ return Markdown(tabulate(
+ {
+ field: [name] + [getattr(item, field) for item in rows]
+ for field, name in asdict(headers).items()
+ },
+ headers="firstrow",
+ numalign="left",
+ ))
```
@@ -91,59 +137,79 @@ Yet more unconventional solutions are presented below.
Combinatorics of Goldberg-Coxeter Operators
-------------------------------------------
+In the first post, we established that a solution figure *S* has feature counts
+ which are parametrized entirely by $F_6$:
+
+$$
+S = \begin{pmatrix} v \\ e \\ f \end{pmatrix}
+ = \begin{pmatrix}
+ 2F_6 + 20 \\
+ 3F_6 + 30 \\
+ F_6 + 12
+ \end{pmatrix}
+ = \begin{pmatrix} 2 \\ 3 \\ 1 \end{pmatrix} F_6
+ + \begin{pmatrix} 20 \\ 30 \\ 12 \end{pmatrix}
+$$
+
In the last post, it was discovered that certain solutions cannot be created easily from seed polyhedra
in a polyhedron viewer.
This prompts the question of how to calculate the vertex, edge, and face counts
without acquiring them from the output of such a program.
-
-Each of the simple GC operators (*c*, *dk*, and *w*) has a combinatoric matrix form
- which can be applied to a vector of the vertex, edge, and face counts of a figure *S*.
+Fortunatelly, each of the simple GC operators (*dk*, *c*, and *w*) has a combinatoric matrix form[^1].
$$
-\begin{gather*}
- S = \begin{pmatrix} v \\ e \\ f \end{pmatrix}
- = \begin{pmatrix}
- 2F_6 + 20 \\
- 3F_6 + 30 \\
- F_6 + 12
- \end{pmatrix}
- = \begin{pmatrix} 2 \\ 3 \\ 1 \end{pmatrix} F_6
- + \begin{pmatrix} 20 \\ 30 \\ 12 \end{pmatrix} \\
- \underset{
- \text{Class I}
- }{
- c = \begin{pmatrix}
- 1 & 2 & 0 \\
- 0 & 4 & 0 \\
- 0 & 1 & 1
- \end{pmatrix}
- } \quad
- \underset{
- \text{Class II}
- }{
- dk = \begin{pmatrix}
- 0 & 2 & 0 \\
- 0 & 3 & 0 \\
- 1 & 0 & 1
- \end{pmatrix}
- } \quad
- \underset{
- \text{Class III}
- }{
- w = \begin{pmatrix}
- 1 & 4 & 0 \\
- 0 & 7 & 0 \\
- 0 & 2 & 1
- \end{pmatrix}
- }
-\end{gather*}
+\underset{
+ \text{Class I}
+}{
+ c = \begin{pmatrix}
+ 1 & 2 & 0 \\
+ 0 & 4 & 0 \\
+ 0 & 1 & 1
+ \end{pmatrix}
+} \quad
+\underset{
+ \text{Class II}
+}{
+ dk = \begin{pmatrix}
+ 0 & 2 & 0 \\
+ 0 & 3 & 0 \\
+ 1 & 0 & 1
+ \end{pmatrix}
+} \quad
+\underset{
+ \text{Class III}
+}{
+ w = \begin{pmatrix}
+ 1 & 4 & 0 \\
+ 0 & 7 & 0 \\
+ 0 & 2 & 1
+ \end{pmatrix}
+}
$$
+[^1]:
+ These matrices can be derived by closely observing the vertex, edge, and face counts of a figure before
+ and after applying the operator.
+ Gather the feature counts of the tetrahedron, dodecahedron, and icosahedron into a matrix.
+
+ $$
+ \begin{gather*}
+ f \begin{pmatrix} | & | & | \\ T & D & I \\ | & | & | \end{pmatrix}
+ = f \begin{pmatrix} 4 & 20 & 12 \\ 6 & 30 & 30 \\ 4 & 12 & 20 \end{pmatrix}
+ = \begin{pmatrix} | & | & | \\ fT & fD & fI \\ | & | & | \end{pmatrix} \\
+ f = \begin{pmatrix} | & | & | \\ fT & fD & fI \\ | & | & | \end{pmatrix}
+ \begin{pmatrix} 4 & 20 & 12 \\ 6 & 30 & 30 \\ 4 & 12 & 20 \end{pmatrix}^{-1}
+ \end{gather*}
+ $$
+
+ This matrix is invertible, and the feature counts for *fT*, *fD*, and *fI* can be acquired from a viewer
+ implementing the operator *f*.
+
These operators are labelled with the classes of Goldberg polyhedra they construct
when applied to the dodecahedron.
-- *cD* = GC(2, 0)
- *dkD* = *tI* = GC(1, 1)
+- *cD* = GC(2, 0)
- *wD* = GC(2, 1)
It's worth noting again that *dk* alternates between producing Class I and Class II solutions.
@@ -156,83 +222,41 @@ Unlike it, it preserves solution class.
Powers of a matrix are more readily expressed when the matrix is diagonalized.
Diagonalizing each of these operators shows that they have something in common.
-$$
-\begin{align*}
- c &= \begin{pmatrix}
- 1 & 2 & 0 \\
- 0 & 4 & 0 \\
- 0 & 1 & 1
- \end{pmatrix}
- = \textcolor{red}{
- \begin{pmatrix}
- -1 & 0 & 2 \\
- 0 & 0 & 3 \\
- 1 & 1 & 1
- \end{pmatrix}
- }
- \begin{pmatrix}
- 1 & 0 & 0 \\
- 0 & 1 & 0 \\
- 0 & 0 & 4
- \end{pmatrix}
- \textcolor{blue}{
- \begin{pmatrix}
- 1 & -2/3 & 0 \\
- 1 & -1 & 1 \\
- 0 & 1/3 & 0
- \end{pmatrix}
- } \\
- dk &= \begin{pmatrix}
- 0 & 2 & 0 \\
- 0 & 3 & 0 \\
- 1 & 0 & 1
- \end{pmatrix}
- = \textcolor{red}{
- \begin{pmatrix}
- -1 & 0 & 2 \\
- 0 & 0 & 3 \\
- 1 & 1 & 1
- \end{pmatrix}
- }
- \begin{pmatrix}
- 0 & 0 & 0 \\
- 0 & 1 & 0 \\
- 0 & 0 & 3
- \end{pmatrix}
- \textcolor{blue}{
- \begin{pmatrix}
- 1 & -2/3 & 0 \\
- 1 & -1 & 1 \\
- 0 & 1/3 & 0
- \end{pmatrix}
- }
- \\
- w &= \begin{pmatrix}
- 1 & 4 & 0 \\
- 0 & 7 & 0 \\
- 0 & 2 & 1
- \end{pmatrix}
- = \textcolor{red}{
- \begin{pmatrix}
- -1 & 0 & 2 \\
- 0 & 0 & 3 \\
- 1 & 1 & 1
- \end{pmatrix}
- }
- \begin{pmatrix}
- 1 & 0 & 0 \\
- 0 & 1 & 0 \\
- 0 & 0 & 7
- \end{pmatrix}
- \textcolor{blue}{
- \begin{pmatrix}
- 1 & -2/3 & 0 \\
- 1 & -1 & 1 \\
- 0 & 1/3 & 0
- \end{pmatrix}
- }
-\end{align*}
-$$
+```{python}
+# diagonalizing dk gives an eigenspace which shows the 3V = 2E condition
+# and Euler characteristic more clearly
+eigenspace, _ = goldberg_operators["dk"].diagonalize()
+
+def show_diagonalized(operator: GoldbergOperator):
+ assert operator != "g_T"
+ matrix = goldberg_operators[operator]
+ diag = eigenspace.inv() @ matrix @ eigenspace
+
+ return f"""{
+ sympy.latex(matrix)
+ } = \\textcolor{{red}}{{{
+ sympy.latex(eigenspace)
+ }}}{
+ sympy.latex(diag)
+ }\\textcolor{{blue}}{{{
+ sympy.latex(eigenspace.inv(), fold_short_frac=True)
+ }}}"""
+
+Markdown(f"""
+ $$
+ \\begin{{align*}}
+ dk &= {show_diagonalized("dk")} \\\\
+ c &= {show_diagonalized("c")} \\\\
+ w &= {show_diagonalized("w")}
+ \\end{{align*}}
+ $$
+ """.replace(
+ "\\left[\\begin{matrix}", "\\begin{pmatrix}"
+ ).replace(
+ "\\end{matrix}\\right]", "\\end{pmatrix}"
+ )
+)
+```
All of these operators share the same eigenvectors, which can be seen
in the columns of the left outer matrix and rows of the right outer one.
@@ -243,7 +267,7 @@ Some of these eigenvectors have special interpretations:
- The left eigenvector (1, -1, 1) (right matrix, middle row) always has eigenvalue 1.
- This means that the operation does not change the Euler characteristic.
-- The left eigenvector (3, -2, 0) (right matrix, top row), when applied to general polyhedra
+- The left eigenvector (3, -2, 0) (right matrix, top row), when applied to general polyhedra,
corresponds to the edges and vertices added by the operation:
- In *dk*, this vector has eigenvalue 0, forcing $3V = 2E$, i.e., all vertices to have degree 3.
- In *c* and *w*, this vector has eigenvalue 1. These operators only add degree-3 vertices.
@@ -265,10 +289,10 @@ $$
Call this number $T = \|a + bu\| = a^2 + ab + b^2$.
We know that integers of this form are never congruent to 2 (mod 3).
Conveniently, this matches with the upper-left eigenvalue.
-
Assuming for the sake of argument that this is true, it implies something interesting:
**the GC operators produced from *T* are (combinatorially) closed under composition**.
This captures all powers of a given *T*, as well as products between it and other possible *T*s.
+
However, this combinatorial view misses some of the picture, since some feature counts
can be shared between two different classes at once.
This comes down to the existence of chiral pairs.
@@ -282,53 +306,21 @@ This doesn't affect hexagon counts, so it means we can characterize the possible
$$
\begin{align*}
- g_T S &= \begin{pmatrix}
- -1 & 0 & 2 \\
- 0 & 0 & 3 \\
- 1 & 1 & 1
- \end{pmatrix}
- \begin{pmatrix}
- x & 0 & 0 \\
- 0 & 1 & 0 \\
- 0 & 0 & T
- \end{pmatrix}
- \begin{pmatrix}
- 1 & -{2 \over 3} & 0 \\
- 1 & -1 & 1 \\
- 0 & {1 \over 3} & 0
- \end{pmatrix}
- \begin{pmatrix} v \\ e \\ f \end{pmatrix} \\[8pt]
- &=
- \begin{pmatrix}
- -1 & 0 & 2 \\
- 0 & 0 & 3 \\
- 1 & 1 & 1
- \end{pmatrix}
- \begin{pmatrix}
- x & 0 & 0 \\
- 0 & 1 & 0 \\
- 0 & 0 & T
- \end{pmatrix}
- \begin{pmatrix}
- v - {2 \over 3} e = 0 \\
- v - e + f = 2 \\
- {1 \over 3} e = F_6 + 10
- \end{pmatrix} \\[8pt]
- &=
- \begin{pmatrix}
- -1 & 0 & 2 \\
- 0 & 0 & 3 \\
- 1 & 1 & 1
- \end{pmatrix}
- \begin{pmatrix} 0 \\ 2 \\ T (F_6 + 10) \end{pmatrix} \\
- &=
- \begin{pmatrix} T(2F_6 + 20) \\ T(3F_6 + 30) \\ T(F_6 + 10) + 2 \end{pmatrix} \\[8pt]
+ g_T S &= g_T \left(
+ \begin{pmatrix} 2 \\ 3 \\ 1 \end{pmatrix} F_6
+ + \begin{pmatrix} 20 \\ 30 \\ 10 \end{pmatrix}
+ + \begin{pmatrix} 0 \\ 0 \\ 2 \end{pmatrix}
+ \right) \\
+ &= T \begin{pmatrix} 2 \\ 3 \\ 1 \end{pmatrix} F_6
+ + T \begin{pmatrix} 20 \\ 30 \\ 10 \end{pmatrix}
+ + \begin{pmatrix} 0 \\ 0 \\ 2 \end{pmatrix} \\
+ &= \begin{pmatrix} T(2F_6 + 20) \\ T(3F_6 + 30) \\ T(F_6 + 10) + 2 \end{pmatrix} \\[8pt]
F'_6 &= T(F_6 + 10) - 10
\end{align*}
$$
This demonstrates two things: the initial $F_6$ count from the choice of seed polygon *S* matters,
- and the possible values of *T* can be used to grow this sequence
+ and we can use valid values of *T* to produce a sequence of solutions.
Searching for Other Seeds
@@ -399,72 +391,13 @@ It inherits the dihedral symmetry of degree 3 from the vertices of the dodecahed
](./truncated gyroelongated bipyramid pole.png)
:::
+::: {.column}
```{python}
-#| echo: false
-
-t_param = sympy.symbols("T")
-norm = lambda a, b: a**2 + a*b + b**2
-
-@dataclass
-class GCOperator:
- name: str
- parameter: int | sympy.Symbol
-
-gc_operators = [
- GCOperator("dk", norm(1, 1)),
- GCOperator("c", norm(2, 0)),
- GCOperator("w", norm(2, 1)),
- GCOperator("tk", norm(3, 0)),
- GCOperator("g_T", t_param),
-]
-
-def polyhedronisme(recipe: str) -> str:
- return f"https://levskaya.github.io/polyhedronisme/?recipe={recipe}"
-
-as_maybe_tex = lambda x: x if isinstance(x, int) or not x.has_free(t_param) else f"${sympy.latex(x)}$"
-as_maybe_recipe_link = lambda x, recipe: f"[{x}]({polyhedronisme(recipe)})" if recipe is not None else x
-
-def mini_conway_table(
- base_case_hexagons: int,
- base_case_name: str,
- recipes: dict[str, str] = {},
-) -> list[tuple[str, PolyData]]:
- return [
- (
- as_maybe_recipe_link(f"${base_case_name}$", recipes.get("")),
- PolyData.from_hexagons(base_case_hexagons),
- )
- ] + [
- (
- as_maybe_recipe_link(
- f"${operator.name + base_case_name.split(' ')[-1]}$",
- recipes.get(operator.name),
- ),
- PolyData.from_hexagons((
- t_param * (base_case_hexagons + 10) - 10
- ).expand().subs(t_param, operator.parameter)),
- )
- for operator in gc_operators
- ]
-
-def display_mini_conway_table(
- base_case_hexagons: int,
- base_case_name: str,
- recipes: dict[str, str] = {},
-) -> Markdown:
- return Markdown(tabulate(
- [[
- conway,
- as_maybe_tex(polyhedron.hexagon_count),
- as_maybe_tex(polyhedron.vertex_count),
- as_maybe_tex(polyhedron.edge_count),
- ] for conway, polyhedron in mini_conway_table(base_case_hexagons, base_case_name, recipes)],
- headers=["Conway", "$F_6$", "V", "E"],
- numalign="left",
- ))
+#| classes: plain
display_mini_conway_table(6, "F")
```
+:::
::::
@@ -497,7 +430,7 @@ The pentagons gather in groups of 4 and are separated by three bands of hexagons
The symmetry inherited by this figure is also dihedral of degree 3, but centered about a hexagon,
rather than (a complex of) pentagons.
-:::: {layout-ncol="2" layout-valign="center"}
+::: {layout-ncol="2" layout-valign="center"}
[
{target="_blank_"}
```{python}
-#| echo: false
+#| classes: plain
display_mini_conway_table(8, "F")
```
-::::
+:::
#### Others
@@ -567,18 +500,18 @@ This is a symmetry beyond that of the icosahedron, but exists due to the symmetr
](./polyhedronisme-K300t6dA6.png)
```{python}
-#| echo: false
+#| classes: plain
display_mini_conway_table(
- 2,
- "t_6dA_6 = T_6",
- recipes = {
- "": "K300t6dA6",
- "dk": "dkK300t6dA6",
- "c": "K300cK30t6dA6",
- "w": "K300wK30t6dA6",
- "tk": "K300tkK30t6dA6"
- }
+ 2,
+ "t_6dA_6 = T_6",
+ recipes = {
+ "": "K300t6dA6",
+ "dk": "dkK300t6dA6",
+ "c": "K300cK30t6dA6",
+ "w": "K300wK30t6dA6",
+ "tk": "K300tkK30t6dA6",
+ },
)
```
::::
@@ -608,11 +541,13 @@ The resultant figure has dihedral symmetry of degree 5.
](./petrial expanded dodecahedron.png)
:::
+::: {.column}
```{python}
-#| echo: false
+#| classes: plain
display_mini_conway_table(5, "D_\\pi")
```
+:::
::::
Interestingly, this is also the first solution polyhedron with an odd number of faces.
@@ -632,43 +567,47 @@ Solution polyhedra can be found by examining the pentagonal ($t_5 g Y_5$) and he
The former has dihedral symmetry of degree 5 and the latter has that of degree 6.
:::: {layout-ncol="2" layout-valign="center"}
+::: {.column .slim-column}
{.column .slim-column}
+:::
```{python}
-#| echo: false
+#| classes: plain
display_mini_conway_table(
- 10,
- "t_5gY_5 = G_5",
- recipes = {
- "": "K300t5K30gY5",
- "dk": "dkK300t5K30gY5",
- "c": "K300dudt5K30gY5",
- "w": "K300wK30t5K30gY5",
- "tk": "tkK300t5K30gY5",
- },
+ 10,
+ "t_5gY_5 = G_5",
+ recipes = {
+ "": "K300t5K30gY5",
+ "dk": "dkK300t5K30gY5",
+ "c": "K300dudt5K30gY5",
+ "w": "K300wK30t5K30gY5",
+ "tk": "tkK300t5K30gY5",
+ },
)
```
+::: {.column .slim-column}
{.column .slim-column}
+](./polyhedronisme-K300t6K30gY6.png)
+:::
```{python}
-#| echo: false
+#| classes: plain
display_mini_conway_table(
- 14,
- "t_6gY_6 = G_6",
- recipes = {
- "": "K300t6K30gY6",
- "dk": "dkK300t6K30gY6",
- "c": "K300dudK40t6gY6",
- "w": "K300wK30t6K30gY6",
- "tk": "tkK300t6K30gY6",
- },
+ 14,
+ "t_6gY_6 = G_6",
+ recipes = {
+ "": "K300t6K30gY6",
+ "dk": "dkK300t6K30gY6",
+ "c": "K300dudK40t6gY6",
+ "w": "K300wK30t6K30gY6",
+ "tk": "tkK300t6K30gY6",
+ },
)
```
::::
@@ -718,9 +657,13 @@ In fact, the graph of the whirl operation on the surface of a cube
:::: {#fig-tatami-polyhedron}
::: {layout="[[-1,2,-1,2,-1]]"}
-
+
+
+
-
+
+
+
:::
Images were retrieved from Wikimedia and belong to their respective owners.
@@ -739,14 +682,14 @@ Next to it is an equivalent graph with a regular hexagon as an outer face.
As a 3D figure, it has only three hexagons and degree-3 dihedral symmetry, another odd number.
:::: {layout-ncol="2" layout-valign="center"}
-::: {.column .slim-column}
+::: {.column .slim-column .text-center}
{.image-wide}
{.image-wide}
:::
```{python}
-#| echo: false
+#| classes: plain
display_mini_conway_table(3, "M")
```
@@ -791,10 +734,11 @@ Final Tabulation
The solutions examined have been collected in the table below.
```{python}
-#| echo: false
+#| classes: plain
+#| tbl-cap: "T, T' are members of the sequence 1, 3, 4, 7, 9, 12, 13, 16, 19, 21... ([OEIS A003136](http://oeis.org/A003136))\
+#|
\\\\*: This is the result of a GC operator applied to $2T - 14$, which requires *T* > 7"
TFilter: TypeAlias = Callable[[int], bool] | None
-n_param, t_param, aux_t_param, temp_param = sympy.symbols("n T T' x")
@dataclass
class TotalHexagonRow:
@@ -803,8 +747,6 @@ class TotalHexagonRow:
f6_expression: sympy.Expr
t_filter: TFilter = None
-from_base_case = lambda x: (t_param * (x + 10) - 10)
-
antitruncation = TotalHexagonRow(
symmetry_group="Tetrahedral",
class_name="Tetrahedral Goldberg Antitruncations",
@@ -880,18 +822,10 @@ full_tabulation_rows = [
),
]
-def loeschian():
- """
- Loeschian numbers -- those of the form a^2 + ab + b^2
- See https://oeis.org/A003136
- """
- for a in itertools.count(1):
- for b in range(a + 1):
- yield a*a + a*b + b*b
-
def get_example_counts(expr: sympy.Expr, amount: int, t_filter: TFilter = None):
- t_params = list(itertools.islice(loeschian(), 2*amount))
+ """Build values from the expression in terms of the number of hexagons"""
+ t_params = list(itertools.islice(loeschian_numbers(), 2*amount))
return [
count
@@ -931,18 +865,20 @@ Markdown(tabulate(
))
```
-T, T' are members of the sequence 1, 3, 4, 7, 9, 12, 13, 16, 19, 21... ([OEIS A003136](http://oeis.org/A003136))
-
-\*: This is the result of a GC operator applied to $2T - 14$, which requires *T* > 7
-
-Sorting the entries in this table, we get the following possible hexagon counts:
+Here are a few hexagon counts from the table, sorted in ascending order:
```{python}
-#| echo: false
-
-Markdown(", ".join(list(map(str, sorted(itertools.chain(*[
- get_example_counts(row.f6_expression, 10, row.t_filter) for row in full_tabulation_rows
-]))))[:15]))
+Markdown(
+ ", ".join([
+ str(i)
+ for i in group_dict(
+ itertools.chain(*[
+ get_example_counts(row.f6_expression, 10, row.t_filter)
+ for row in full_tabulation_rows
+ ])
+ ).keys()
+ ][:20]) + "..."
+)
```
However, keep in mind that this list is *not* exhaustive.
diff --git a/posts/pentagons/_metadata.yml b/posts/pentagons/_metadata.yml
new file mode 100644
index 0000000..8c5faf1
--- /dev/null
+++ b/posts/pentagons/_metadata.yml
@@ -0,0 +1,25 @@
+# freeze computational output
+freeze: auto
+
+# Enable banner style title blocks
+title-block-banner: true
+
+execute:
+ echo: false
+
+# Get rid of the figure label
+crossref:
+ fig-title: ""
+ fig-labels: " "
+ tbl-title: ""
+ tbl-labels: " "
+ title-delim: ""
+ custom:
+ - key: fig
+ kind: float
+ reference-prefix: Figure
+ space-before-numbering: false
+ - key: tbl
+ kind: float
+ reference-prefix: Table
+ space-before-numbering: false