private Entry findEntryWithMinChoices(LatinSquare lq) { int minChoices = lq.entries.Length; int targetRow = -1; int targetCol = -1; for (int row = 0; row < lq.entries.Length; row++) { for (int col = 0; col < lq.entries.Length; col++) { int choices = lq.entries[row][col].GetNumPossibleValues(); if (choices == 2) { return(new Entry(row, col, NumberSet.UNKNOWN)); } if (choices > 1 && choices < minChoices) { minChoices = choices; targetRow = row; targetCol = col; } } } return(new Entry(targetRow, targetCol, NumberSet.UNKNOWN)); }
/** * Creates an instance linked with its two alternative forms. */ public static LatinSquare create(int size) { LatinSquare result = new LatinSquare(size); result.nextTransposition = new LatinSquare(new LatinSquare(result)); return(result); }
public virtual LatinSquare CreateCopy() { LatinSquare result = new LatinSquare(entries, this); LatinSquare nnt = new LatinSquare(nextTransposition.nextTransposition.entries, result); LatinSquare nt = new LatinSquare(nextTransposition.entries, nnt); result.nextTransposition = nt; return(result); }
/// <summary> /// Create a deep copy of this (including transposed forms) /// </summary> /// <returns>instance of Sudoku</returns> public override LatinSquare CreateCopy() { // TODO: in base constructor param is transposition, here it is original Sudoku result = new Sudoku(this); LatinSquare nnt = new LatinSquare(nextTransposition.nextTransposition.entries, result); LatinSquare nt = new LatinSquare(nextTransposition.entries, nnt); result.nextTransposition = nt; return(result); }
private void addOneEntry(LatinSquare square) { try { while (solution == null) { square.AddFindings(); var target = findEntryWithMinChoices(square); if (target.Row == -1) { solution = square; tasks.AbortAll(); return; } List <int> values = square.entries[target.Row][target.Col].GetAllowedValues(); if (Reverse) { values.Reverse(); } int remaining = values.Count; foreach (int num in values) { if (--remaining > 0) { try { LatinSquare candidate = square.CreateCopy(); candidate.SetEntry(target.Row, target.Col, num); tasks.Add(candidate); } catch (IllegalEntryException) { Effort++; } } else { square.SetEntry(target.Row, target.Col, num); // just continue loop instead of wait for another task } } } } catch (IllegalEntryException) { Effort++; } }
public LatinSquare CompleteParallel(LatinSquare square, int numberThreads) { tasks.Add(square); List <Thread> threads = new List <Thread>(); for (int i = 0; i < numberThreads; i++) { threads.Add(new Thread(AddEntry)); } threads.ForEach(t => t.Start()); threads.ForEach(t => t.Join()); if (solution == null) { throw new IllegalEntryException(); } return(solution); }
private void AddEntry() { while (solution == null) { LatinSquare square = tasks.GetNext(); if (square == null) { return; } try { addOneEntry(square); } finally { tasks.Done(); } } }
public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) { return(false); } LatinSquare other = (LatinSquare)obj; for (int row = 0; row < entries.Length; row++) { for (int col = 0; col < entries[row].Length; col++) { if (GetEntry(row, col) != other.GetEntry(row, col)) { return(false); } } } return(true); }
public LatinSquare Complete(LatinSquare square) { if (square == null) { throw new ArgumentNullException(nameof(square)); } square.AddFindings(); var target = findEntryWithMinChoices(square); if (target.Row == -1) { return(square); } IllegalEntryException last = null; List <int> values = square.entries[target.Row][target.Col].GetAllowedValues(); if (Reverse) { values.Reverse(); } int remaining = values.Count; foreach (int num in values) { try { LatinSquare candidate = (--remaining == 0 ? square : square.CreateCopy()); candidate.SetEntry(target.Row, target.Col, num); return(Complete(candidate)); } catch (IllegalEntryException e) { Effort++; last = e; } } throw last; }
internal LatinSquare(NumberSet[][] originalEntries, LatinSquare nt) { entries = CloneEntries(originalEntries); nextTransposition = nt; }
/** * Not to be used except in inheriting classes. Protected would not permit call from static methods. */ internal LatinSquare(LatinSquare nt) : this(nt.entries.Length) { nextTransposition = nt; }