Ask Your Question

Revision history [back]

Useful tools that can help achieve the goal here are

  • the cartesian product iterator
  • using a dictionary
  • getting an item in a string by its index
  • the randint function to pick said index at random

Define $E$ and an empty dictionary $d$:

sage: E = {3, 5, 7}
sage: d = dict()

For each element $u$ in the cartesian product $E^3$,

  • if its two cyclic permutations have already been assigned a letter,
    • if they turn out to be the same letter, then assign it to $u$ too,
    • otherwise assign the remaining letter,
  • otherwise assign a letter at random.

Define a function to assign letters to tuples in $E^3$:

def abc(E):
    r"""
    Return a dictionary of letters assigned to elements in `E^3`.

    Each triple `(x, y, z)` in `E^3` is assigned a letter among
    'a', 'b', 'c', in a way that if `(x, y, z)` and `(y, z, x)` are
    assigned the same values then so is `(z, x, y)`.
    """
    d = dict()
    for u in cartesian_product_iterator((E, E, E)):
        x, y, z = u
        v = y, z, x
        w = z, x, y
        if v in d and w in d:
            if d[v] == d[w]:
                d[u] = d[v]
            else:
                d[u] = 'abc'.replace(d[v], '').replace(d[w], '')
        else:
            d[u] = 'abc'[randint(0, 2)]
    return d

Define a function to check the conditions are satisfied:

def check_cyclic(d):
    return all(len(set([d[(x, y, z)], d[(y, z, x)], d[(z, x, y)]])) in (1, 3)
               for x, y, z in d)

Assign values with the function:

sage: d = abc({3, 5, 7})

Check the conditions are satisfied:

sage: check_cyclic(d)
True

See what values were assigned:

sage: d
{(3, 3, 3): 'c',
 (3, 3, 5): 'a',
 ...
 (3, 7, 7): 'b',
 ...
 (3, 5, 7): 'b',
 ...
 (5, 7, 3): 'b',
 ...
 (7, 3, 5): 'b',
 ...
 (7, 3, 7): 'c',
 ...
 (7, 7, 3): 'a',
 (7, 7, 5): 'b',
 (7, 7, 7): 'a'}

In this case (3, 5, 7), (5, 7, 3) and (7, 3, 5) all got 'b', while (3, 7, 7), (7, 3, 7) and (7, 7, 3) got 'b', 'c', 'a'.

Note: if instead of assigning 'a', 'b', 'c' we assigned 0, 1, 2, we could slightly simplify the function abc as follows:

def abc(E):
    r"""
    Return a dictionary of letters assigned to elements in `E^3`.

    Each triple `(x, y, z)` in `E^3` is assigned a number among
    0, 1, 2, in a way that if `(x, y, z)` and `(y, z, x)` are
    assigned the same values then so is `(z, x, y)`.
    """
    d = dict()
    for u in cartesian_product_iterator((E, E, E)):
        x, y, z = u
        v = y, z, x
        w = z, x, y
        if v in d and w in d:
            if d[v] == d[w]:
                d[u] = d[v]
            else:
                d[u] = 3 - d[u] - d[v]
        else:
            d[u] = randint(0, 2)
    return d

Note: one could save on storage by using less keys in the dictionary, running through triples in $E^3$ only up to cyclic order. Each $(x, y, z)$ would be assigned one of 'aaa', 'bbb', 'ccc', 'abc', 'acb', 'bac', 'bca', 'cab', 'cba', with the understanding that this stores at once the values for $(x, y, z)$, $(y, z, x)$ and $(z, x, y)$. Triples of the form $(x, x, x)$ would always be assigned one of 'aaa', 'bbb', 'ccc'.