private bool GetMinRowCol_Rows(SkyscraperData d, out int row, out int col) { row = -1; col = -1; int currminbits = _n + 1; int setbits = 0; for (int i = 0; i < _n; i++) { int setbitsinrow = d.CountBits(d.SetInRow[i]); for (int j = 0; j < d.Rows[i].Count; j++) { int bits = d.CountBits(i, d.Rows[i][j]); if ((bits < currminbits) || ((bits == currminbits) && (setbitsinrow < setbits))) //w wierszu najmniej ustawionych bitow { row = i; col = d.Rows[i][j]; currminbits = bits; setbits = setbitsinrow; } } } return(currminbits != _n + 1); }
private bool GetMinRowCol_Default(SkyscraperData d, out int row, out int col) { row = -1; col = -1; int currminbits = _n + 1; int setbits = 0; for (int i = 0; i < _n; i++) { if (d.SetInRow[i] != SkyscraperData.InitialValues[_n]) { int setbitsinrow = d.CountBits(d.SetInRow[i]); for (int j = 0; j < _n; j++) { int bits = d.CountBits(i, j); if (bits > 1) { if ((bits < currminbits) || ((bits == currminbits) && (setbitsinrow < setbits))) //w wierszu najmniej ustawionych bitow { row = i; col = j; currminbits = bits; setbits = d.SetInRow[i]; } } } } } return(currminbits != _n + 1); }
private bool CheckDataUniqueElements(SkyscraperData d) { for (int i = 0; i < _n; i++) { int mask = 0, mask2 = 0; int cnt = 0, cnt2 = 0; for (int j = 0; j < _n; j++) { if (d.CountBits(i, j) == 1) { mask ^= d.Data[i, j]; cnt++; } if (d.CountBits(j, i) == 1) { mask2 ^= d.Data[j, i]; cnt2++; } } if ((d.CountBits(mask) != cnt) || (d.CountBits(mask2) != cnt2)) { return(false); } } return(true); }
private bool ReduceRowsCols(SkyscraperData d, List <Tuple <int, int> > proc) { //int iproc = 0; //while (iproc < proc.Count) //{ // if (!ReduceRowCol(d, proc[iproc].Item1, proc[iproc].Item2)) return false; // iproc++; //} return(proc.All(p => ReduceRowCol(d, p.Item1, p.Item2))); }
public SkyscraperData CreateInitialData() { SkyscraperData d = new SkyscraperData(_n); for (int i = 0; i < _n; i++) { for (int j = 0; j < _n; j++) { d.Data[i, j] = SkyscraperData.InitialValues[_n]; } } return(d); }
public SkyscraperData(SkyscraperData obj) { _size = obj._size; Data = (int[, ])obj.Data.Clone(); SetInRow = (int[])obj.SetInRow.Clone(); SetInCol = (int[])obj.SetInCol.Clone(); Rows = new List <int> [_size]; Cols = new List <int> [_size]; for (int i = 0; i < _size; i++) { Rows[i] = obj.Rows[i].ToList(); Cols[i] = obj.Cols[i].ToList(); } }
public bool CheckData(SkyscraperData d, int[] constraints) { //incorrectElements = false; //if (!CheckDataUniqueElements(d)) //{ // incorrectElements = true; // return false; //} if (!CheckDataReduced(d)) { return(false); } return(CheckDataConstraints(d, constraints)); }
public bool ReduceData(SkyscraperData d, List <Tuple <int, int> > proc) { if (!ReduceRowsCols(d, proc)) { return(false); } if (!SetRowsColsWherePossible(d)) { return(false); } //if (!ReduceRowsCols(d, proc)) return false; //proc.Clear(); //SetRowsColsWherePossibleDoubles(d, proc); return(true); }
private bool TrySetSingleElement(SkyscraperData d, int row, int col, int mask) { int v = (mask ^ -1) & (d.Data[row, col] & ((d.SetInRow[row] | d.SetInCol[col]) ^ -1)); //zostaja jedynki tam gdzie w masce sa 0, dodatkowo wylaczone juz ustawione bity if (d.CountBits(v) == 1) { d.SetSingleElementMask(row, col, v); if (!ReduceRowCol(d, row, col)) { return(false); } return(true); } return(false); }
private bool CheckDataReduced(SkyscraperData d) { //for (int i = 0; i < _n; i++) // for (int j = 0; j < _n; j++) // if (d.CountBits(i, j) != 1) return false; //return true; for (int i = 0; i < _n; i++) { if (d.SetInRow[i] != SkyscraperData.InitialValues[_n]) { return(false); } } return(true); }
private bool CheckDataElements(SkyscraperData d) { for (int i = 0; i < _n; i++) { int mask = 0, mask2 = 0; for (int j = 0; j < _n; j++) { mask |= d.Data[i, j]; mask2 |= d.Data[j, i]; } if ((mask != SkyscraperData.InitialValues[_n]) || (mask2 != SkyscraperData.InitialValues[_n])) { return(false); } } return(true); }
public SkyscraperData FindSolution(SkyscraperData d, int[] constraints) { if (_dataValidator.CheckData(d, constraints)) { return(d); } //wybierany pierwszy element o najmniejszej ilosci mozliwych pozycji //analiza drzewa rozwiazan w glab int row = -1, col = -1; //if (GetMinRowCol_Default(d, out row, out col)) if (GetMinRowCol_Rows(d, out row, out col)) { //Console.WriteLine($"{SkyscrapersCounters.Level}, {row}, {col}"); int el = d.Data[row, col]; for (int m = 1; m <= _n; m++) { if ((el & SkyscraperData.Masks[m]) != 0) { //Console.WriteLine($"{SkyscrapersCounters.Level}, {row}, {col}, {m}"); SkyscrapersCounters.NewData++; SkyscraperData newd = new SkyscraperData(d); newd.SetSingleElement(row, col, m); List <Tuple <int, int> > proc = new List <Tuple <int, int> >() { new Tuple <int, int>(row, col) }; SkyscraperData nextd = null; SkyscrapersCounters.Level++; if (_dataReductor.ReduceData(newd, proc)) { nextd = FindSolution(newd, constraints); } SkyscrapersCounters.Level--; if (nextd != null) { return(nextd); } } } } return(null); }
private void SetRowsColsWherePossibleDoubles(SkyscraperData d, List <Tuple <int, int> > proc) { //wierszami //for (int i = 0; i < _n; i++) //{ // //listy indeksow elementow dla masek // Dictionary<int, PrecalcData<int>> rowels = new Dictionary<int, PrecalcData<int>>(); // for (int j = 0; j < _n; j++) // { // //rozbicie elementu (wybranie ustawionych bitow) // PrecalcData<int> el = new PrecalcData<int>(); // for (int m = 1; m <= _n; m++) // if ((d.Data[i, j] & SkyscraperData.Masks[m]) != 0) el.Add(SkyscraperData.Masks[m]); // //wyznaczenie list z calego wiersza dla wszystkich par danego elementu // for (int f = 0; f < el.Count - 1; f++) // for (int n = f + 1; n < el.Count; n++) // { // int p = el[f] | el[n]; // if (rowels.ContainsKey(p)) continue; // PrecalcData<int> tl = new PrecalcData<int>(); // for (int k = 0; k < _n; k++) // if ((d.Data[i, k] & p) == p) tl.Add(k); // rowels.Add(p, tl); // } // } // //analiza par // int removedmask = 0; //moga pojawic sie pary dla powtarzajacych sie pozycji - mozna tylko raz pozycje usunac // foreach (var rowel in rowels.Where(x => x.Value.Count==2)) // { // if ((rowel.Key & removedmask) != 0) continue; // for (int k = 0; k < _n; k++) // { // if (rowel.Value.Contains(k)) // d.Data[i, k] = rowel.Key; // else // TryReduceSingleElement(d, proc, i, k, rowel.Key ^ -1); // } // removedmask |= rowel.Key; // } //} }
private bool ReduceRowCol(SkyscraperData d, int row, int col) { SkyscrapersCounters.ReduceRCReductions++; int mask = d.Data[row, col] ^ -1; int i = 0; while (i < d.Rows[row].Count) { bool singleset = false; if (col != d.Rows[row][i]) { if (!TryReduceSingleElement(d, row, d.Rows[row][i], mask, out singleset)) { return(false); } } if (!singleset) { i++; } } i = 0; while (i < d.Cols[col].Count) { bool singleset = false; if (row != d.Cols[col][i]) { if (!TryReduceSingleElement(d, d.Cols[col][i], col, mask, out singleset)) { return(false); } } if (!singleset) { i++; } } return(true); }
private bool TryReduceSingleElement(SkyscraperData d, int row, int col, int mask, out bool singleset) { singleset = false; //if (d.CountBits(row, col) > 1) { d.RemoveElementMask(row, col, mask); if (d.CountBits(row, col) == 1) { if (((d.Data[row, col] & d.SetInRow[row]) != 0) || ((d.Data[row, col] & d.SetInCol[col]) != 0)) { SkyscrapersCounters.ReduceRCDoublesCut++; return(false); } d.SetSingleElementMask(row, col, d.Data[row, col]); if (!ReduceRowCol(d, row, col)) { return(false); } singleset = true; } } return(true); }
public int[][] Solve(int[] constraints) { //Console.WriteLine("***"); SkyscrapersCounters.Clear(); SkyscraperData d = CreateInitialData(); ApplyConstraints(d, constraints); SkyscraperData dres = FindSolution(d, constraints); Console.WriteLine($"NewData: {SkyscrapersCounters.NewData}"); //Console.WriteLine($"ReduceRCIters: {SkyscrapersCounters.ReduceRCIters}"); //Console.WriteLine($"ReduceRCLoops: {SkyscrapersCounters.ReduceRCLoops}"); //Console.WriteLine($"ReduceRCLoopsRemoves: {SkyscrapersCounters.ReduceRCLoopsRemoves}"); Console.WriteLine($"ReduceRCReductions: {SkyscrapersCounters.ReduceRCReductions}"); Console.WriteLine($"ReduceRCDoublesCut: {SkyscrapersCounters.ReduceRCDoublesCut}"); //Console.WriteLine($"CheckDataCorrectCalls: {SkyscrapersCounters.CheckDataCorrectCalls}"); //Console.WriteLine($"CorrectData: {SkyscrapersCounters.CorrectData}"); //Console.WriteLine($"FirstCorrectDataInCall: {SkyscrapersCounters.FirstCorrectDataInCall}"); Console.WriteLine($"SetRowsCols: {SkyscrapersCounters.SetRowsCols}"); Console.WriteLine($"CountBits: {SkyscrapersCounters.CountBits}"); if (dres == null) { return(null); //throw new Exception("dres == null"); } int[][] res = new int[_n][]; for (int i = 0; i < _n; i++) { res[i] = new int[_n]; for (int j = 0; j < _n; j++) { res[i][j] = Array.IndexOf(SkyscraperData.Masks, dres.Data[i, j]); } } return(res); }
public void ApplyConstraints(SkyscraperData d, int[] constraints) { //ograniczenia od lewej do prawej po N rzedow //po przejsciu N rzedow obrot tablicy w prawo i analiza kolejnych rzedow for (int i = constraints.Length - 1; i >= 0; i--) { if (constraints[i] > 0) { int row = _n - 1 - i % _n; if (constraints[i] == _n) { for (int k = 0; k < _n; k++) { d.Data[row, k] = SkyscraperData.Masks[k + 1]; } } else if (constraints[i] == 1) { d.Data[row, 0] = SkyscraperData.Masks[_n]; } else { for (int el = _n; el > 1; el--) { for (int k = 0; k < constraints[i] - 1 - (_n - el); k++) { d.RemoveElement(row, k, el); } } } } if (i % _n == 0) { d.RotateRight(); } } //po nalozeniu ograniczen wygenerowanie list indeksow pozycji nie jednobitowych for (int i = 0; i < _n; i++) { for (int j = 0; j < _n; j++) { if (d.CountBits(i, j) > 1) { d.Rows[i].Add(j); d.Cols[j].Add(i); } } } //po nalozeniu ograniczen uwzglednienie wszystkich powstalych pozycji jednoelementowych (redukcja w wierszach i kolumnach) List <Tuple <int, int> > proc = new List <Tuple <int, int> >(); for (int i = 0; i < _n; i++) { for (int j = 0; j < _n; j++) { if (d.CountBits(i, j) == 1) { d.SetSingleElementMask(i, j, d.Data[i, j]); proc.Add(new Tuple <int, int>(i, j)); } } } _dataReductor.ReduceData(d, proc); }
private bool CheckDataConstraints(SkyscraperData d, int[] constraints) { int v; int highest; for (int i = 0; i < _n; i++) { //poziomo if (constraints[4 * _n - 1 - i] != 0) { v = 1; highest = d.Data[i, 0]; for (int j = 0; j < _n; j++) { CheckDataConstraintsSingleCheck(ref v, ref highest, d.Data[i, j]); } if (constraints[4 * _n - 1 - i] != v) { return(false); } } if (constraints[_n + i] != 0) { v = 1; highest = d.Data[i, _n - 1]; for (int j = _n - 1; j >= 0; j--) { CheckDataConstraintsSingleCheck(ref v, ref highest, d.Data[i, j]); } if (constraints[_n + i] != v) { return(false); } } //pionowo if (constraints[i] != 0) { v = 1; highest = d.Data[0, i]; for (int j = 0; j < _n; j++) { CheckDataConstraintsSingleCheck(ref v, ref highest, d.Data[j, i]); } if (constraints[i] != v) { return(false); } } if (constraints[3 * _n - 1 - i] != 0) { v = 1; highest = d.Data[_n - 1, i]; for (int j = _n - 1; j >= 0; j--) { CheckDataConstraintsSingleCheck(ref v, ref highest, d.Data[j, i]); } if (constraints[3 * _n - 1 - i] != v) { return(false); } } } return(true); }
private bool SetRowsColsWherePossible(SkyscraperData d) { SkyscrapersCounters.SetRowsCols++; //for (int i = 0; i < _n; i++) //{ // int j = 0; // while (j < d.Rows[i].Count) // { // int mask = 0; // for (int k = 0; k < d.Rows[i].Count; k++) // if (k != j) mask |= d.Data[i, d.Rows[i][k]]; // if (!TrySetSingleElement(d, i, d.Rows[i][j], mask)) j++; // } //} //for (int i = 0; i < _n; i++) //{ // int j = 0; // while (j < d.Cols[i].Count) // { // int mask = 0; // for (int k = 0; k < d.Cols[i].Count; k++) // if (k != j) mask |= d.Data[d.Cols[i][k], i]; // if (!TrySetSingleElement(d, d.Cols[i][j], i, mask)) j++; // } //} for (int i = 0; i < _n; i++) { int j = 0; int leftmask = 0; while (j < d.Rows[i].Count) { int mask = leftmask; for (int k = j + 1; k < d.Rows[i].Count; k++) { mask |= d.Data[i, d.Rows[i][k]]; } leftmask |= d.Data[i, d.Rows[i][j]]; if (!TrySetSingleElement(d, i, d.Rows[i][j], mask)) { j++; } } } for (int i = 0; i < _n; i++) { int j = 0; int leftmask = 0; while (j < d.Cols[i].Count) { int mask = leftmask; for (int k = j + 1; k < d.Cols[i].Count; k++) { mask |= d.Data[d.Cols[i][k], i]; } leftmask |= d.Data[d.Cols[i][j], i]; if (!TrySetSingleElement(d, d.Cols[i][j], i, mask)) { j++; } } } return(true); }