From bbf141785ea709370f9fac5637e1482a64a26c61 Mon Sep 17 00:00:00 2001 From: queue-miscreant Date: Sun, 23 Mar 2025 22:05:24 -0500 Subject: [PATCH] refactor pentagons.3 --- posts/pentagons/2/index.qmd | 2 - posts/pentagons/3/goldberg | 1 + posts/pentagons/3/index.qmd | 584 +++++++++++++++------------------- posts/pentagons/_metadata.yml | 25 ++ 4 files changed, 286 insertions(+), 326 deletions(-) create mode 120000 posts/pentagons/3/goldberg create mode 100644 posts/pentagons/_metadata.yml 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"} [ ![ One-third of the figure, showing a group of four pentagons.
@@ -506,11 +439,11 @@ The symmetry inherited by this figure is also dihedral of degree 3, but centered ](./frustum_third.png){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} ![ Base case 1: truncated pentagonal gyro-pyramid ](./polyhedronisme-K300t5K30gY5.png){.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} ![ Base case 2: truncated hexagonal gyro-pyramid -](./polyhedronisme-K300t6K30gY6.png){.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]]"} -Conway wC + +Conway wC + -Tearoom layout + +Tearoom layout + ::: 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} ![](./tatami_graph.png){.image-wide} ![](./regularized_tatami_graph.png){.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