예제 #1
0
    public Puzzle LoadFromString(string input)
    {
        Group[] rows = new Group[9];
        try
        {
            var enumerator = input.GetEnumerator();
            for (int row = 0; row < 9; row++)
            {
                var rowCells = new Cell[9];

                for (int col = 0; col < 9; col++)
                {
                    enumerator.MoveNext();
                    var current = enumerator.Current;
                    rowCells[col] = new Cell(current, row + 1, col + 1, _logger);
                }
                rows[row] = new Group(rowCells, $"row {row+1}", _logger);
            }
        }
        catch (IOException e)
        {
            _logger.Log("LoadPuzzle", $"Problem reading puzzle data: {e.Message}");
            throw;
        }
        return(new Puzzle(rows, _logger));
    }
예제 #2
0
 public void FillIn(char candidate, string actor)
 {
     Filled     = true;
     Value      = candidate;
     Candidates = null;
     _log.Log(actor, $"Filled in a {candidate} at {Col},{Row}!");
 }
예제 #3
0
        internal bool IsValidActivityType(string activityTypeCode, string policyNumber, IMessageLogger log)
        {
            bool success = activityTypeCode.Equals(Constants.TransactionType.PENDINGCANCEL, StringComparison.InvariantCultureIgnoreCase) ||
                           activityTypeCode.Equals(Constants.BillingActivityTypeCodes.RESCINDPCN, StringComparison.InvariantCultureIgnoreCase);

            if (!success)
            {
                log.Log(
                    new Log()
                {
                    Messages = new List <LogMessage>()
                    {
                        new LogMessage()
                        {
                            Category = Constants.Logging.CATEGORY,
                            Severity = SeverityType.Information,
                            Message  = $"Detected an activity type to not process: {activityTypeCode} for {policyNumber}",
                        }
                    }
                },
                    policyNumber);
            }

            return(success);
        }
    public bool Apply(Puzzle puzzle)
    {
        _searchCombos = 0;
        bool progress = false;

        // Iterate each row, column and box, looking for 3 cells that contain only 3 candidates
        for (int num = 1; num < 10; num++)
        {
            var group = puzzle.GetRow(num);
            progress = CheckGroup(group) || progress;
            group    = puzzle.GetColumn(num);
            progress = CheckGroup(group) || progress;
            group    = puzzle.GetBox(num);
            progress = CheckGroup(group) || progress;
        }
        _logger.Log(Name, $"Searched {_searchCombos} group/triplet combos");
        return(progress);
    }
예제 #5
0
        public void Post([FromBody] LogMessage message)
        {
            if (message == null || string.IsNullOrWhiteSpace(message.Message))
            {
                throw new Exception($"Value for {nameof(message)} is missing.");
            }

            _messageLogger.Log(message.Message);
        }
예제 #6
0
        public IActionResult Post([FromBody] LogMessage message)
        {
            if (message == null || string.IsNullOrWhiteSpace(message.Message))
            {
                return(BadRequest($"Value for {nameof(message)} is missing."));
            }

            _messageLogger.Log(message.Message);

            return(Accepted());
        }
예제 #7
0
    private bool CheckGroup(Group group)
    {
        bool progress = false;

        for (int firstCell = 1; firstCell <= 8; firstCell++)
        {
            var firstCellData = group.GetCell(firstCell);
            if (firstCellData.Given || firstCellData.Filled)
            {
                continue;
            }
            if (firstCellData.Candidates.Count == 2)
            {
                // See if any of the other cells are a pair with this one
                for (int secondCell = firstCell + 1; secondCell <= 9; secondCell++)
                {
                    var secondCellData = group.GetCell(secondCell);
                    if (secondCellData.Given || secondCellData.Filled)
                    {
                        continue;
                    }
                    if (secondCellData.Candidates.SetEquals(firstCellData.Candidates))
                    {
                        bool pairProgress = false;
                        // This is a naked pair - remove candidates from all other cells!
                        for (int cellNum = 1; cellNum <= 9; cellNum++)
                        {
                            if (cellNum == firstCell || cellNum == secondCell)
                            {
                                continue;
                            }

                            var cell = group.GetCell(cellNum);
                            if (!cell.Given && !cell.Filled)
                            {
                                if (cell.EliminateCandidates(firstCellData.Candidates, Name))
                                {
                                    pairProgress = true;
                                }
                            }
                        }
                        if (pairProgress)
                        {
                            _logger.Log(Name, $"{firstCellData.Candidates.First()}{firstCellData.Candidates.Skip(1).First()} in {group.Description} helps us");
                            progress = true;
                        }
                    }
                }
            }
        }
        return(progress);
    }
예제 #8
0
 public void WriteGridAsText(IMessageLogger logger)
 {
     for (int row = 1; row <= 9; row++)
     {
         if ((row - 1) % 3 == 0)
         {
             logger.Log(null, "-------------");
         }
         var rowData = GetRow(row);
         var msg     = "";
         for (int col = 1; col <= 9; col++)
         {
             if ((col - 1) % 3 == 0)
             {
                 msg += "|";
             }
             msg += rowData.GetCell(col).Value;
         }
         logger.Log(null, msg + "|");
     }
     logger.Log(null, "-------------");
 }
예제 #9
0
    private bool RemoveCandidatesFromRow(Puzzle puzzle, int rowNum, int rowOffset, int colOffset, char candidate, int boxNum)
    {
        bool progress = false;
        var  group    = puzzle.GetRow(rowNum + rowOffset);

        for (int colNum = 1; colNum <= 9; colNum++)
        {
            if (colNum > colOffset && colNum <= colOffset + 3)
            {
                // Skip the 3 cells in the current box
                continue;
            }
            if (group.GetCell(colNum).EliminateCandidate(candidate, Name))
            {
                progress = true;
            }
        }
        if (progress)
        {
            _logger.Log(Name, $"{candidate}s all in a row in box {boxNum}");
        }
        return(progress);
    }
예제 #10
0
    internal bool IsValid()
    {
        var valid      = true;
        var candidates = new HashSet <char>();
        var placed     = new HashSet <char>();

        foreach (var cell in _cells)
        {
            if (cell.Filled)
            {
                if (placed.Contains(cell.Value))
                {
                    _log.Log(null, $"{cell.Value} filled in more than once in {this.Description}!", SudokuBrain.Models.LogItemLevel.Problem);
                    valid = false;
                }
                placed.Add(cell.Value);
            }
            else
            {
                candidates.UnionWith(cell.Candidates);
            }
        }
        placed.UnionWith(candidates);
        var allNumbers = new HashSet <char>(Constants.AllValues);

        foreach (var ch in placed)
        {
            allNumbers.Remove(ch);
        }
        if (allNumbers.Count > 0)
        {
            _log.Log(null, $"{allNumbers.First()} is missing from {this.Description}!", SudokuBrain.Models.LogItemLevel.Problem);
            valid = false;
        }

        return(valid);
    }
예제 #11
0
        internal bool IsValidIssueSystemCode(string issueSystemCode, string policyNumber, IMessageLogger log)
        {
            bool success = issueSystemCode.Equals(Constants.IssueSystemCode.DUCKPERSONAL, StringComparison.InvariantCultureIgnoreCase);

            if (!success)
            {
                log.Log(
                    new Log()
                {
                    Messages = new List <LogMessage>()
                    {
                        new LogMessage()
                        {
                            Category = Constants.Logging.CATEGORY,
                            Severity = SeverityType.Information,
                            Message  = $"Detected a system code to not process: {issueSystemCode} for {policyNumber}",
                        }
                    }
                },
                    policyNumber);
            }

            return(success);
        }
예제 #12
0
    public void EndSolutionStats(Puzzle puzzle)
    {
        _logger.Log(null, "Strategies applied successfully:");
        int difficulty = 0;

        foreach (var strat in puzzle.UsedStrats)
        {
            difficulty += strat.Value;
            _logger.Log(null, $"{strat.Key}");
        }
        if (puzzle.CountFilledInCells == 81)
        {
            _logger.Log(null, $"Difficulty: {difficulty}");
            _logger.Log(null, "All Done :)");
        }
        else
        {
            _logger.Log(null, $"Difficulty: {difficulty}+");
            _logger.Log(null, "Ran out of ideas :/", SudokuBrain.Models.LogItemLevel.Problem);
        }
    }
예제 #13
0
 public void Log(string message)
 {
     _messageLogger.Log(message);
 }
        public async Task <Result> Run()
        {
            var templates = _configurationExplorer.Explore(_options.SourcePath, _options.ConfigurationFiles);

            if (templates.State == Result.Error)
            {
                return(Result.Error);
            }

            var buildGraphResult = _buildGraphFactory.Create(templates.Value);

            if (buildGraphResult.State == Result.Error)
            {
                return(Result.Error);
            }

            var buildGraphsResult = _buildGraphsFactory.Create(buildGraphResult.Value);

            if (buildGraphsResult.State == Result.Error)
            {
                return(Result.Error);
            }

            var buildGraphs = buildGraphsResult.Value.ToList();

            if (!buildGraphs.Any())
            {
                _logger.Log("Nothing to build.", Result.Error);
                return(Result.Error);
            }

            var dockerFilesRootPath = _fileSystem.UniqueName;
            var contextStreamResult = await _contextFactory.Create(dockerFilesRootPath, buildGraphResult.Value.Nodes.Select(i => i.Value).OfType <Image>().Select(i => i.File));

            if (contextStreamResult.State == Result.Error)
            {
                return(Result.Error);
            }

            var contextStream = contextStreamResult.Value;

            using (contextStream)
                using (_logger.CreateBlock("Build"))
                {
                    var labels = new Dictionary <string, string>();
                    foreach (var buildGraph in buildGraphs)
                    {
                        var name = _graphNameFactory.Create(buildGraph).Value ?? "Unnamed graph";
                        if (!string.IsNullOrWhiteSpace(_options.FilterRegex) && !new Regex(_options.FilterRegex).IsMatch(name))
                        {
                            _logger.Log($"\"{name}\" was skipped according to filter \"{_options.FilterRegex}\".", Result.Warning);
                            continue;
                        }

                        using (_logger.CreateBlock(name))
                        {
                            var buildPath = _buildPathProvider.GetPath(buildGraph).ToList();
                            foreach (var buildNode in buildPath)
                            {
                                switch (buildNode.Value)
                                {
                                case Image image:
                                    var dockerFile = image.File;
                                    using (_logger.CreateBlock(dockerFile.ToString()))
                                    {
                                        contextStream.Position = 0;
                                        var dockerFilePathInContext = _pathService.Normalize(Path.Combine(dockerFilesRootPath, dockerFile.Path));
                                        var buildParameters         = new ImageBuildParameters
                                        {
                                            Dockerfile = dockerFilePathInContext,
                                            Tags       = dockerFile.Tags.Distinct().ToList(),
                                            Labels     = labels
                                        };

                                        using (var buildEventStream = await _dockerClient.Images.BuildImageFromDockerfileAsync(
                                                   contextStream,
                                                   buildParameters,
                                                   _cancellationTokenSource.Token))
                                        {
                                            _streamService.ProcessLines(buildEventStream, line => { _messageLogger.Log(line); });
                                        }
                                    }

                                    break;
                                }
                            }
                        }
                    }
                }

            return(Result.Success);
        }
예제 #15
0
    private bool CheckGroup(Group group)
    {
        bool progress = false;
        // Get all remaining candidates in the group
        var candidates = new HashSet <char>(Constants.AllValues);

        for (int cell = 1; cell <= 9; cell++)
        {
            var cellData = group.GetCell(cell);
            if (cellData.Given || cellData.Filled)
            {
                candidates.Remove(cellData.Value);
            }
        }

        var candidatesList = new List <char>(candidates);

        if (candidatesList.Count >= 4)
        {
            // Iterate all sets of 4 possible candidates
            int combos = Helpers.Factorial(candidates.Count) / (Helpers.Factorial(4) * Helpers.Factorial(candidates.Count - 4));
            _logger.Log(Name, $"Hidden quads: searching in {group.Description} with {combos} quad combos");
            for (var i = 0; i < candidatesList.Count - 2; i++)
            {
                var candidate1 = candidatesList[i];
                for (var j = i + 1; j < candidatesList.Count - 1; j++)
                {
                    var candidate2 = candidatesList[j];
                    for (var k = j + 1; k < candidatesList.Count; k++)
                    {
                        var candidate3 = candidatesList[k];
                        // Find all cells containing 2 or 3 of the candidates
                        var permutation = new char[] { candidate1, candidate2, candidate3 };
                        var rejected    = false;
                        var inCells     = new List <int>();
                        for (int cell = 1; cell <= 9; cell++)
                        {
                            var cellData = group.GetCell(cell);
                            if (cellData.Given || cellData.Filled)
                            {
                                continue;
                            }
                            var foundCandidates = new HashSet <char>(cellData.Candidates);
                            foundCandidates.IntersectWith(permutation);
                            if (foundCandidates.Count == 1)
                            {
                                rejected = true;
                                break;
                            }
                            if (foundCandidates.Count > 3)
                            {
                                throw new Exception("makes no sense");
                            }
                            if (foundCandidates.Count > 1)
                            {
                                if (inCells.Count >= 3)
                                {
                                    // This triplet is in too many cells
                                    rejected = true;
                                    break;
                                }
                                inCells.Add(cell);
                            }
                        }
                        if (rejected)
                        {
                            continue;
                        }
                        if (inCells.Count == 3)
                        {
                            _logger.Log(Name, $"{candidate1}{candidate2}{candidate3} in {group.Description}");
                            // We found a hidden triplet! Expose it
                            bool exposeProgress = false;
                            var  tripleValues   = new char[] { candidate1, candidate2, candidate3 };
                            foreach (var cellNum in inCells)
                            {
                                var cellData = group.GetCell(cellNum);
                                var currentCandidateCount = cellData.Candidates.Count;
                                cellData.Candidates.IntersectWith(tripleValues);
                                if (cellData.Candidates.Count < currentCandidateCount)
                                {
                                    exposeProgress = true;
                                }
                            }
                            if (exposeProgress)
                            {
                                _logger.Log(Name, $"Exposed {candidate1}{candidate2}{candidate3} in {group.Description}", SudokuBrain.Models.LogItemLevel.Debug);
                                progress = true;
                            }

                            bool tripletProgress = false;
                            // This is a naked triplet - remove candidates from all other cells!
                            for (int cellNum = 1; cellNum <= 9; cellNum++)
                            {
                                if (inCells.Contains(cellNum))
                                {
                                    continue;
                                }

                                var cell = group.GetCell(cellNum);
                                if (!cell.Given && !cell.Filled)
                                {
                                    if (cell.EliminateCandidates(tripleValues, Name))
                                    {
                                        tripletProgress = true;
                                    }
                                }
                            }
                            if (tripletProgress)
                            {
                                _logger.Log(Name, $"Progress {candidate1}{candidate2}{candidate3} in {group.Description}");
                                progress = true;
                            }
                        }
                    }
                }
            }
        }
        return(progress);
    }
    public bool ApplyToLine(Group line, int lineNum, bool isColumn)
    {
        bool progress = false;

        foreach (var candidate in line.Candidates)
        {
            // Check if this digit is a candidate in only 2 or 3 locations
            var cellNumbers = new HashSet <int>();
            for (int cellNum = 1; cellNum <= 9; cellNum++)
            {
                var cell = line.GetCell(cellNum);
                if (!cell.Filled && cell.Candidates.Contains(candidate))
                {
                    cellNumbers.Add(cellNum);
                }
            }
            if (cellNumbers.Count == 2 || cellNumbers.Count == 3)
            {
                // Check if our candidates are all in the same box number
                int  boxNum = 0;
                bool valid  = true;
                foreach (var cellNum in cellNumbers)
                {
                    int currentBoxNum;
                    if (isColumn)
                    {
                        currentBoxNum = Helpers.BoxNumber(lineNum, cellNum);
                    }
                    else
                    {
                        currentBoxNum = Helpers.BoxNumber(cellNum, lineNum);
                    }
                    if (boxNum == 0)
                    {
                        // First cell - record the box number
                        boxNum = currentBoxNum;
                    }
                    else if (boxNum != currentBoxNum)
                    {
                        // Subsequent cell was not in the same box number
                        valid = false;
                        break;
                    }
                }
                if (valid)
                {
                    // Remove this candidate from all the other cells in the box
                    IList <int> skipCells;
                    if (isColumn)
                    {
                        if (lineNum % 3 == 1)
                        {
                            skipCells = Constants.BoxLeftCol;
                        }
                        else if (lineNum % 3 == 2)
                        {
                            skipCells = Constants.BoxMiddleCol;
                        }
                        else
                        {
                            skipCells = Constants.BoxRightCol;
                        }
                    }
                    else
                    {
                        if (lineNum % 3 == 1)
                        {
                            skipCells = Constants.BoxTopRow;
                        }
                        else if (lineNum % 3 == 2)
                        {
                            skipCells = Constants.BoxMiddleRow;
                        }
                        else
                        {
                            skipCells = Constants.BoxBottomRow;
                        }
                    }

                    var  box         = _puzzle.GetBox(boxNum);
                    bool boxProgress = false;
                    for (int b = 1; b <= 9; b++)
                    {
                        if (!skipCells.Contains(b))
                        {
                            // This cell isnt in our column/row - remove the candidate
                            var boxCell = box.GetCell(b);
                            if (boxCell.EliminateCandidate(candidate, Name))
                            {
                                boxProgress = true;
                            }
                        }
                    }
                    if (boxProgress)
                    {
                        progress = true;
                        if (isColumn)
                        {
                            _logger.Log(Name, $"{candidate}s all in a column in box {boxNum}");
                        }
                        else
                        {
                            _logger.Log(Name, $"{candidate}s all in a row in box {boxNum}");
                        }
                    }
                }
            }
        }
        return(progress);
    }
예제 #17
0
        public async Task <Result> Run()
        {
            var templates = _configurationExplorer.Explore(_options.SourcePath, _options.ConfigurationFiles);

            if (templates.State == Result.Error)
            {
                return(Result.Error);
            }

            var buildGraphResult = _buildGraphFactory.Create(templates.Value);

            if (buildGraphResult.State == Result.Error)
            {
                return(Result.Error);
            }

            var buildGraphsResult = _buildGraphsFactory.Create(buildGraphResult.Value);

            if (buildGraphsResult.State == Result.Error)
            {
                return(Result.Error);
            }

            var buildGraphs = buildGraphsResult.Value.ToList();

            if (!buildGraphs.Any())
            {
                _logger.Log("Nothing to build.", Result.Error);
                return(Result.Error);
            }

            var dockerFilesRootPath = _fileSystem.UniqueName;
            var contextStreamResult = await _contextFactory.Create(dockerFilesRootPath, buildGraphResult.Value.Nodes.Select(i => i.Value).OfType <Image>().Select(i => i.File));

            if (contextStreamResult.State == Result.Error)
            {
                return(Result.Error);
            }

            var contextStream = contextStreamResult.Value;

            using (contextStream)
                using (_logger.CreateBlock("Build"))
                {
                    foreach (var buildGraph in buildGraphs)
                    {
                        var nameResult = _nodesDescriptionFactory.Create(buildGraph.Nodes);
                        var name       = nameResult.State != Result.Error ? nameResult.Value.Name : "Unnamed graph";
                        if (!string.IsNullOrWhiteSpace(_options.FilterRegex) && !new Regex(_options.FilterRegex).IsMatch(name))
                        {
                            _logger.Log($"\"{name}\" was skipped according to filter \"{_options.FilterRegex}\".", Result.Warning);
                            continue;
                        }

                        using (_logger.CreateBlock(name))
                        {
                            var buildPath = _buildPathProvider.GetPath(buildGraph).ToList();
                            foreach (var buildNode in buildPath)
                            {
                                switch (buildNode.Value)
                                {
                                case Image image:
                                    var dockerFile = image.File;
                                    using (_logger.CreateBlock(dockerFile.ToString()))
                                    {
                                        var id     = Guid.NewGuid().ToString();
                                        var labels = new Dictionary <string, string> {
                                            { "InternalImageId", id }
                                        };

                                        var tags = (
                                            from tag in dockerFile.Tags
                                            select $"{dockerFile.ImageId}:{tag}")
                                                   .Distinct()
                                                   .ToList();

                                        contextStream.Position = 0;
                                        var dockerFilePathInContext = _pathService.Normalize(Path.Combine(dockerFilesRootPath, dockerFile.Path));
                                        var buildParameters         = new ImageBuildParameters
                                        {
                                            Dockerfile = dockerFilePathInContext,
                                            Tags       = tags,
                                            PullParent = true,
                                            Labels     = labels
                                        };

                                        using (var buildEventStream = await _dockerClient.Images.BuildImageFromDockerfileAsync(
                                                   contextStream,
                                                   buildParameters,
                                                   _cancellationTokenSource.Token))
                                        {
                                            _streamService.ProcessLines(buildEventStream, line => { _messageLogger.Log(line); });
                                        }

                                        var filter = new Dictionary <string, IDictionary <string, bool> >
                                        {
                                            { "label", labels.ToDictionary(i => $"{i.Key}={i.Value}", _ => true) }
                                        };

                                        var images = await _dockerClient.Images.ListImagesAsync(new ImagesListParameters { Filters = filter });

                                        if (images.Count == 0)
                                        {
                                            _logger.Log($"Error while building the image {dockerFile}", Result.Error);
                                            return(Result.Error);
                                        }
                                    }

                                    break;
                                }
                            }
                        }
                    }
                }

            return(Result.Success);
        }
예제 #18
0
 public void Trace(string message, params object[] arguments)
 {
     traceLogger.Log(message, arguments);
 }
예제 #19
0
 public void Error(string message, params object[] arguments)
 {
     errorLogger.Log(message, arguments);
 }
예제 #20
0
    public bool FindSwordfish(Puzzle puzzle, bool columnsSearch)
    {
        bool progress = false;
        var  lineCandidatePositions = new Dictionary <char, List <int> > [10];

        for (int lineNum = 1; lineNum <= 9; lineNum++)
        {
            var   candidatePositions = new Dictionary <char, List <int> >();
            Group line;
            if (columnsSearch)
            {
                line = puzzle.GetColumn(lineNum);
            }
            else
            {
                line = puzzle.GetRow(lineNum);
            }
            for (int cellNum = 1; cellNum <= 9; cellNum++)
            {
                var cell = line.GetCell(cellNum);
                if (!cell.Filled)
                {
                    foreach (var candidate in cell.Candidates)
                    {
                        if (candidatePositions.ContainsKey(candidate))
                        {
                            candidatePositions[candidate].Add(cellNum);
                        }
                        else
                        {
                            candidatePositions[candidate] = new List <int> {
                                cellNum
                            };
                        }
                    }
                }
            }
            lineCandidatePositions[lineNum] = new Dictionary <char, List <int> >();
            foreach (var candidate in candidatePositions.Keys)
            {
                if (candidatePositions[candidate].Count == 2 || candidatePositions[candidate].Count == 3)
                {
                    lineCandidatePositions[lineNum].Add(candidate, candidatePositions[candidate]);
                }
            }
        }

        // Phew OK we've now got for each line a list of candidates and which 2 or 3 cell numbers they appear in
        for (int firstLineNum = 1; firstLineNum <= 7; firstLineNum++)
        {
            for (int secondLineNum = firstLineNum + 1; secondLineNum <= 8; secondLineNum++)
            {
                for (int thirdLineNum = secondLineNum + 1; thirdLineNum <= 9; thirdLineNum++)
                {
                    var firstLineCandidates = lineCandidatePositions[firstLineNum];
                    foreach (var candidate in firstLineCandidates.Keys)
                    {
                        var secondLineCandidates = lineCandidatePositions[secondLineNum];
                        var thirdLineCandidates  = lineCandidatePositions[thirdLineNum];
                        if (secondLineCandidates.ContainsKey(candidate) && thirdLineCandidates.ContainsKey(candidate))
                        {
                            // Check if the three lines have the candidate within the same 3 positions
                            var allCandidateCells = firstLineCandidates[candidate]
                                                    .Union(secondLineCandidates[candidate])
                                                    .Union(thirdLineCandidates[candidate])
                                                    .ToList();

                            if (allCandidateCells.Count == 3)
                            {
                                // We've found a Swordfish
                                if (columnsSearch)
                                {
                                    _logger.Log(Name, $"{candidate} in cols {firstLineNum}, {secondLineNum}, {thirdLineNum} rows {allCandidateCells[0]}, {allCandidateCells[1]}, {allCandidateCells[2]}", LogItemLevel.Debug);
                                }
                                else
                                {
                                    _logger.Log(Name, $"{candidate} in rows {firstLineNum}, {secondLineNum}, {thirdLineNum} cols {allCandidateCells[0]}, {allCandidateCells[1]}, {allCandidateCells[2]}", LogItemLevel.Debug);
                                }

                                // Eliminate any other instances of candidate from the 3 perpendicular lines
                                IEnumerable <Group> lines;
                                if (columnsSearch)
                                {
                                    lines = allCandidateCells.Select(c => puzzle.GetRow(c));
                                }
                                else
                                {
                                    lines = allCandidateCells.Select(c => puzzle.GetColumn(c));
                                }
                                var lineProgress = new HashSet <Group>();
                                for (int cell = 1; cell <= 9; cell++)
                                {
                                    if (cell != firstLineNum && cell != secondLineNum && cell != thirdLineNum)
                                    {
                                        foreach (var line in lines)
                                        {
                                            if (line.GetCell(cell).EliminateCandidate(candidate, Name))
                                            {
                                                lineProgress.Add(line);
                                            }
                                        }
                                    }
                                }
                                foreach (var line in lineProgress)
                                {
                                    _logger.Log(Name, $"Removed {candidate}s in {line.Description}");
                                    progress = true;
                                }
                            }
                        }
                    }
                }
            }
        }
        return(progress);
    }
예제 #21
0
 public void Info(string message, params object[] arguments)
 {
     infoLogger.Log(message, arguments);
 }
예제 #22
0
    public bool Apply(Puzzle puzzle)
    {
        bool progress = false;

        // For every 2 candidate cell, look for other cells it can see that also have 2 candidates
        for (int r = 1; r <= 9; r++)
        {
            var row = puzzle.GetRow(r);
            for (int c = 1; c <= 9; c++)
            {
                var hingeCell = row.GetCell(c);
                if (!hingeCell.Filled && hingeCell.Candidates.Count == 2)
                {
                    // Search the row, col and box for other cells with 2 candidates where 1 candidate is the same
                    var col            = puzzle.GetColumn(c);
                    var box            = puzzle.GetBox(Helpers.BoxNumber(c, r));
                    var potentialCells = new HashSet <Cell>();
                    for (int i = 1; i <= 9; i++)
                    {
                        if (i != c)
                        {
                            var rowCell = row.GetCell(i);
                            if (rowCell.TwoCandidatesWith1Intersection(hingeCell))
                            {
                                potentialCells.Add(rowCell);
                            }
                        }
                        if (i != r)
                        {
                            var colCell = col.GetCell(i);
                            if (colCell.TwoCandidatesWith1Intersection(hingeCell))
                            {
                                potentialCells.Add(colCell);
                            }
                        }
                        var boxCell = box.GetCell(i);
                        if (boxCell.Col != c && boxCell.Row != r)
                        {
                            if (boxCell.TwoCandidatesWith1Intersection(hingeCell))
                            {
                                potentialCells.Add(boxCell);
                            }
                        }

                        // Find any pairs of cells that make sense????
                        var potentials = potentialCells.ToArray();
                        for (int p1 = 0; p1 < potentialCells.Count - 1; p1++)
                        {
                            for (int p2 = p1 + 1; p2 < potentialCells.Count; p2++)
                            {
                                var potential1 = potentials[p1];
                                var potential2 = potentials[p2];

                                var intersectionCandidates = potential1.Candidates.Intersect(potential2.Candidates);
                                if (intersectionCandidates.Count() != 1)
                                {
                                    // Y Wing cells need 1 candidate in common
                                    break;
                                }
                                var intersectionCandidate = intersectionCandidates.First();
                                if (hingeCell.Candidates.Contains(intersectionCandidate))
                                {
                                    // Candidate in common needs to be something not in the hinge cell
                                    break;
                                }

                                // We have found a Y Wing - find any candidates to delete
                                // Get all the cells seen by p1 and p2 and remove candidate from the intersecting cells
                                HashSet <Cell> seen1 = new HashSet <Cell>(puzzle.GetRow(potential1.Row).Cells);
                                seen1.UnionWith(puzzle.GetColumn(potential1.Col).Cells);
                                seen1.UnionWith(puzzle.GetBox(Helpers.BoxNumber(potential1.Col, potential1.Row)).Cells);

                                HashSet <Cell> seen2 = new HashSet <Cell>(puzzle.GetRow(potential2.Row).Cells);
                                seen2.UnionWith(puzzle.GetColumn(potential2.Col).Cells);
                                seen2.UnionWith(puzzle.GetBox(Helpers.BoxNumber(potential2.Col, potential2.Row)).Cells);

                                seen1.IntersectWith(seen2);
                                seen1.Remove(potential1);
                                seen1.Remove(potential2);

                                var latestProgress = false;

                                foreach (var elimCell in seen1)
                                {
                                    if (elimCell.EliminateCandidate(intersectionCandidate, Name))
                                    {
                                        latestProgress = true;
                                    }
                                }

                                if (latestProgress)
                                {
                                    progress = true;
                                    _logger.Log(Name, $"({hingeCell.Col},{hingeCell.Row}), ({potential1.Col},{potential1.Row}), ({potential2.Col},{potential2.Row}) eliminated {intersectionCandidate}s successfully");
                                }
                            }
                        }
                    }
                }
            }
        }
        return(progress);
    }
예제 #23
0
 public void Warning(string message, params object[] arguments)
 {
     warningLogger.Log(message, arguments);
 }
예제 #24
0
    private bool CheckGroup(Group group)
    {
        bool progress = false;
        // Get all the numbers not already filled in the group
        var candidates = new HashSet <char>(Constants.AllValues);

        for (int cell = 1; cell <= 9; cell++)
        {
            var cellData = group.GetCell(cell);
            if (cellData.Given || cellData.Filled)
            {
                candidates.Remove(cellData.Value);
            }
        }

        // Iterate all pairs of possible candidates
        var candidatesList = new List <char>(candidates);
        int combos         = Helpers.Factorial(candidates.Count) / (2 * Helpers.Factorial(candidates.Count - 2));

        // _logger.Log(Name, $"Hidden pairs: searching in {group.Description} with {combos} pair combos");
        for (var i = 0; i < candidatesList.Count - 1; i++)
        {
            var candidate1 = candidatesList[i];
            for (var j = i + 1; j < candidatesList.Count; j++)
            {
                var candidate2 = candidatesList[j];

                // Find all cells containing both of the candidates
                var rejected = false;
                var inCells  = new List <int>();
                for (int cell = 1; cell <= 9; cell++)
                {
                    var cellData = group.GetCell(cell);
                    if (cellData.Given || cellData.Filled)
                    {
                        continue;
                    }
                    if (cellData.Candidates.Contains(candidate1))
                    {
                        if (cellData.Candidates.Contains(candidate2))
                        {
                            if (inCells.Count > 1)
                            {
                                // This pair is in too many cells
                                rejected = true;
                                break;
                            }
                            inCells.Add(cell);
                        }
                        else
                        {
                            rejected = true;
                            break;
                        }
                    }
                    else if (cellData.Candidates.Contains(candidate2))
                    {
                        rejected = true;
                        break;
                    }
                }
                if (rejected)
                {
                    continue;
                }
                if (inCells.Count == 2)
                {
                    // We found a hidden pair! Expose it
                    foreach (var cellNum in inCells)
                    {
                        var cellData = group.GetCell(cellNum);
                        if (cellData.SetOnlyCandidates(new char[] { candidate1, candidate2 }, Name))
                        {
                            _logger.Log(Name, $"Hidden pairs: hidden pair {candidate1}{candidate2} exposed in {group.Description}");
                            // Re-check all candidates before moving on to the next group
                            //puzzle.CheckAllGroups();
                            progress = true;
                        }
                    }
                }
            }
        }
        return(progress);
    }