Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gen 2 #12

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Sudoku/Extensions/IntArrayExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ namespace Sudoku.Extensions;

public static class IntArrayExtensions
{
public static bool IsValidSudoku(this int[] puzzle)
{
return SpanIntExtensions.IsValidSudoku(puzzle);
}

public static void DumpToConsole(this int[] array, int left = -1, int top = -1)
{
SetPosition(left, top, 0);
Expand Down
6 changes: 3 additions & 3 deletions src/Sudoku/Extensions/SpanIntExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ public static bool IsValidSudoku(this Span<int> puzzle)

for (var x = 0; x < 9; x++)
{
if (puzzle[x + y * 9] != 0)
if (puzzle[x + y * 9] > 0)
{
uniqueRow.Add(puzzle[x + y * 9]);

countRow++;
}

if (puzzle[y + x * 9] != 0)
if (puzzle[y + x * 9] > 0)
{
uniqueColumn.Add(puzzle[y + x * 9]);

Expand Down Expand Up @@ -55,7 +55,7 @@ public static bool IsValidSudoku(this Span<int> puzzle)
{
for (var y = 0; y < 3; y++)
{
if (puzzle[(yO + y) * 9 + xO + x] != 0)
if (puzzle[(yO + y) * 9 + xO + x] > 0)
{
uniqueBox.Add(puzzle[(yO + y) * 9 + xO + x]);

Expand Down
96 changes: 40 additions & 56 deletions src/Sudoku/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,97 +4,81 @@ namespace Sudoku;

public class Generator
{
private readonly List<int> _positions = new();

private readonly List<int>[] _candidates = new List<int>[81];

private int[] _puzzle;

private readonly Random _rng = Random.Shared;

private readonly Solver _solver = new(HistoryType.None, SolveMethod.FindUnique);

public int[] Generate(int cluesToLeave = 30)
{
var puzzle = new int[81];
_puzzle = new int[81];

InitialiseCandidates();

CreateSolvedPuzzle(puzzle);

RemoveCells(puzzle, 81 - cluesToLeave);

return puzzle;
GeneratePositions(cluesToLeave);

FillPositions(cluesToLeave);

return _puzzle;
}

private void RemoveCells(int[] puzzle, int cellsToRemove)
private void GeneratePositions(int cluesToLeave)
{
var copy = new int[81];

for (var i = 0; i < 81; i++)
{
copy[i] = puzzle[i];
}

var filledCells = new List<int>();

for (var i = 0; i < 81; i++)
{
filledCells.Add(i);
}

while (true)
_positions.Clear();

for (var i = 0; i < cluesToLeave; i++)
{
for (var i = 0; i < cellsToRemove; i++)
{
var cell = filledCells[_rng.Next(filledCells.Count)];

filledCells.Remove(cell);

puzzle[cell] = 0;
}
var position = _rng.Next(81);

if (_solver.Solve(puzzle).Solved)
while (_puzzle[position] != 0)
{
return;
position = _rng.Next(81);
}

for (var i = 0; i < 81; i++)
{
if (puzzle[i] == 0)
{
filledCells.Add(i);

puzzle[i] = copy[i];
}
}
_puzzle[position] = -1;

_positions.Add(position);
}
}

private bool CreateSolvedPuzzle(Span<int> puzzle, int cell = 0)
private bool FillPositions(int cluesToLeave, int position = 0)
{
while (_candidates[cell].Count > 0)
{
var candidateIndex = _rng.Next(_candidates[cell].Count);
InitialiseCandidates();

var candidate = _candidates[cell][candidateIndex];
var cell = _positions[position];

_candidates[cell].RemoveAt(candidateIndex);
while (_candidates[cell].Count > 0)
{
var index = _rng.Next(_candidates[cell].Count);

puzzle[cell] = candidate;
_puzzle[cell] = _candidates[cell][index];

_candidates[cell].RemoveAt(index);

if (puzzle.IsValidSudoku())
if (_puzzle.IsValidSudoku())
{
if (cell == 80)
if (position == cluesToLeave - 1)
{
return true;
return _solver.Solve(_puzzle).Solved;
}

return CreateSolvedPuzzle(puzzle, cell + 1);
return FillPositions(cluesToLeave, position + 1);
}
}

puzzle[cell] = 0;
if (position == 0)
{
return false;
}

_puzzle[cell] = -1;

_candidates[cell] = [1, 2, 3, 4, 5, 6, 7, 8, 9];

return CreateSolvedPuzzle(puzzle, cell - 1);
return FillPositions(cluesToLeave, position - 1);
}

private void InitialiseCandidates()
Expand Down