Today I wanted to write a program that solves a sudoku.
When my approach didn't quite work I resorted to a solution found here: http://www.heimetli.ch/ffh/simplifiedsudoku.html
But for some reason, I keep getting a StackOverflow Exception.
This is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Sudoku_Solver
{
class Program
{
static void Main(string[] args)
{
MainClass _mainClass = new MainClass();
_mainClass.printSudoku();
Console.ReadLine();
}
}
class MainClass
{
private const int FieldsVertical = 3, FieldsHorizontal = 3;
private const int RowsInField = 3, ColumnsInField = 3;
Thread _sudokuSolverThread;
private int[,] Sudoko = new int[(FieldsVertical * ColumnsInField), (FieldsHorizontal * RowsInField)]{
{ 4, 0, 2, 0, 3, 0, 0, 0, 0},
{ 7, 0, 8, 0, 4, 2, 0, 9, 0},
{ 0, 0, 0, 8, 0, 5, 4, 0, 0},
{ 0, 8, 0, 0, 0, 4, 2, 0, 9},
{ 0, 9, 4, 2, 0, 6, 8, 1, 0},
{ 6, 0, 1, 7, 0, 0, 0, 3, 0},
{ 0, 0, 9, 5, 0, 3, 0, 0, 0},
{ 0, 3, 0, 4, 6, 0, 7, 0, 2},
{ 0, 0, 0, 0, 2, 0, 9, 0, 3},
};
public MainClass(){ }
private void startSudokuSolver()
{
solveSudoku(0, 0);
}
private bool solveSudoku(int row, int col)
{
if (Sudoko[row, col] != 0)
{
return next(row, col++);
}
else
{
for (int i = 0; i < ColumnsInField * RowsInField; i++)
{
if (checkColumn(i, row) && checkField(i, row, col) && checkRow(i, col))
{
Sudoko[row, col] = i;
//Thread.Sleep(10);
return next(row, col++);
}
}
Sudoko[row, col] = 0;
return false;
}
}
private bool next(int row, int col)
{
if (row == 9)
{
return false;
}
else
{
if (col == 9)
{
return solveSudoku(row++, 0);
}
else
{
return solveSudoku(row, col);
}
}
}
public void printSudoku()
{
startSudokuSolver();
for (int i = 0; i < Sudoko.GetLength(0); i++)
{
for (int x = 0; x < Sudoko.GetLength(1); x++)
{
Console.Write(Sudoko[i, x] + " ");
}
Console.Write(Environment.NewLine);
}
}
private bool checkRow(int number, int col)
{
for (int row = 0; row < FieldsVertical * RowsInField; row++)
{
if (Sudoko[row, col] == number)
{
return false;
}
}
return true;
}
private bool checkColumn(int number, int row)
{
for (int column = 0; column < FieldsHorizontal * ColumnsInField; column++)
{
if (Sudoko[row, column] == number)
{
return false;
}
}
return true;
}
int _currentFieldRow;
int _currentFieldColumn;
private bool checkField(int number, int row, int col)
{
_currentFieldRow = (row / RowsInField) * RowsInField;
_currentFieldColumn = (col / ColumnsInField) * ColumnsInField;
for (int a = _currentFieldRow; a < _currentFieldRow + RowsInField; a++)
{
for (int b = _currentFieldColumn; b < _currentFieldColumn + ColumnsInField; b++)
{
if (Sudoko[a, b] == number)
{
return false;
}
}
}
return true;
}
}
}
E.g. here
return solveSudoku(row++, 0);
the original value of row is passed to the function solveSudoku (and after that row is incremented). Change it to row + 1.
The reason for the StackOverflowException is in the next() method. Change
return solveSudoku(row, col);
to
return solveSudoku(row, ++col);
This does at least solve the StackOverflowException. Anyway, you need to enhance the algorithm further as it does not solve the complete Sudoku yet.
Related
The following picture is retrieved from Wikipedia:
I haven't understood this part:
I have two questions here:
Where did they obtain [8,4,1,2] from and what did they want to tell us by that?
Take a look at cell [0, 0] whose value is 13. If I go clockwise along with its contouring values, I obtain the binary string 0010 which is 2. How does the 1st cell-value become 13?
.
enum What
{
lines, surface, both
}
class Program
{
public static void Print(int[,] data, int xn, int yn)
{
for (int j = 0; j < yn; j++)
{
for (int i = 0; i < xn; i++)
{
Console.Write(data[i,j] + ", ");
}
Console.WriteLine();
}
}
public static int[,] normalize(int[,] data, int xn, int yn)
{
for (int j = 0; j < yn; j++)
{
for (int i = 0; i < xn; i++)
{
if (data[i, j] > 1)
{
data[i, j] = 0;
}
else
{
data[i, j] = 1;
}
}
}
return data;
}
public static int[,] marching_square(int x, int y, int[,] data, int isovalue, What what)
{
int xn = x;
int yn = y;
data = normalize(data, xn, yn);
int[,] bitMask = new int[xn - 1, yn - 1];
for (int j = 0; j < yn - 1; j++)
{
for (int i = 0; i < xn - 1; i++)
{
StringBuilder sb = new StringBuilder();
sb.Append(data[i, j]);
sb.Append(data[i, j + 1]);
sb.Append(data[i + 1, j]);
sb.Append(data[i + 1, j + 1]);
bitMask[i, j] = Convert.ToInt32(sb.ToString(), 2);
}
}
return bitMask;
}
static void Main(string[] args)
{
int[,] data = new int[,] {
{ 1,1,1,1,1 },
{ 1,2,3,2,1 },
{ 1,3,3,3,1 },
{ 1,2,3,2,1 },
{ 1,1,1,1,1 }
};
Print(data, 5,5);
int[,] bitMask = marching_square(5,5,data, 0, What.lines);
Print(bitMask, 4, 4);
}
}
Output:
1, 1, 1, 1, 1,
1, 2, 3, 2, 1,
1, 3, 3, 3, 1,
1, 2, 3, 2, 1,
1, 1, 1, 1, 1,
14, 10, 10, 11,
12, 0, 0, 3,
12, 0, 0, 3,
13, 5, 5, 7,
I inverted the bits. But, the output looks different.
How find template in array ?
Template
int[] = {X, X, X}; //(example 3,3,3)
, or template
int[,] temp2 =
{
{X, X, ?}
{?, X, X}
}
Example
int[,] temp2 =
{
{3, 3, 1}
{2, 3, 3}
}
For example, in such an array?
int[,] a = new int[,]
{
{ 1, 4, 5, 3, 4 },
{ 1, 2, 3, 1, 3 },
{ 1, 1, 2, 4, 4 },
{ 4, 4, 3, 3, 3 },
{ 3, 4, 4, 5, 5 }
};
Is there a faster way than searching each cell and its neighboring cells?
If you are looking for patterns inside a bigger array, probably checking cell by cell is the only way to do it. You could do some complex optimizations for skipping the ? values and speedup a little, but I don't think it would easily work.
A sample code that should do what you asked:
// null means anything is ok, X is 0, Y is 1, Z is 2...
int?[,] temp = new int?[,]
{
{0, 0, null},
{null, 0, 0}
};
int[,] a = new int[,]
{
{ 0, 1, 1, 2, 4, 4, 1 },
{ 0, 1, 4, 4, 3, 3, 3 },
{ 0, 2, 3, 4, 4, 5, 5 }
};
int row, col;
bool success = CheckPattern(temp, a, out row, out col);
Console.WriteLine("Success: {0}, row: {1}, col: {2}", success, row, col);
and then
private static bool CheckPattern(int?[,] temp, int[,] data, out int row, out int col)
{
int rowsT = temp.GetLength(0);
int colsT = temp.GetLength(1);
int rowsD = data.GetLength(0);
int colsD = data.GetLength(1);
// Find the "maximum" value of the template (how many different
// condition are there... If there is only "X" then 1, "X", "Y" then 2,
// "X", "Y", "Z" then 3...
int max = -1;
for (int i = 0; i < rowsT; i++)
{
for (int j = 0; j < rowsT; j++)
{
if (temp[i, j] != null)
{
max = Math.Max(temp[i, j].Value, max);
}
}
}
// We save in an array the "current" values of "X", "Y", "Z", ...
int?[] values = new int?[max + 1];
for (int i = 0; i < rowsD - rowsT + 1; i++)
{
for (int j = 0; j < colsD - colsT + 1; j++)
{
Array.Clear(values, 0, values.Length);
bool success = true;
// Check the template
for (int k = 0; k < rowsT; k++)
{
for (int r = 0; r < colsT; r++)
{
if (temp[k, r] != null)
{
int? curr = values[temp[k, r].Value];
if (curr == null)
{
// If this is the first time we check this
// condition, then any value is good
values[temp[k, r].Value] = data[i + k, j + r];
}
else if (curr.Value == data[i + k, j + r])
{
// For subsequent instances we check this
// condition, then the data must have the
// value found in the previous instance
}
else
{
success = false;
break;
}
}
}
if (!success)
{
break;
}
}
if (success)
{
row = i;
col = j;
return true;
}
}
}
row = 0;
col = 0;
return false;
}
This piece of code should work even for multiple conditions "X", "Y"...
I'm learning how to program, I have used other languages before mainly for web, but c# is a bit hard to understand at least for me, and msdn site is so complex or I don't know to use it properly. Trying to build program that solve sudoku puzzles, I run into problem when I try to display two dimensional array in a method, getting 2 errors:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
int[,] board = new int[9, 9] {{7, 2, 5, 8, 0, 4, 9, 1, 3},
{0, 0, 0, 0, 3, 0, 0, 0, 4},
{0, 0, 0, 0, 0, 1, 8, 2, 6},
{0, 0, 9, 0, 0, 0, 0, 0, 7},
{0, 1, 0, 6, 2, 8, 0, 4, 0},
{2, 0, 0, 0, 0, 0, 5, 0, 0},
{3, 6, 8, 4, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 7, 0, 0, 0, 8},
{0, 0, 0, 0, 0, 2, 6, 9, 5}};
DisplayBoard(board);
List<int> missing = new List<int>();
List<int> present = new List<int>();
int temp = 0;
for (int i = 0; i < 1; i++)
{
for (int j = 0; j < 9; j++)
{
//Console.Write(board[i, j]);
if (board[i, j] == 0)
{
missing.Add(j);
}
else
{
present.Add(board[i, j]);
}
if (present.Count == 8)
{
for (int x = 0; x < present.Count; x++)
{
if (!present.Contains(x))
{
temp = x;
}
}
board[i, missing[0]] = temp;
}
}
//missing.ForEach(Console.WriteLine);
}
DisplayBoard(board);
}
static void DisplayBoard(int[,])
{
for (int i = 0; i < 1; i++)
{
for (int j = 0; j < 9; j++)
{
Console.Write(board[i, j]);
}
}
}
}
You didn't give name to the parameter of DisplayBoard method
static void DisplayBoard(int[,] board)
{
for (int i = 0; i < 1; i++)
{
for (int j = 0; j < 9; j++)
{
Console.Write(board[i, j]);
}
}
}
How to create a method for insertion sort using boundaries specifically left and right.
public static void InsertionWorker<TYPE>(TYPE[] data, int left, int right) where TYPE : IComparable<TYPE>
{
TYPE temp;
for (int firstSorted = 0; firstSorted < data.Length - 1; firstSorted++)
for (int current = firstSorted + 1; current > 0; current--)
{
if (data[current - 1].CompareTo(data[current]) < 0)
{
temp = data[current - 1];
data[current - 1] = data[current];
data[current] = temp;
}
current--;
}
}
public static void Insertion<TYPE>(TYPE[] data) where TYPE : IComparable<TYPE>
{
InsertionWorker(data, 0, data.Length - 1);
}
Implementation of Insertion sort in C# using left and right boundaries:
class Program
{
public static void InsertionWorker<T>(T[] data, int left, int right) where T : IComparable<T>
{
for (var i = left; i < right + 1; i++)
{
T tmp = data[i];
int j;
for (j = i - 1; j >= left && tmp.CompareTo(data[j]) < 0; j--)
{
data[j + 1] = data[j];
}
data[j + 1] = tmp;
}
}
static void Main(string[] args)
{
// test data array
var a = new[] {234, 2, 11111, 34, 24, 23, 4, 432, 42, 423, 1, 4, 123, 124, 32, 345, 45, 3, 7, 56,9999999};
// Run insertion sort by provided boundaries
InsertionWorker(a, 7, a.Length-1);
// InsertionWorker(a, 0, 8);
foreach (int t in a)
{
Console.WriteLine(t);
}
Console.ReadKey();
}
}
Insertion sort
I have a 2D array as follows:
long[,] arr = new long[4, 4] {{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 },
{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 }};
I want to print the values of this array in matrix format like:
0 0 0 0
1 1 1 1
0 0 0 0
1 1 1 1
How can I do this?
You can do it like this (with a slightly modified array to show it works for non-square arrays):
long[,] arr = new long[5, 4] { { 1, 2, 3, 4 }, { 1, 1, 1, 1 }, { 2, 2, 2, 2 }, { 3, 3, 3, 3 }, { 4, 4, 4, 4 } };
int rowLength = arr.GetLength(0);
int colLength = arr.GetLength(1);
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
Console.Write(string.Format("{0} ", arr[i, j]));
}
Console.Write(Environment.NewLine + Environment.NewLine);
}
Console.ReadLine();
like so:
long[,] arr = new long[4, 4] { { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 1, 1, 1, 1 } };
var rowCount = arr.GetLength(0);
var colCount = arr.GetLength(1);
for (int row = 0; row < rowCount; row++)
{
for (int col = 0; col < colCount; col++)
Console.Write(String.Format("{0}\t", arr[row,col]));
Console.WriteLine();
}
I wrote extension method
public static string ToMatrixString<T>(this T[,] matrix, string delimiter = "\t")
{
var s = new StringBuilder();
for (var i = 0; i < matrix.GetLength(0); i++)
{
for (var j = 0; j < matrix.GetLength(1); j++)
{
s.Append(matrix[i, j]).Append(delimiter);
}
s.AppendLine();
}
return s.ToString();
}
To use just call the method
results.ToMatrixString();
Here is how to do it in Unity:
(Modified answer from #markmuetz so be sure to upvote his answer)
int[,] rawNodes = new int[,]
{
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 }
};
private void Start()
{
int rowLength = rawNodes.GetLength(0);
int colLength = rawNodes.GetLength(1);
string arrayString = "";
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
arrayString += string.Format("{0} ", rawNodes[i, j]);
}
arrayString += System.Environment.NewLine + System.Environment.NewLine;
}
Debug.Log(arrayString);
}
Your can do it like this in short hands.
int[,] values=new int[2,3]{{2,4,5},{4,5,2}};
for (int i = 0; i < values.GetLength(0); i++)
{
for (int k = 0; k < values.GetLength(1); k++) {
Console.Write(values[i,k]);
}
Console.WriteLine();
}
you can do like this also
long[,] arr = new long[4, 4] { { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 1, 1, 1, 1 }};
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
Console.Write(arr[i,j]+" ");
}
Console.WriteLine();
}
If using a square matrix:
int[,] mat = new int[,]{{ 1, 0, 0 },{ 0, 1, 0},{ 0, 0, 1}};
int i=1;
foreach(int e in mat){
Console.Write(i%Math.Sqrt(mat.Length)==0? $"{e}\n" : e);
i+=1;
}