Пример #1
0
        /// <summary>
        /// 2 sections can only see each other if the row or column of the chute they are in
        /// is the same.
        /// </summary>
        /// <param name="als2"></param>
        /// <returns></returns>
        private bool CanSee(AlmostLockedSet als2)
        {
            bool returnValue = Coordinate != Coord.SECTION || als2.Coordinate != Coord.SECTION ||
                               (CoordIndex / GroupDimension) == (als2.CoordIndex / GroupDimension) ||
                               (CoordIndex % GroupDimension) == (als2.CoordIndex % GroupDimension);

            return(returnValue);
        }
Пример #2
0
        /// <summary>
        /// Creates an AlmostLockedSet object from a list of cells.
        /// </summary>
        /// <param name="cellCollection">List of cells making the ALS</param>
        /// <param name="dimension">Size of a line or column or group.</param>
        /// <param name="coordinate">Indicates the type of housing for the ALS</param>
        /// <param name="index">Index of the coordinate (e.g. index of the row, or
        /// index of the column, or index of the group).</param>
        /// <returns></returns>
        private static AlmostLockedSet ALSFromCellList(IEnumerable <Cell> cellCollection, int dimension,
                                                       int coordinate, int index)
        {
            List <int> perfectSquares = new List <int> {
                0, 1, 4, 9, 16, 25
            };
            int dimSquared = dimension * dimension;
            int intsNeeded = (dimSquared / Int64BitSize) + (((dimSquared % Int64BitSize) == 0) ? 0 : 1);
            int pmMask     = 0;

            Int64[]     cellMap  = new Int64[intsNeeded];
            List <Cell> cellList = cellCollection
                                   .ToList();

            int groupSize = perfectSquares.IndexOf(dimension);

            cellList.ForEach(cell =>
            {
                pmMask      |= cell.PMSignature;
                int cellPos  = cell.RowIndex * dimension + cell.ColIndex;
                int mapIndex = cellPos / Int64BitSize;
                int bitIndex = cellPos % Int64BitSize;

#pragma warning disable 0675
                cellMap[mapIndex] |= (long)((ulong)(1 << bitIndex));
#pragma warning restore 0675
            });

            AlmostLockedSet returnValue = (pmMask.NumberOfBitsSet() == cellList.Count + 1) ?
                                          new AlmostLockedSet()
            {
                Cells          = cellList,
                PmsInSet       = pmMask,
                GroupDimension = groupSize,
                Coordinate     = coordinate,
                CoordIndex     = index,
                CellMap        = cellMap
            }
                    :
            null;

            return(returnValue);
        }
Пример #3
0
        public static ALSMatch AreAlsXZ(AlmostLockedSet als1, AlmostLockedSet als2)
        {
            int len = als1.CellMap.Length;

            for (int i = 0; i < len; i++)
            {
                if ((als1.CellMap[i] & als2.CellMap[i]) != 0)
                {
                    return(null);
                }
            }

            if (!als1.CanSee(als2))
            {
                return(null);
            }

            // Set A:  N cells with (N + 1) candidates
            // Set B:  M cells with (M + 1) candidates
            // With 1 common restricted pencilmark, and 1 uncommon restricted pencilmark,
            // the total number of pencilmarks in an ALS-XZ pattern is M + N, and the
            // number of common ones must be 2.
            int commonPMsSignature = als1.PmsInSet & als2.PmsInSet;

            if (commonPMsSignature.NumberOfBitsSet() < 2)
            {
                return(null);
            }

            List <int> commonPMCandidates = commonPMsSignature.ListOfBits();

            Func <List <Cell>, int, List <Cell> > fnCellsWithPM = (cellList, pm) => cellList
                                                                  .Where(cell => cell.IsPencilmarkSet(pm))
                                                                  .ToList();

            Cell unShadowed         = null;
            int  restrictedCommonPM = 0;

            List <Cell> commonCells1;
            List <Cell> commonCells2;

            // find out if one of the common pencilmarks can see all the ones in the other group.
            foreach (int pm in commonPMCandidates)
            {
                commonCells1 = fnCellsWithPM(als1.Cells, pm);
                commonCells2 = fnCellsWithPM(als2.Cells, pm);

                unShadowed = commonCells1.FirstOrDefault(cell1 =>
                                                         commonCells2.FirstOrDefault(cell2 => !cell1.CanSee(cell2)) != null);

                if (unShadowed == null)
                {
                    restrictedCommonPM = pm;
                    break;
                }
            }

            if (restrictedCommonPM == 0)
            {
                return(null);
            }

            commonPMCandidates.Remove(restrictedCommonPM);
            foreach (int pmc in commonPMCandidates)
            {
                // if the commonPMs have shadowed cells with the pencilmark, then it's a good
                // ALS pattern
                commonCells1 = fnCellsWithPM(als1.Cells, pmc);
                commonCells2 = fnCellsWithPM(als2.Cells, pmc);

                IEnumerable <Cell> intersectAll = commonCells1
                                                  .First()
                                                  .ShadowedCells
                                                  .Where(cell => cell.IsPencilmarkSet(pmc));

                if (!intersectAll.Any())
                {
                    continue;
                }

                Action <List <Cell>, int> cumulativeIntersect = (cellList, skipCount) =>
                                                                cellList
                                                                .Skip(skipCount)
                                                                .Select(cell => cell.ShadowedCells.Where(cell2 => cell2.IsPencilmarkSet(pmc)))
                                                                .ToList()
                                                                .ForEach(singleList => intersectAll = intersectAll.Intersect(singleList));

                cumulativeIntersect(commonCells1, 1);
                if (intersectAll.Any())
                {
                    cumulativeIntersect(commonCells2, 0);
                }

                // this if is not a bogus if with negated condition of the previous one, since
                // cumulativeIntersect will change the value of intersectAll
                if (!intersectAll.Any())
                {
                    continue;
                }

                ALSMatch returnValue = new ALSMatch()
                {
                    Als1                       = als1,
                    Als2                       = als2,
                    commonPencilmark           = pmc,
                    commonRestrictedPencilmark = restrictedCommonPM,
                    AffectedCells              = intersectAll.ToList()
                };

                return(returnValue);
            }

            return(null);
        }