示例#1
0
        public static IEnumerable<Coordinate2D[]> GetAlternatingAxisSets(Coordinate2D[] set, int size)
        {
            // Initialize the state used to enumerate the snake set.
            AlternatingAxisState state = new AlternatingAxisState();
            state.Set = set;
            state.SetMap = GetSetMap(set);
            state.N = set.Length;
            state.K = size;
            state.Coordinates = new Coordinate2D[size];

            // Enumerate all the coordinate sets that consist of sequences
            // of alternating vertical and horizonal turns.
            foreach (Coordinate2D coord in state.Set)
            {
                state.Coordinates[0] = coord;
                state.Index = 1;

                // Enumerate sets that start with a vertical turn.
                foreach (Coordinate2D[] coords in GetAlternatingAxisSets(state, Axis.Vertical))
                {
                    yield return coords;
                }

                // Enumerate sets that start with a horizontal turn.
                foreach (Coordinate2D[] coords in GetAlternatingAxisSets(state, Axis.Horizontal))
                {
                    yield return coords;
                }
            }
        }
示例#2
0
 private static bool IsDuplicateAlternatingAxisCoordinate(AlternatingAxisState state)
 {
     // Check whether the last coordinate is
     // a duplicate of one of the others.
     // It takes at least four coordinates
     // before we can have a loop.
     Coordinate2D[] coords = state.Coordinates;
     Coordinate2D coord = coords[state.Index - 1];
     int limit = state.Index - 4;
     for (int i = 0; i < limit; i++)
     {
         if (coords[i] == coord)
         {
             return true;
         }
     }
     return false;
 }
示例#3
0
        private static bool IsDuplicateAlternatingAxisSet(AlternatingAxisState state)
        {
            Coordinate2D[] coords = state.Coordinates;
            Coordinate2D firstCoord = coords[0];
            Coordinate2D lastCoord = coords[state.K - 1];

            // If the first coordinate is after the last, then it's a duplicate.
            if (firstCoord > lastCoord)
            {
                return true;
            }

            // If the first coordinate is adjacent to the last and
            // the axis between them is perpendicular to the first
            // and last turns, then the set is a loop.
            // If the set is a loop, and the first coordinate is not
            // lexicographically the lowest or the loop direction
            // is not to the right, then it's a duplicate.
            if (Coordinate2D.GetOrthogonalDistance(firstCoord, lastCoord) == 1)
            {
                Direction loopDirection = GetDirectionBetween(lastCoord, firstCoord);
                Direction firstDirection = GetDirectionBetween(firstCoord, coords[1]);
                Direction lastDirection = GetDirectionBetween(coords[state.K - 2], lastCoord);
                if (Direction.ArePerpendicular(loopDirection, firstDirection) &&
                    Direction.ArePerpendicular(loopDirection, lastDirection))
                {
                    // Keep the loop set that starts with the most upper-left coordinate and
                    // advance clockwise.
                    if (!IsFirstCoordinateLeast(coords) || firstDirection != Direction.Right)
                    {
                        return true;
                    }
                }
            }

            return false;
        }
示例#4
0
        private static IEnumerable<Coordinate2D[]> GetAlternatingAxisSets(AlternatingAxisState state, Axis axis)
        {
            // Determine the next two coordinates on either side
            // of the specified axis.
            Coordinate2D coord = state.Coordinates[state.Index - 1];
            Coordinate2D coord1;
            Coordinate2D coord2;
            Axis nextAxis;
            if (axis == Axis.Vertical)
            {
                // Check the coordinates above and below this one.
                coord1 = coord + Direction.Up;
                coord2 = coord + Direction.Down;
                nextAxis = Axis.Horizontal;
            }
            else
            {
                // Check the coordinates the the left and right of this one.
                coord1 = coord + Direction.Left;
                coord2 = coord + Direction.Right;
                nextAxis = Axis.Vertical;
            }

            // Pursue both choices.
            ++state.Index;
            for (int i = 0; i < 2; i++)
            {
                // Select the appropriate coordinate for the first or second pass.
                Coordinate2D newCoord = i == 0 ? coord1 : coord2;

                // Check whether this coordinate is in the set.
                if (state.SetMap[newCoord])
                {
                    // Store the new coordinate.
                    state.Coordinates[state.Index - 1] = newCoord;

                    // Ensure we haven't created a loop.
                    if (IsDuplicateAlternatingAxisCoordinate(state))
                    {
                        continue;
                    }

                    // Check whether we have a complete set.
                    if (state.Index == state.K)
                    {
                        // Account for sets that can be
                        // nagivated in a different order.
                        if (!IsDuplicateAlternatingAxisSet(state))
                        {
                            yield return state.Coordinates;
                        }
                    }
                    else
                    {
                        // Otherwise recurse on the opposite axis.
                        foreach (Coordinate2D[] coords in GetAlternatingAxisSets(state, nextAxis))
                        {
                            yield return coords;
                        }
                    }
                }
            }
            --state.Index;
        }