private void SetLineSolution(LineType lineType, int lineIndex, PicrossLine candidateToSet) { var targetSet = lineType == LineType.Column ? Columns : Rows; PicrossActiveLine target = targetSet.First(line => line.Index == lineIndex); target.ApplyLine(candidateToSet); }
private PicrossActiveLine[] GatherRows() { var rows = new PicrossActiveLine[RowCount]; for (int rowIndex = 0; rowIndex < RowCount; rowIndex++) { var rowCells = new List <PicrossCell>(); for (int columnIndex = 0; columnIndex < ColumnCount; columnIndex++) { rowCells.Add(Matrix[rowIndex, columnIndex]); } var rowRule = new PicrossLineRule( lineStructure: Puzzle.RowRules[rowIndex], lineLength: ColumnCount); rows[rowIndex] = new PicrossActiveLine( type: LineType.Row, index: rowIndex, cells: rowCells, rule: rowRule); } return(rows); }
private PicrossActiveLine[] GatherColumns() { var columns = new PicrossActiveLine[ColumnCount]; for (int columnIndex = 0; columnIndex < ColumnCount; columnIndex++) { var columnCells = new List <PicrossCell>(); for (int rowIndex = 0; rowIndex < RowCount; rowIndex++) { columnCells.Add(Matrix[rowIndex, columnIndex]); } var columnRule = new PicrossLineRule( lineStructure: Puzzle.ColumnRules[columnIndex], lineLength: RowCount); columns[columnIndex] = new PicrossActiveLine( type: LineType.Column, index: columnIndex, cells: columnCells, rule: columnRule); } return(columns); }
public PicrossActiveLine(IEnumerable <PicrossCell> cells, PicrossActiveLine copySource) : base(cells) { Type = copySource.Type; Index = copySource.Index; Rule = copySource.Rule; CandidateSolutions = new List <PicrossLine>(copySource.CandidateSolutions); RegisterCellHandlers(); }
private async Task <PicrossBoard> SpeculativeSolveAsync(SpeculativeCallContext context) { var undeterminedLines = ActiveLines .Where(line => !line.IsSet); PicrossActiveLine speculationTarget = undeterminedLines .First(line => line.CandidateCount == undeterminedLines.Min(l => l.CandidateCount)); //todo: review this criteria. Max reduces memory footprint Random rng = new Random(); var candidateSolutions = speculationTarget.CandidateSolutions .OrderBy(cs => rng.Next()).ToArray(); int candidatesCount = candidateSolutions.Count(); for (int i = 0; i < candidatesCount; i++) { PicrossBoard speculativeBoard = new PicrossBoard(this); speculativeBoard.SetLineSolution( lineType: speculationTarget.Type, lineIndex: speculationTarget.Index, candidateToSet: candidateSolutions[i] ); SpeculativeCallContext speculativeContext = new SpeculativeCallContext() { depth = context?.depth + 1 ?? 1, optionIndex = i, optionsCount = candidatesCount }; var speculativeTask = new Task(() => speculativeBoard.Solve(VerboseLevel.Silent, speculativeContext)); speculativeTask.Start(); await speculativeTask.ConfigureAwait(false); if (speculativeBoard.IsValid && speculativeBoard.IsSolved) { return(speculativeBoard); } } return(null); }
private PicrossActiveLine[] CopyRows(PicrossBoard copySource) { var rows = new PicrossActiveLine[RowCount]; Parallel.ForEach( Enumerable.Range(0, RowCount), rowIndex => { var rowCells = new List <PicrossCell>(); for (int columnIndex = 0; columnIndex < ColumnCount; columnIndex++) { rowCells.Add(Matrix[rowIndex, columnIndex]); } rows[rowIndex] = new PicrossActiveLine( cells: rowCells, copySource: copySource.Rows.ElementAt(rowIndex)); }); return(rows); }
private PicrossActiveLine[] CopyColumns(PicrossBoard copySource) { var columns = new PicrossActiveLine[ColumnCount]; Parallel.ForEach( Enumerable.Range(0, ColumnCount), columnIndex => { var columnCells = new List <PicrossCell>(); for (int rowIndex = 0; rowIndex < RowCount; rowIndex++) { columnCells.Add(Matrix[rowIndex, columnIndex]); } columns[columnIndex] = new PicrossActiveLine( cells: columnCells, copySource: copySource.Columns.ElementAt(columnIndex)); }); return(columns); }
public void Solve( VerboseLevel verboseLevel = VerboseLevel.Silent, SpeculativeCallContext context = null) { if (!IsValid) { if (verboseLevel != VerboseLevel.Silent) { log.Info("Solving aborted, board invalid - " + BoardName(context)); } return; } if (verboseLevel != VerboseLevel.Silent) { log.Info("Start solving - " + BoardName(context)); } if (context == null) { SetDetermibableCells(); } CandidateExclusionSolve(verboseLevel); if (IsValid && !IsSolved) { var undeterminedLines = ActiveLines .Where(line => !line.IsSet); PicrossActiveLine speculationTarget = undeterminedLines .First(line => line.CandidateCount == undeterminedLines.Min(l => l.CandidateCount)); //todo: review this criteria. Max reduces memory footprint Random rng = new Random(); var candidateSolutions = speculationTarget.CandidateSolutions .OrderBy(cs => rng.Next()).ToArray(); int candidatesCount = candidateSolutions.Count(); for (int i = 0; i < candidatesCount; i++) { PicrossBoard speculativeBoard = new PicrossBoard(this); speculativeBoard.SetLineSolution( lineType: speculationTarget.Type, lineIndex: speculationTarget.Index, candidateToSet: candidateSolutions[i] ); SpeculativeCallContext speculativeContext = new SpeculativeCallContext() { depth = context?.depth + 1 ?? 1, optionIndex = i, optionsCount = candidatesCount }; speculativeBoard.Solve(verboseLevel, speculativeContext); if (speculativeBoard.IsValid && speculativeBoard.IsSolved) { this.Copy(speculativeBoard); return; } } } if (verboseLevel != VerboseLevel.Silent) { if (!IsSolved) { log.Info("Solving failed - " + BoardName(context)); } else { log.Info("Solving succeeded - " + BoardName(context)); } } }