using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SudokuSolver
{
public class STable
{
readonly static int SPSIZE = 81;
int[] SPlacesInit = new int[SPSIZE];
int[] SPlaces = new int[SPSIZE];
List<int[]> SAreas;
public STable()
{
SAreas = new List<int[]>();
//Areas
for(int ia = 0; ia<9; ia++)
{
//Row
int[] ira = new int[9];
for(int ir = 0; ir <9; ir++)
{
ira[ir] = 9 * ia + ir;
}
SAreas.Add(ira);
//Col
int[] ica = new int[9];
for (int ic = 0; ic < 9; ic++)
{
ica[ic] = 9 * ic + ia;
}
SAreas.Add(ica);
//Block
int[] iba = new int[9];
for (int ib = 0; ib < 9; ib++)
{
iba[ib] = ((int)(ia / 3) * 27 + (ia % 3) * 3) + ((int)(ib / 3) * 9 + ib % 3);
}
SAreas.Add(iba);
}
}
public bool LoadTable(Dictionary<int, int> Values)
{
foreach (KeyValuePair<int, int> kvp in Values)
{
if (kvp.Key > 0 && kvp.Key < SPSIZE &&
kvp.Value >= 0 && kvp.Value <= 9)
SPlacesInit[kvp.Key] = kvp.Value;
else
{
Array.Clear(SPlacesInit, 0, SPSIZE);
return false;
}
}
if (TestAreas())
{
Array.Copy(SPlacesInit, SPlaces, SPSIZE);
return true;
}
else
{
Array.Clear(SPlacesInit, 0, SPSIZE);
return false;
}
}
public bool LoadTable(List<int> Values)
{
if (Values.Count != SPSIZE)
return false;
int counter = 0;
foreach (int value in Values)
{
if (value < 0 && value > 9)
{
Array.Clear(SPlacesInit, 0, SPSIZE);
return false;
}
SPlacesInit[counter] = value;
counter++;
}
if (TestAreas())
{
Array.Copy(SPlacesInit, SPlaces, SPSIZE);
return true;
}
else
{
Array.Clear(SPlacesInit, 0, SPSIZE);
return false;
}
}
private List<int[]> GetAreas(int Place)
{
return SAreas.FindAll(arr => arr.Contains(Place));
}
private List<int> AvailableValues(int Place)
{
List<int> Avaliable = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
List<int[]> RespectiveAreas = GetAreas(Place);
foreach (int[] Area in RespectiveAreas)
foreach (int TPlace in Area)
if (SPlaces[TPlace] != 0)
Avaliable.Remove(SPlaces[TPlace]);
return Avaliable;
}
public bool TestAreas()
{
for (int ix = 0; ix<SPSIZE ; ix ++)
{
if (SPlaces[ix] == 0)
{
List<int> AV = AvailableValues(ix);
if (AV.Count == 0)
return false;
}
}
return true;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
for (int ix = 0; ix < SPSIZE;)
{
sb.Append(SPlaces[ix]);
ix++;
if (ix % 9 == 0)
sb.Append(Environment.NewLine);
else if (ix % 3 == 0)
sb.Append("|");
if (ix % 27 == 0)
{
sb.Append("---+---+---");
sb.Append(Environment.NewLine);
}
}
return sb.ToString();
}
public bool FillTable()
{
Console.Clear();
int cPos = 0;
bool rollbacked = false;
while (cPos < SPSIZE)
{
//Console.SetCursorPosition(0, 0);
//Console.Write(this.ToString());
int cValue = SPlaces[cPos];
if (!rollbacked && cValue > 0 && TestAreas())
{
cPos++;
rollbacked = false;
continue;
}
else if (cValue > 0 && (rollbacked || !TestAreas()))
{
List<int> AV = AvailableValues(cPos);
var cNewValues = from v in AV
where v > cValue
select v;
if (cNewValues.Count() == 0)
{
//Rollback
SPlaces[cPos] = 0;
cPos--;
while (SPlacesInit[cPos] != 0)
{
if (cPos < 0)
return false;
cPos--;
}
rollbacked = true;
}
else
{
//New Position Value
SPlaces[cPos] = cNewValues.Min();
rollbacked = false;
}
}
else if (cValue == 0)
{
List<int> AV = AvailableValues(cPos);
var cNewValues = from v in AV
where v > cValue
select v;
SPlaces[cPos] = cNewValues.Min();
rollbacked = false;
}
else
{
//Should not be
return false;
}
}
return true;
}
}
}