コード例 #1
0
        /// <inheritdoc/>
        public override void GetAll(IBag <TechniqueInfo> accumulator, IReadOnlyGrid grid)
        {
            // Iterate on each region pair.
            for (int index = 0; index < 18; index++)
            {
                // Iterate on each size.
                var(r1, r2) = (Regions[index, 0], Regions[index, 1]);
                foreach (var(size, masks) in Combinations)
                {
                    // Iterate on each combination.
                    foreach (short mask in masks)
                    {
                        var positions   = mask.GetAllSets();
                        var allCellsMap = GridMap.Empty;
                        var pairs       = new List <(int, int)>();
                        foreach (int pos in positions)
                        {
                            int c1 = RegionCells[r1][pos];
                            int c2 = RegionCells[r2][pos];
                            allCellsMap.Add(c1);
                            allCellsMap.Add(c2);
                            pairs.Add((c1, c2));
                        }

                        // Check each pair.
                        // Ensures all pairs should contains same digits
                        // and the kind of digits must be greater than 2.
                        bool checkKindsFlag = true;
                        foreach (var(l, r) in pairs)
                        {
                            if ((grid.GetCandidatesReversal(l) & grid.GetCandidatesReversal(r)).CountSet() < 2)
                            {
                                checkKindsFlag = false;
                                break;
                            }
                        }
                        if (!checkKindsFlag)
                        {
                            // Failed to check.
                            continue;
                        }

                        // Check the mask of cells from two regions.
                        short m1 = 0, m2 = 0;
                        foreach (var(l, r) in pairs)
                        {
                            m1 |= grid.GetCandidatesReversal(l);
                            m2 |= grid.GetCandidatesReversal(r);
                        }

                        int resultMask   = m1 | m2;
                        var normalDigits = new List <int>();
                        var extraDigits  = new List <int>();
                        var digits       = resultMask.GetAllSets();
                        foreach (int digit in digits)
                        {
                            int count = 0;
                            foreach (var(l, r) in pairs)
                            {
                                if (((grid.GetCandidatesReversal(l) & grid.GetCandidatesReversal(r)) >> digit & 1) != 0)
                                {
                                    // Both two cells contain same digit.
                                    count++;
                                }
                            }

                            if (count >= 2)
                            {
                                // This candidate must be in the structure.
                                normalDigits.Add(digit);
                            }
                            else
                            {
                                // This candidate must be the extra digit.
                                extraDigits.Add(digit);
                            }
                        }

                        if (normalDigits.Count != size)
                        {
                            // The number of normal digits are not enough.
                            continue;
                        }

                        if (resultMask.CountSet() == size + 1)
                        {
                            // Possible type 1 or 2 found.
                            // Now check extra cells.
                            var extraCells = new List <int>();
                            foreach (int cell in allCellsMap)
                            {
                                if ((grid.GetCandidatesReversal(cell) >> extraDigits[0] & 1) != 0)
                                {
                                    extraCells.Add(cell);
                                }
                            }

                            var extraCellsMap = new GridMap(extraCells) & EmptyMap;
                            if (extraCellsMap.IsEmpty)
                            {
                                continue;
                            }

                            // Get all eliminations and highlight candidates.
                            int extraDigit       = extraDigits[0];
                            var conclusions      = new List <Conclusion>();
                            var candidateOffsets = new List <(int, int)>();
                            if (extraCellsMap.Count == 1)
                            {
                                // Type 1.
                                foreach (int cell in allCellsMap)
                                {
                                    if (cell == extraCells[0])
                                    {
                                        foreach (int digit in grid.GetCandidatesReversal(cell).GetAllSets())
                                        {
                                            if (digit == extraDigit)
                                            {
                                                continue;
                                            }

                                            conclusions.Add(new Conclusion(Elimination, cell, digit));
                                        }
                                    }
                                    else
                                    {
                                        foreach (int digit in grid.GetCandidatesReversal(cell).GetAllSets())
                                        {
                                            candidateOffsets.Add((0, cell * 9 + digit));
                                        }
                                    }
                                }

                                if (conclusions.Count == 0)
                                {
                                    continue;
                                }

                                accumulator.Add(
                                    new XrType1TechniqueInfo(
                                        conclusions,
                                        views: new[]
                                {
                                    new View(
                                        cellOffsets: null,
                                        candidateOffsets,
                                        regionOffsets: null,
                                        links: null)
                                },
                                        typeCode: 1,
                                        typeName: "Type 1",
                                        cells: allCellsMap.ToArray(),
                                        digits: normalDigits));
                            }
                            else
                            {
                                // Type 2.
                                // Check eliminations.
                                var elimMap = new GridMap(extraCells, ProcessPeersWithoutItself);
                                foreach (int cell in elimMap)
                                {
                                    if (!(grid.Exists(cell, extraDigit) is true))
                                    {
                                        continue;
                                    }

                                    conclusions.Add(new Conclusion(Elimination, cell, extraDigit));
                                }

                                if (conclusions.Count == 0)
                                {
                                    continue;
                                }

                                // Record all highlight candidates.
                                foreach (int cell in allCellsMap)
                                {
                                    foreach (int digit in grid.GetCandidatesReversal(cell).GetAllSets())
                                    {
                                        candidateOffsets.Add((digit == extraDigit ? 1 : 0, cell * 9 + digit));
                                    }
                                }

                                accumulator.Add(
                                    new XrType2TechniqueInfo(
                                        conclusions,
                                        views: new[]
                                {
                                    new View(
                                        cellOffsets: null,
                                        candidateOffsets,
                                        regionOffsets: null,
                                        links: null)
                                },
                                        typeCode: 2,
                                        typeName: "Type 2",
                                        cells: allCellsMap.ToArray(),
                                        digits: normalDigits,
                                        extraDigit));
                            }
                        }
                        else
                        {
                            // Check type 3 or 4.
                            for (int subsetSize = 2; subsetSize <= 8 - size; subsetSize++)
                            {
                                CheckType3Naked(
                                    accumulator, grid, allCellsMap, subsetSize, r1, r2, pairs,
                                    normalDigits, extraDigits);
                            }

                            CheckType14(accumulator, grid, allCellsMap, normalDigits, extraDigits);
                        }
                    }
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Check type 1 or 4.
        /// </summary>
        /// <param name="accumulator">The accumulator.</param>
        /// <param name="grid">The grid.</param>
        /// <param name="allCellsMap">All cells map.</param>
        /// <param name="normalDigits">The normal digits.</param>
        /// <param name="extraDigits">The extra digits.</param>
        private void CheckType14(
            IBag <TechniqueInfo> accumulator, IReadOnlyGrid grid, GridMap allCellsMap,
            IReadOnlyList <int> normalDigits, IReadOnlyList <int> extraDigits)
        {
            // Now check extra cells.
            var extraCells = new List <int>();

            foreach (int cell in allCellsMap)
            {
                foreach (int digit in extraDigits)
                {
                    if ((grid.GetCandidatesReversal(cell) >> digit & 1) != 0)
                    {
                        extraCells.Add(cell);
                    }
                }
            }

            int extraCellsCount = extraCells.Count;

            if (extraCellsCount == 1)
            {
                // Type 1 found.
                // Check eliminations.
                var conclusions = new List <Conclusion>();
                int extraCell   = extraCells[0];
                foreach (int digit in normalDigits)
                {
                    if (!(grid.Exists(extraCell, digit) is true))
                    {
                        continue;
                    }

                    conclusions.Add(new Conclusion(Elimination, extraCell, digit));
                }

                if (conclusions.Count == 0)
                {
                    return;
                }

                // Record all highlight candidates.
                var candidateOffsets = new List <(int, int)>();
                foreach (int cell in allCellsMap)
                {
                    if (cell == extraCell)
                    {
                        continue;
                    }

                    foreach (int digit in grid.GetCandidatesReversal(cell).GetAllSets())
                    {
                        candidateOffsets.Add((0, cell * 9 + digit));
                    }
                }

                accumulator.Add(
                    new XrType1TechniqueInfo(
                        conclusions,
                        views: new[]
                {
                    new View(
                        cellOffsets: null,
                        candidateOffsets,
                        regionOffsets: null,
                        links: null)
                },
                        typeCode: 1,
                        typeName: "Type 1",
                        cells: allCellsMap.ToArray(),
                        digits: normalDigits));
            }
            else
            {
                // TODO: Check XR type 4.
            }
        }