# Objective

Given a vertex figure consisting of regular convex polygons, determine whether it represents a convex uniform polyhedron.

# What is a uniform polyhedron?

A uniform polyhedron is a polyhedron whose faces are regular polygons, while having the same vertex figure for each vertices. Generally a uniform polyhedron can be nonconvex, but only convex polyhedra will be considered in this challenge. (More precisely, the polyhedron is required to be vertex-transitive, but that's just another detail.)

# What is a vertex figure?

In the context of a convex uniform polyhedron, a vertex figure is a list of the number of edges of polygons (in order) around a vertex. For example, a cube has vertex figure of (4.4.4).

# Truthy inputs

(3.3.3) – Tetrahedron
(4.4.4) – Cube
(3.3.3.3) – Octahedron
(5.5.5) – Dodecahedron
(3.3.3.3.3) – Icosahedron
(4.4.N) for every N≥3 – N-gonal prism (It is a cube for N=4)
(3.3.3.N) for every N≥4 – N-gonal antiprism (It is an octahedron for N=3)
(3.6.6) – Truncated tetrahedron
(3.4.3.4) – Cuboctahedron
(3.8.8) – Truncated cube
(4.6.6) – Truncated octahedron
(3.4.4.4) – Rhombicuboctahedron
(4.6.8) – Truncated cuboctahedron
(3.3.3.3.4) – Snub cube
(3.5.3.5) – Icosidodecahedron
(3.10.10) – Truncated dodecahedron
(5.6.6) – Truncated icosahedron
(3.4.5.4) – Rhombicosidodecahedron
(4.6.10) – Truncated icosidodecahedron
(3.3.3.3.5) – Snub dodecahedron

Rotations and reversions (generally, all dihedral permutations) of these lists are also truthy. For example, (4.6.8), (4.8.6), (6.4.8), (6.8.4), (8.4.6), (8.6.4) are all truthy.

# Falsy examples

(3.3.3.3.3.3) – Triangular tiling; not a polyhedron.
(5.5.5.5) – Order-4 pentagonal (hyperbolic) tiling; not a polyhedron.
(3.3.4.4) – Cannot be uniform. Note that this is different from (3.4.3.4).

# Don't care situations

An input is expected to have at least 3 entries, and to consist of integers that are at least 3. Otherwise, the challenge falls in don't care situation.

(5/2.5/2.5/2) – Great stellated dodecahedron; not convex.
(3.3) – Triangular dihedron; not Euclidean.
(2.2.2) – Triangular hosohedron; not Euclidean.
(1)
(-3)
()

• As I understand it, the Kepler-Poinsot polyhedra and uniform star polyhedra all have non-integer entries in the vertex figure, so they are not included, and the truthy inputs shown are all truthy inputs possible. Is this correct? – fireflame241 Jul 19 at 2:07
• @fireflame241 Yes. – Dannyu NDos Jul 19 at 3:28

# Jelly,  54  51 bytes

2×þ5o6R¤
“EḶ¤ẊƓW4mð,’b6ṣ5ịþ¢Ẏṙ€Ƭ1Ẏ;U$e@ ṢṖ’Ḍe“!ṛ‘ȯÇ  A dyadic Link accepting a list of integers (each greater than two) which yields 1 if that list is a vertex figure which represents a uniform polyhedron, or 0 otherwise. Try it online! Or see the test-suite. ### How? First, check if the input is any rotation or reflection of either 4,4,N or 3,3,3,N (using ṢṖ’Ḍe“!ṛ‘) - the prisms or antiprisms. If not, build a table containing all the other un-permuted, possibilities - the Platonic and Archimedean solids. Then get all dihedral-permutations of that table's values (Ẏṙ€Ƭ1Ẏ;U$) and then check for the existence of the input (e@).

Note: The table actually built includes two redundant rows containing only lists which either contain some value(s) less than 3 or are of the form 4,4,N in some rotation.

To build the table an outer-product using 1-based indexing is made between "items" vectors (of the form r,2r,3,4,5,6, where r is the row) and "indexes" vectors.

  | items        | indexes
--+--------------+----------------------------------------------------------------
r | r,2r,3,4,5,6 | 1,1,1 | 3, 2, 2 | 3,1,3,1 | 1,0,0 | 3,4,1,4 | 4,0,2 | 3,3,3,3,1
--+--------------×-------+---------+---------+-------+---------+-------+----------
1 | 1, 2,3,4,5,6 | 1,1,1 | 3, 2, 2 | 3,1,3,1 | 1,6,6 | 3,4,1,4 | 4,6,2 | 3,3,3,3,1
2 | 2, 4,3,4,5,6 | 2,2,2 | 3, 4, 4 | 3,2,3,2 | 2,6,6 | 3,4,2,4 | 4,6,4 | 3,3,3,3,2
3 | 3, 6,3,4,5,6 | 3,3,3 | 3, 6, 6 | 3,3,3,3 | 3,6,6 | 3,4,3,4 | 4,6,6 | 3,3,3,3,3
4 | 4, 8,3,4,5,6 | 4,4,4 | 3, 8, 8 | 3,4,3,4 | 4,6,6 | 3,4,4,4 | 4,6,8 | 3,3,3,3,4
5 | 5,10,3,4,5,6 | 5,5,5 | 3,10,10 | 3,5,3,5 | 5,6,6 | 3,4,5,4 | 4,6,T | 3,3,3,3,5


The "indexes" vectors are encoded as a single base-6 integer which is split at its 5 digits (see the start of Link 2).

2×þ5o6R¤ - Link 1, Get the five "items vectors": no arguments
2        - two
5     - five
þ      - (implicit [1..2]) table (implicit [1..5]) using:
×       -   multiplication  -> [[1,2],[2,4],[3,6],[4,8],[5,10]]
6R¤ - range of six -> [1,2,3,4,5,6]
o    - logical OR (vectorises) -> [[1,2,3,4,5,6],[2,4,3,4,5,6],[3,6,3,4,5,6],[4,8,3,4,5,6],[5,10,3,4,5,6]]

“EḶ¤ẊƓW4mð,’b6ṣ5ịþ¢Ẏṙ€Ƭ1Ẏ;U$e@ - Link 2, Platonic or Achimedian?: list of integers (>2), V “EḶ¤ẊƓW4mð,’ - base 250 number = 269760427146828960006295 b6 - in base 6 = [1,1,1,5,3,2,2,5,3,1,3,1,5,1,0,0,5,3,4,1,4,5,4,0,2,5,3,3,3,3,1] ṣ5 - split at fives = [[1,1,1],[3,2,2],[3,1,3,1],[1,0,0],[3,4,1,4],[4,0,2],[3,3,3,3,1]] ¢ - call Link 1 as a nilad = [[1,2,3,4,5,6],[2,4,3,4,5,6],[3,6,3,4,5,6],[4,8,3,4,5,6],[5,10,3,4,5,6]] þ - table using: ị - index into -> the 5 by 7 table shown above Ẏ - tighten (to a list of the unpermuted lists) Ƭ - collect up until repetition applying: ṙ€ 1 - rotate each left one place Ẏ - tighten (to a list of all the rotations)$   - last two links as a monad:
U    -   upend (reverse each list)
;     -   concatenate (to the forward ones)
e@ - does (the input, V) exist in that list of lists?

ṢṖ’Ḍe“!ṛ‘ȯÇ - Main Link: list of integers (each >2), V
Ṣ           - sort V
Ṗ          - remove the rightmost (maximal)
’         - decrement (each)
Ḍ        - convert from base ten
“!ṛ‘   - list of code page indices = [33,222]
e       - exists in? (i.e. was V some rotation of [4,4,n] or [3,3,3,n]?)
ȯ  - logical OR


# Python 3, 190 bytes

def f(F):s="".join(hex(k)for k in F);F[1:]in[[4,4],*3]or{s,s[::-1]}&{*"555 333 366 388 3aa 466 566 468 46a 3434 3444 3454 3535 33333 33334 33335".split()}and max(F)<16or f(F[1:]+F[:1])


Try it online!

Takes input as a list of integers representing the vertex figure. The function errors (RecursionError) if the vertex figure is not a uniform polyhedron, otherwise there is no error.

I tried several schemes of organizing the finite classes into a smart way that takes advantage of patterns, but hardcoding all possibilities reigned superior since it is a relatively small set.

### Explanation

def f(F):
# F is a rotation of the input vertex figure; initially is the input vertex figure
# Convert to string for easier comparison later in the code
s="".join(hex(k)for k in F)
# Test true if the permutation is N.4.4.4 or N.3.3.3
(F[1:]in[[4,4],*3]or
# Test truthy if permutation (or its reverse) is in
#   3.3.3, 3.6.6, 3.8.8, 3.10.10, 4.6.6, 5.6.6, 4.6.8, 4.6.10,
#   3.3.3.N, 3.4.3.4, 3.4.4.4, 3.4.5.4, 3.5.3.5
#   3.3.3.3.3, 3.3.3.3.4, 3.3.3.3.5
{s,s[::-1]}&{*"555 333 366 388 3aa 466 566 468 46a 3434 3444 3454 3535 33333 33334 33335".split()}
# Numbers greater than 15 would convert into the most-significant hexit when converted to a string,
# causing 0x43 to match the same as 0x4,
# so we need to check that none of this happened if we want a bugfree string search
and max(F)<16
# If we tested truthy, then terminate
# Otherwise, recurse with the vertex figure cyclically rotated left one
or f(F[1:]+F[:1]))


# Retina, 142 bytes

$,$",
^\G\d+,
$& %L$,
$'$>
N^$.+,(.+),$1
N
^(3,(3,3(,(\d+|3,[3-5]))?|4,([3-5],)?4|5,3,5|(6|8|10),\6)|4,4,\d+|4,6,(6|8|10)|5,(5|6),\8),¶


Try it online! Link includes test cases. Explanation:

$,$",


Duplicate the list and suffix a comma to each copy.

^\G\d+,
$&  Reverse the first copy of the list. %L$,
$'$>


Generate all rotations of both the list and its reverse.

N^$.+,(.+),$1


Sort the last number in descending order.

N


Sort in ascending numeric order. (For the truthy cases, these two sorts ensure that the resulting first list is also the first list in list order.)

^(...),¶


Ensure the first list matches one of the truthy cases:

3,(3,3(,(\d+|3,[3-5]))?|4,([3-5],)?4|5,3,5|(6|8|10),\6)


Handle those cases with a 3: 3,3,3, 3,3,3,N (N>=3), 3,3,3,3,3, 3,3,3,3,4, 3,3,3,3,5, 3,4,4 (this is 4,4,N with N=3 of course), 3,4,3,4, 3,4,4,4, 3,4,5,4, 3,5,3,5, 3,6,6, 3,8,8, and 3,10,10.

|4,4,\d+|4,6,(6|8|10)|5,(5|6),\8


Handle 4,4,N (N>=4), 4,6,6, 4,6,8, 4,6,10, 5,5,5 and 5,5,6.

# 05AB1E, 68 61 bytes

Ž‚ÃS2äI{¨.å•3É≠ÞÌδ)Ö“JhG•твŽ6ð9ǝ11Ž
¤š«.¥Ƶ_+ε5L._Dí«}˜€S>I.å~


Input as a list of integers.

Explanation:

Hard-coded approach.

Step 1: Check if the input is of the type 3.3.3.N or 4.4.N:

Ž‚Ã         # Push compressed integer 33344
S        # Split it into a list of digits: [3,3,3,4,4]
2ä      # Try to split it into 2 equal-sized parts: [[3,3,3],[4,4]]
I     # Push the input-list
{    # Sort it from lowest to highest
¨   # Remove the last/highest item
.å # Check if this modified input-list is in the [[3,3,3],[4,4]] list of lists


Step 2: Check if the input is in the hard-coded list of truthy polyhedrons including their rotations and reflections (minus the 4.4.4 and 3.3.3.3, which are already covered by the 3.3.3.N and 4.4.N check):

•3É≠ÞÌδ)Ö“JhG•
# Push compressed integer 1122222256020285110099101081
тв         # Convert it to base-100 as list:
#  [11,22,22,22,56,2,2,85,11,0,99,10,10,81]
Ž6ð         # Push compressed integer 1769
9ǝ       # Insert it at index 9:
#  [11,22,22,22,56,2,2,85,11,1760,99,10,10,81]
11          # Push 11
Ž\n¤      # Push compressed integer 19798
š     # Convert the 11 to a list [1,1] and prepend the 19798: [19798,1,1]
«    # Merge it to the other list:
#  [11,22,22,22,56,2,2,85,11,1769,99,10,10,81,19798,1,1]
.¥          # Undelta it:
#  [0,11,33,55,77,133,135,137,222,233,2002,2101,2111,2121,2202,22000,22001,22002]
Ƶ_        # Push compressed integer 222
+       # Add it to each value:
#  [222,233,255,277,299,355,357,359,444,455,2224,2323,2333,2343,2424,22222,22223,22224]
ε          # Map each value to:
5L        #  Push list [1,2,3,4,5]
._      #  Rotate the current integer that many times towards the left:
#   i.e. acbde → [bcdea,cdeab,deabc,eabcd,abcde]
#   i.e. abc → [bca,cab,abc,bca,cab]
D     #  Duplicate that list
í    #  Reverse each inner integer
#   i.e. → [aedbc,caedb,bcaed,dbcae,edbca]
#   i.e. → [acb,bac,cba,acb,bac]
«   #  Merge the two lists together
}˜         # After the map: flatten the list of lists
€S       # Split each integer into a list of digits
>      # Increase each by 1
I.å   # Check if the input-list is in this list of lists


Step 3: Check if either of the two checks is truthy, and output the result:

~           # Bitwise-OR to check if either of the two is truthy
# (after which the result is output implicitly)


See this 05AB1E tip of mine (sections How to compress large integers? and How to compress integer lists?) to understand why Ž‚Ã is 33344; •3É≠ÞÌδ)Ö“JhG• is 1122222256020285110099101081; •3É≠ÞÌδ)Ö“JhG•тв is [11,22,22,22,56,2,2,85,11,0,99,10,10,81]; Ž6ð is 1769; Ž\n¤ is 19798; and Ƶ_ is 222.