public void Notify(int index, Quadstate before, Quadstate after) { var a = after == Quadstate.Yes || after == Quadstate.Contradiction; var b = before == Quadstate.Yes || before == Quadstate.Contradiction; if (a && !b) { VisitNearby(index, false); } if (b && !a) { // Must be backtracking. // The main backtrack mechanism will handle undoing bans, and // undos are always in order, so we just need to reverse VisitNearby VisitNearby(index, true); } }
public void Notify(int index, Quadstate before, Quadstate after) { switch (before) { case Quadstate.No: NoCount--; break; case Quadstate.Maybe: MaybeCount--; break; case Quadstate.Yes: YesCount--; break; } switch (after) { case Quadstate.No: NoCount++; break; case Quadstate.Maybe: MaybeCount++; break; case Quadstate.Yes: YesCount++; break; } }
public static bool Possible(this Quadstate v) => (int)v >= 0;
public static bool IsContradiction(this Quadstate v) => v == Quadstate.Contradiction;
public static bool IsNo(this Quadstate v) => v == Quadstate.No;
public static bool IsMaybe(this Quadstate v) => v == Quadstate.Maybe;
public static bool IsYes(this Quadstate v) => v == Quadstate.Yes;
public bool Next(int index, Quadstate selected) { switch (state) { case State.Initial: if (selected.IsYes()) { state = State.InRun; runCount = 1; runStartIndex = index; } return(false); case State.JustAfterRun: if (selected.IsYes()) { state = State.InRun; runCount = 1; runStartIndex = index; goto checkCases; } else { state = State.Initial; prevRunCount = 0; runCount = 0; } return(false); case State.InRun: if (selected.IsYes()) { state = State.InRun; runCount += 1; if (runCount > max) { // Immediate contradiction return(true); } goto checkCases; } else { // Also case 1. if (runCount == max) { if (selected.Possible()) { banAt(index); } } state = State.JustAfterRun; prevRunCount = runCount; runCount = 0; } return(false); } // Unreachable throw new Exception("Unreachable"); checkCases: // Have we entered case 1 or 2? if (prevRunCount + runCount == max) { // Ban on the previous end of the run if (runStartIndex == 0) { if (periodic) { banAt(indexCount - 1); } } else { banAt(runStartIndex - 1); } } return(false); }