예제 #1
0
        private void ReduceRegion(uint pair, SudokuRegion region, SudokuState state, ICollection <IEvent> events)
        {
            HiddenPairs.Clear();

            foreach (var index in region)
            {
                var and = state[index] & pair;

                // at least on of the two is pressent.
                if (and != 0)
                {
                    // If not both are present or we already had 2, return.
                    if (and != pair || HiddenPairs.Count > 1)
                    {
                        return;
                    }
                    HiddenPairs.Add(index);
                }
            }

            if (HiddenPairs.Count == 2)
            {
                Fetch(pair, HiddenPairs, state, events);
            }
        }
예제 #2
0
        private void Fetch(uint quad, SimpleList <int> buffer, SudokuRegion region, SudokuState state, ICollection <IEvent> events)
        {
            var reduced = false;
            var mask    = ~quad;

            foreach (var index in region)
            {
                if (buffer.Contains(index))
                {
                    continue;
                }
                var result = state.And <ReduceNakedTriples>(index, mask);
                if (result is ValueFound)
                {
                    events.Add(result);
                }
                else if (result is ReducedOption)
                {
                    reduced = true;
                }
            }

            if (reduced)
            {
                events.Add(ReducedOptions.Ctor <ReduceNakedTriples>());
            }
        }
예제 #3
0
        private void ReduceRegion(int skip, SudokuRegion region, SudokuState state, ICollection <IEvent> events)
        {
            var quad = 0u;

            buffer.Clear();

            foreach (var index in region.Skip(skip))
            {
                var value = state[index];

                if (SudokuCell.Count(value) < 4)
                {
                    quad |= value;

                    // Joined the represent more then 3 values.
                    if (SudokuCell.Count(quad) > 4 || buffer.Count > 3)
                    {
                        return;
                    }
                    buffer.Add(index);
                }
            }

            if (buffer.Count == 4)
            {
                Fetch(quad, buffer, region, state, events);
            }
        }
예제 #4
0
        private void Fetch(uint nakedPair, SudokuRegion region, SudokuState state, ICollection <IEvent> events)
        {
            IEvent result = NoReduction.Instance;
            var    mask   = ~nakedPair;

            foreach (var index in region)
            {
                var value = state[index];
                if (value != nakedPair)
                {
                    var test = state.And <ReduceNakedPairs>(index, mask);

                    if (test is ValueFound)
                    {
                        events.Add(test);
                    }
                    else if (test is ReducedOption)
                    {
                        result = test;
                    }
                }
            }

            if (result is ReducedOption)
            {
                events.Add(ReducedOptions.Ctor <ReduceNakedPairs>());
            }
        }
예제 #5
0
        /// <inheritdoc />
        public void Solve(SudokuPuzzle puzzle, SudokuState state, ICollection <IEvent> events)
        {
            foreach (var region in puzzle.Regions)
            {
                foreach (var intersected in region.Intersected)
                {
                    intersection.Clear();
                    intersection.AddRange(region.Intersect(intersected));

                    // We found candidate intersections
                    if (intersection.Count > 1)
                    {
                        foreach (var value in puzzle.SingleValues)
                        {
                            var pre = events.Count;
                            Solve(state, region, intersected, value, events);

                            if (pre != events.Count)
                            {
                                return;
                            }
                        }
                    }
                }
            }
        }
예제 #6
0
        private void ReduceRegion(SudokuRegion region, SudokuState state, ICollection <IEvent> events)
        {
            var nakedPair = 0u;
            var count     = 0;

            foreach (var index in region)
            {
                var value = state[index];

                // nothing found yet.
                if (nakedPair == default)
                {
                    if (SudokuCell.Count(value) == 2)
                    {
                        nakedPair = value;
                        count++;
                    }
                }

                // Equal to the first (potential) naked pair.
                else if (value == nakedPair && count++ > 2)
                {
                    throw new InvalidPuzzleException();
                }
            }

            if (count > 1)
            {
                Fetch(nakedPair, region, state, events);
            }
        }
예제 #7
0
        private void CheckCells(SudokuState state, SudokuRegion region, uint singleValue, ICollection <IEvent> events)
        {
            var hidden = NoIndex;

            foreach (var index in region)
            {
                var value = state[index];

                // the cell has the value.
                if ((singleValue & value) != 0)
                {
                    // Already value, try next.
                    if (singleValue == value)
                    {
                        return;
                    }

                    // not the first
                    if (hidden != NoIndex)
                    {
                        return;
                    }
                    hidden = index;
                }
            }

            if (hidden == NoIndex)
            {
                return;
            }
            events.Add(state.And <ReduceHiddenSingles>(hidden, singleValue));
        }
예제 #8
0
        public void Solve(SudokuPuzzle puzzle, SudokuState state, ICollection <IEvent> events)
        {
            var count = -1;

            while (count != events.Count)
            {
                count = events.Count;

                for (var i = 0; i < solvers.Length; i++)
                {
                    var solver = solvers[i];
                    solver.Solve(puzzle, state, events);

                    if (events.Count != count)
                    {
                        if (state.IsSolved)
                        {
                            events.Add(SolvedPuzzle.Instance);
                            return;
                        }
                        i = solvers.Length;
                    }
                }
            }
        }
예제 #9
0
        /// <inheritdoc />
        public void Solve(SudokuPuzzle puzzle, SudokuState state, ICollection <IEvent> events)
        {
            foreach (var region in puzzle.Regions)
            {
                var pre = events.Count;
                ReduceRegion(region, state, events);

                if (pre != events.Count)
                {
                    return;
                }
            }
        }
예제 #10
0
        /// <summary>Solves a Sudoku puzzle given the Sudoku state.</summary>
        public SudokuState Solve(SudokuState sudokuState)
        {
            // As states are mutable, create a copy.
            var state  = sudokuState.Copy();
            var events = new List <IEvent>(128);

            Solver.Solve(Puzzle, state, events);
            foreach (var @event in events)
            {
                Console.WriteLine(@event);
            }
            return(state);
        }
예제 #11
0
        /// <inheritdoc />
        public void Solve(SudokuPuzzle puzzle, SudokuState state, ICollection <IEvent> events)
        {
            // check all groups.
            foreach (var region in puzzle.Regions)
            {
                foreach (var singleValue in puzzle.SingleValues)
                {
                    var pre = events.Count;
                    CheckCells(state, region, singleValue, events);

                    if (pre != events.Count)
                    {
                        return;
                    }
                }
            }
        }
예제 #12
0
        private void Fetch(uint pair, SimpleList <int> hiddenPairs, SudokuState state, ICollection <IEvent> events)
        {
            IEvent result = NoReduction.Instance;

            foreach (var index in hiddenPairs)
            {
                var test = state.And <ReduceHiddenPairs>(index, pair);

                if (test is ReducedOption)
                {
                    result = test;
                }
            }
            if (result is ReducedOption)
            {
                events.Add(ReducedOptions.Ctor <ReduceHiddenPairs>());
            }
        }
예제 #13
0
        /// <inheritdoc />
        public void Solve(SudokuPuzzle puzzle, SudokuState state, ICollection <IEvent> events)
        {
            foreach (var region in puzzle.Regions)
            {
                foreach (var pair in Pairs)
                {
                    var pre = events.Count;

                    ReduceRegion(pair, region, state, events);

                    // We found some, let simpler strategies try again.
                    if (pre != events.Count)
                    {
                        return;
                    }
                }
            }
        }
예제 #14
0
        /// <inheritdoc />
        public void Solve(SudokuPuzzle puzzle, SudokuState state, ICollection <IEvent> events)
        {
            var reduced = false;

            for (var index = 0; index <= puzzle.MaximumIndex; index++)
            {
                // For known cells only.
                if (state.IsKnown(index))
                {
                    var mask = ~state[index];

                    // for all groups the cell belongs to.
                    foreach (var group in puzzle.Lookup[index])
                    {
                        foreach (var target in group)
                        {
                            if (target == index)
                            {
                                continue;
                            }

                            var result = state.And <ReduceNakedSingles>(target, mask);

                            if (result is ReducedOption)
                            {
                                reduced = true;
                            }
                            else if (result is ValueFound)
                            {
                                events.Add(result);
                            }
                        }
                    }
                }
            }
            if (reduced)
            {
                events.Add(ReducedOptions.Ctor <ReduceNakedSingles>());
            }
        }
예제 #15
0
        private void Solve(SudokuPuzzle puzzle, SudokuState state, ICollection <IEvent> events, SudokuRegionType type, SudokuRegionType otherType)
        {
            var pre = events.Count;

            foreach (var first in puzzle.Regions.Where(r => r.RegionType == type))
            {
                foreach (var second in puzzle.Regions.Where(r => r.RegionType == otherType))
                {
                    if (first != second)
                    {
                        foreach (var value in SudokuCell.Singles)
                        {
                            Solve(value, first, second, otherType, state, events);
                            if (events.Count != pre)
                            {
                                return;
                            }
                        }
                    }
                }
            }
        }
예제 #16
0
        private void Solve(SudokuState state, SudokuRegion region, SudokuRegion intersected, uint value, ICollection <IEvent> events)
        {
            var count = 0;

            foreach (var index in region)
            {
                if ((state[index] & value) != 0)
                {
                    if (intersection.Contains(index))
                    {
                        count++;
                    }
                    else
                    {
                        return;
                    }
                }
            }
            if (count > 1)
            {
                Fetch(value, intersection, intersected, state, events);
            }
        }
예제 #17
0
        private bool Fetch(uint value, SudokuRegion region, SudokuState state, ICollection <IEvent> events)
        {
            var reducded = false;
            var mask     = ~value;

            foreach (var index in region)
            {
                if (buffer.Contains(index))
                {
                    continue;
                }
                var result = state.And <ReduceXWing>(index, mask);
                if (result is ValueFound)
                {
                    events.Add(result);
                }
                else if (result is ReducedOption)
                {
                    reducded = true;
                }
            }
            return(reducded);
        }
예제 #18
0
        private void Fetch(uint value, SimpleList <int> intersection, SudokuRegion intersected, SudokuState state, ICollection <IEvent> events)
        {
            IEvent result = NoReduction.Instance;
            var    mask   = ~value;

            foreach (var index in intersected)
            {
                // items in the shared section should be skipped.
                if (intersection.Contains(index))
                {
                    continue;
                }
                var test = state.And <ReducePointingPairs>(index, mask);

                if (test is ValueFound)
                {
                    events.Add(test);
                }
                else if (test is ReducedOption)
                {
                    result = test;
                }
            }

            if (result is ReducedOption)
            {
                events.Add(ReducedOptions.Ctor <ReduceNakedPairs>());
            }
        }
예제 #19
0
 public void Solve(SudokuPuzzle puzzle, SudokuState state, ICollection <IEvent> events)
 {
     Solve(puzzle, state, events, SudokuRegionType.Row, SudokuRegionType.Column);
     Solve(puzzle, state, events, SudokuRegionType.Column, SudokuRegionType.Row);
 }
예제 #20
0
        public void Solve(uint value, SudokuRegion first, SudokuRegion second, SudokuRegionType otherType, SudokuState state, ICollection <IEvent> events)
        {
            buffer.Clear();

            for (var index = 0; index < 9; index++)
            {
                var indexFirst  = first[index];
                var indexSecond = second[index];
                var joinFirst   = state[indexFirst] & value;
                var joinSecond  = state[indexSecond] & value;

                if (joinFirst == 0)
                {
                    if (joinSecond != 0)
                    {
                        return;
                    }
                }
                else
                {
                    if (joinSecond == 0 || buffer.Count > 3)
                    {
                        return;
                    }
                    buffer.Add(indexFirst);
                    buffer.Add(indexSecond);
                }
            }
            if (buffer.Count == 4)
            {
                var reducded = Fetch(
                    value,
                    first.Intersected.FirstOrDefault(r => r.RegionType == otherType),
                    state,
                    events);

                reducded |= Fetch(
                    value,
                    second.Intersected.FirstOrDefault(r => r.RegionType == otherType),
                    state,
                    events);

                if (reducded)
                {
                    events.Add(ReducedOptions.Ctor <ReduceXWing>());
                }
            }
        }