Skip to content

Instantly share code, notes, and snippets.

@secretGeek
Last active June 30, 2017 19:42
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save secretGeek/eb1c37588d725fd2122d81f67ba3861f to your computer and use it in GitHub Desktop.
Save secretGeek/eb1c37588d725fd2122d81f67ba3861f to your computer and use it in GitHub Desktop.
void Main()
{
//testGenerating();
var grid = goodGrid();
//grid.Write().Dump();
grid.MakeGame();
//grid.Write().Dump();
var foundOne = false;
var game = grid.Write();
while(!foundOne)
{
try
{
grid.Assess();
foundOne = grid.FillInTheObvious();
if (foundOne)
{
game.Dump();
}
}
catch (InvalidDataException e)
{
//oookay. let's start again.
//"Oops".Dump();
grid = goodGrid();
grid.MakeGame();
game = grid.Write();
}
}
//grid.cells.Select(p => p.Value == null ? p.Possible.Count : p.Value).Dump();
}
private Grid goodGrid() {
Random r = new Random();
var success = false;
var grid = new Grid() { R = r};
while (!success)
{
//Util.ClearResults();
grid = new Grid() { R = r};
success = grid.Generate();
//grid.Write().Dump();
}
return grid;
}
private void testGenerating() {
Random r = new Random();
int b = 0;
for (int z = 0; z<100; z++) {
int a = 0;
b++;
var success = false;
Grid grid = new Grid() { R = r};
while(!success) {
a++;
//Util.ClearResults();
grid = new Grid() { R = r};
success = grid.Generate();
//grid.Write().Dump();
}
//grid.Write().Dump();
//a.Dump();
if (a >= 1590) {
//a.Dump();
//b.Dump();
//grid.Write().Dump();
}
}
}
// Define other methods and classes here
public class Grid
{
public List<Cell> cells = new List<Cell>();
public Random R { get; set; }
public Grid ()
{
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
cells.Add(new Cell { RowNumber = i, ColumnNumber = j, Value = null});
}
public string Write()
{
var result = new StringBuilder();
int row = 0;
int column = 0;
foreach(var c in cells)
{
result.Append((c.Value == null? "_" : c.Value.ToString()) + " ");
column++;
if (column >= 9)
{
column = 0;
row++;
result.AppendLine();
if (row % 3 == 0 && row < 9)
{
result.AppendLine("-------------------------------------");
}
} else if (column % 3 == 0)
{
result.Append(" | ");
}
else
{
result.Append(" ");
}
}
return result.ToString();
}
public string WritePossible()
{
var result = new StringBuilder();
int row = 0;
int column = 0;
foreach(var c in cells)
{
result.Append((c.Value != null? "_" : c.Possible.Count().ToString()) + " ");
column++;
if (column>=9) {
column = 0;
row++;
result.AppendLine();
if (row%3 == 0 && row < 9)
{
result.AppendLine("-------------------------------------");
}
}
else if (column % 3 == 0)
{
result.Append(" | ");
}
else
{
result.Append(" ");
}
}
return result.ToString();
}
public IEnumerable<Cell> GetRow(int rowNumber)
{
return this.cells.GetRange(rowNumber*9, 9);
}
public IEnumerable<Cell> GetColumn(int columnNumber)
{
var result = new List<Cell>();
for (int i = 0; i < 9; i++)
{
result.Add(this.cells[columnNumber + (i*9)]);
}
return result;
}
// Return the 3x3 'subgrid' to which this row/col belongs.
public IEnumerable<Cell> GetSubGrid(int columnNumber, int rowNumber)
{
int colN = (columnNumber / 3)*3 ;
int rowN = (rowNumber / 3)*3;
var result = new List<Cell>();
for(int i = 0; i< 3; i++)
{
result.AddRange(this.cells.GetRange((i*9)+(9*rowN) + colN, 3));
}
return result;
}
public bool MakeGame() {
var numbers = new List<int>();
for(int i = 0; i<9; i++)
{
numbers.Add(9);
}
var keepGoing = true;
int numberRemoved = 0;
while(keepGoing)
{
var x = R.Next(81);
var value = this.cells[x].Value;
if (value != null && numbers[(value ?? 1)-1] > 2)
{
this.cells[x].Value = null;
numbers[(value ?? 1)-1] = numbers[(value ?? 1)-1]-1;
numberRemoved++;
}
if (numberRemoved >= 50) {
keepGoing = false;
}
}
return true;
}
public bool FillInTheObvious()
{
var foundOne = false;
var nothingToSolve = true;
foreach(var c in this.cells)
{
if (c.Value == null)
{
nothingToSolve = false;
}
if (c.Possible != null && c.Possible.Count == 1)
{
var x = c.Possible.ToArray()[0];
c.Value = x;
foundOne = true;
}
}
if (nothingToSolve)
{
return true;
//Console.WriteLine("SOLVED!");
}
if (!foundOne)
{
throw new InvalidDataException("Data just not valid enough.");
}
return false;
}
public bool Assess()
{
foreach(var c in this.cells)
{
if (c.Value != null)
{
c.Possible = new HashSet<int>();
}
else
{
var numbers = new HashSet<int>(Enumerable.Range(1, 9));
c.Possible = numbers; //Anything is possible.
var row = this.GetRow(c.RowNumber);
foreach(var cell in row)
{
if (cell.Value != null)
{
c.Possible.Remove(cell.Value.Value);
}
}
var column = this.GetColumn(c.ColumnNumber);
foreach(var cell in column)
{
if (cell.Value != null)
{
c.Possible.Remove(cell.Value.Value);
}
}
var subGrid = this.GetSubGrid(c.ColumnNumber, c.RowNumber);
foreach(var cell in subGrid)
{
if (cell.Value != null)
{
c.Possible.Remove(cell.Value.Value);
}
}
}
}
return true;
}
public bool Generate()
{
for(int i = 1; i<=9; i++)
{
for(int j = 0; j<9; j++)
{
var row = GetRow(j).ToList();
var solved = false;
int tries = 0;
while(!solved)
{
tries++;
var candidatePosition = R.Next(9);
if (row[candidatePosition].Value == null
&& !GetColumn(candidatePosition).Any(c => c.Value == i)
&& !GetSubGrid(candidatePosition, j).Any(c => c.Value == i))
{
row[candidatePosition].Value = i;
solved = true;
}
if (!solved && tries > 50) {
return false;
}
}
}
}
return true;
}
}
public class Cell {
public int RowNumber { get; set; }
public int ColumnNumber { get; set; }
public int? Value { get; set; }
public HashSet<int> Possible { get; set;}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment