public void FinishFaceTurn()
    {
        Debug.Assert(turningFace.HasValue);

        HV[] faceVertices = Hexahedron.VERTICES_BY_FACE[(int)turningFace.Value];

        // Compute new permutation
        VP newPermutation = new VP(vertexPermutation);

        for (int vertexIndex = 0; vertexIndex < faceVertices.Length; vertexIndex++)
        {
            HV source      = faceVertices[vertexIndex];
            HV destination = faceVertices[(vertexIndex + 1) % faceVertices.Length];
            HV target      = vertexPermutationInverse[source];
            newPermutation[target] = destination;
        }

        // Copy into perm and perm inverse
        foreach (HV vertex in System.Enum.GetValues(typeof(HV)))
        {
            vertexPermutation[vertex] = newPermutation[vertex];
            vertexPermutationInverse[newPermutation[vertex]] = vertex;
        }

        AssertPermutationInverseIsValid();

        turningFace = null;
    }
    public RegularHexpressionsController(KMBombInfo bomb, string logPrefix)
    {
        this.logPrefix = logPrefix;

        regexCoords = SampleRegexCoordinates(bomb);
        puzzle      = PuzzleData.SamplePuzzle(
            regexCoords.rowNorth, regexCoords.rowSouth, regexCoords.colWest, regexCoords.colEast);

        Debug.LogFormat("{0} North-west regex '{1}' matches word '{2}'.",
                        logPrefix, puzzle.regexData[0].realStr, puzzle.matchingWords[0]);
        Debug.LogFormat("{0} North-east regex '{1}' matches word '{2}'.",
                        logPrefix, puzzle.regexData[1].realStr, puzzle.matchingWords[1]);
        Debug.LogFormat("{0} South-east regex '{1}' matches word '{2}'.",
                        logPrefix, puzzle.regexData[2].realStr, puzzle.matchingWords[2]);
        Debug.LogFormat("{0} South-west regex '{1}' matches word '{2}'.",
                        logPrefix, puzzle.regexData[3].realStr, puzzle.matchingWords[3]);

        // Assign words to vertices such that at most 2 words are in the correct locations
        string[] wordOrder = puzzle.matchingWords.Concat(puzzle.decoyWords).ToArray();
        int      correctLocations;

        do
        {
            wordOrder.Shuffle();
            correctLocations = CENTER_COLUMN_VERTICES
                               .Where((vertex, i) => wordOrder[(int)vertex] == puzzle.matchingWords[i])
                               .Count();
        } while (correctLocations > 2);
        vertexWords        = new Dictionary <HV, string>(wordOrder.Length);
        vertexLabeledWords = new Dictionary <HV, string>(wordOrder.Length);
        for (int i = 0; i < wordOrder.Length; i++)
        {
            HV vertex = (HV)i;
            vertexWords[vertex]        = wordOrder[i];
            vertexLabeledWords[vertex] = string.Format("({0} {1})", VERTEX_LABELS[vertex], wordOrder[i]);
        }
        Debug.LogFormat("{0} Vertex labels and words: {1}",
                        logPrefix,
                        vertexLabeledWords.Select(pair => pair.Value).Join(" "));

        // Both permutation and inverse are identity
        vertexPermutation = new VP();
        foreach (HV vertex in System.Enum.GetValues(typeof(HV)))
        {
            vertexPermutation[vertex] = vertex;
        }
        vertexPermutationInverse = new VP(vertexPermutation);
        AssertPermutationInverseIsValid();

        isSolved    = false;
        turningFace = null;
    }
    public string GetTopWord()
    {
        HV topVertex = vertexPermutationInverse[0];

        return(vertexWords[topVertex]);
    }