Пример #1
0
        private static IEnumerable <int?[]> generateCombinations(bool isCol, int rowCol, int[] clue, IEnumerable <UniquenessConstraint> furtherRestrictions, int gridWidth, int gridHeight, int minValue, int maxValue)
        {
            var combinations        = new List <int?[]>();
            var affectedCenterCells = Enumerable.Range(0, isCol ? gridHeight : gridWidth).Select(ix => isCol ? rowCol + gridWidth * ix : ix + gridWidth * rowCol).ToArray();

            bool combinationAcceptable(int?[] combination)
            {
                if (furtherRestrictions == null)
                {
                    return(true);
                }
                foreach (var uniq in furtherRestrictions)
                {
                    for (var i = 0; i < uniq.AffectedCells.Length; i++)
                    {
                        if (combination[uniq.AffectedCells[i]] != null)
                        {
                            for (var j = i + 1; j < uniq.AffectedCells.Length; j++)
                            {
                                if (combination[uniq.AffectedCells[j]] == combination[uniq.AffectedCells[i]])
                                {
                                    return(false);
                                }
                            }
                        }
                    }
                }
                return(true);
            }

            switch (clue.Length)
            {
            case 0:
                return(Enumerable.Empty <int?[]>());

            case 1:
            {
                for (var i1 = 0; i1 < affectedCenterCells.Length; i1++)
                {
                    var comb   = new int?[gridWidth * gridHeight];
                    var neigh1 = PuzzleUtil.Orthogonal(affectedCenterCells[i1], gridWidth, gridHeight).ToArray();
                    foreach (var numbers in PuzzleUtil.Combinations(minValue, maxValue, neigh1.Length, allowDuplicates: true).Where(c => c.Sum() == clue[0]))
                    {
                        for (var i = 0; i < neigh1.Length; i++)
                        {
                            comb[neigh1[i]] = numbers[i];
                        }
                        if (combinationAcceptable(comb))
                        {
                            combinations.Add((int?[])comb.Clone());
                        }
                    }
                }
                break;
            }

            case 2:
            {
                for (var i1 = 0; i1 < affectedCenterCells.Length; i1++)
                {
                    var comb   = new int?[gridWidth * gridHeight];
                    var neigh1 = PuzzleUtil.Orthogonal(affectedCenterCells[i1], gridWidth, gridHeight).ToArray();
                    foreach (var numbers in PuzzleUtil.Combinations(minValue, maxValue, neigh1.Length, allowDuplicates: true).Where(c => c.Sum() == clue[0]))
                    {
                        for (var i = 0; i < neigh1.Length; i++)
                        {
                            comb[neigh1[i]] = numbers[i];
                        }
                        if (!combinationAcceptable(comb))
                        {
                            continue;
                        }

                        for (var i2 = i1 + 1; i2 < affectedCenterCells.Length; i2++)
                        {
                            var neigh2 = PuzzleUtil.Orthogonal(affectedCenterCells[i2], gridWidth, gridHeight).ToArray();
                            foreach (var numbers2 in PuzzleUtil.Combinations(minValue, maxValue, neigh2.Length, allowDuplicates: true).Where(c => c.Sum() == clue[1]))
                            {
                                var comb2 = (int?[])comb.Clone();
                                for (var i = 0; i < neigh2.Length; i++)
                                {
                                    if (comb2[neigh2[i]] != null && comb2[neigh2[i]] != numbers2[i])
                                    {
                                        goto busted2;
                                    }
                                    comb2[neigh2[i]] = numbers2[i];
                                }
                                if (combinationAcceptable(comb2))
                                {
                                    combinations.Add(comb2);
                                }
                            }
                            busted2 :;
                        }
                    }
                }
                break;
            }

            default:
                throw new NotImplementedException("NeighborSumConstraint currently only supports up to 2 numbers per clue.");
            }

            return(combinations);
        }
Пример #2
0
    private bool isUnique(int[] rowSums, int[] rowVoltorbs, int[] colSums, int[] colVoltorbs, int[] givenCells)
    {
        var puzzle = new Puzzle(25, 0, 3);

        for (var i = 0; i < 5; i++)
        {
            puzzle.AddConstraint(new CombinationsConstraint(Enumerable.Range(0, 5).Select(j => j + 5 * i), PuzzleUtil.Combinations(0, 3, 5, true).Where(c => c.Sum() == rowSums[i] && c.Count(v => v == 0) == rowVoltorbs[i])));
            puzzle.AddConstraint(new CombinationsConstraint(Enumerable.Range(0, 5).Select(j => i + 5 * j), PuzzleUtil.Combinations(0, 3, 5, true).Where(c => c.Sum() == colSums[i] && c.Count(v => v == 0) == colVoltorbs[i])));
        }
        for (var gcIx = 0; gcIx < givenCells.Length; gcIx++)
        {
            puzzle.AddConstraint(new GivenConstraint(givenCells[gcIx], 0));
        }

        bool[] voltorbs = null;

        foreach (var solution in puzzle.Solve())
        {
            if (voltorbs == null)
            {
                voltorbs = solution.Select(v => v == 0).ToArray();
            }
            else
            {
                for (var i = 0; i < solution.Length; i++)
                {
                    if ((solution[i] == 0) != voltorbs[i])
                    {
                        return(false);
                    }
                }
            }
        }
        return(true);
    }