Created
August 25, 2012 19:57
-
-
Save gregmajor/3470268 to your computer and use it in GitHub Desktop.
Combination Lock using the Iteration State Machine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* REVISITING THE COMBINATION LOCK | |
* - We can make our machine non-deterministic | |
*/ | |
using System; | |
using System.Collections.Generic; | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
UnlockUsingCorrectCombination(); | |
} | |
public static void UnlockUsingCorrectCombination() | |
{ | |
var combinationLock = new CombinationLock(); | |
combinationLock.Start(); | |
Console.WriteLine(string.Format("Starting State: {0}", combinationLock.CurrentState)); | |
combinationLock.EnterNumber(7); | |
Console.WriteLine(combinationLock.CurrentState); | |
combinationLock.EnterNumber(1); | |
Console.WriteLine(combinationLock.CurrentState); | |
combinationLock.EnterNumber(3); | |
Console.WriteLine(combinationLock.CurrentState); | |
Console.WriteLine(string.Format("Ending State: {0}", combinationLock.CurrentState)); | |
} | |
} | |
public enum CombinationLockState | |
{ | |
NoneRight, | |
OneRight, | |
TwoRight, | |
Open | |
} | |
public class CombinationLock : IteratorStateMachine<CombinationLockState> | |
{ | |
private int? firstNumber; | |
private int? secondNumber; | |
private int? thirdNumber; | |
public void EnterNumber(int number) | |
{ | |
this.SetNumber(number); | |
Console.WriteLine(string.Format("Entered {0}...", number)); | |
this.Trigger(); | |
} | |
protected override IEnumerable<CombinationLockState> States() | |
{ | |
/* | |
* Of course, nobody in their right mind would build a system that confirms | |
* each value after input as our example is doing. Doing so reduces the | |
* number of attempts required to crack the code from a maximum of 1000 to | |
* just 30! | |
*/ | |
while (true) | |
{ | |
if (this.firstNumber == 7 && this.secondNumber == 1 && this.thirdNumber == 3) | |
{ | |
yield return CombinationLockState.Open; | |
} | |
else if (this.firstNumber == 7 && this.secondNumber == 1 && this.thirdNumber != 3) | |
{ | |
yield return CombinationLockState.TwoRight; | |
} | |
else if (this.firstNumber == 7 && this.secondNumber != 1) | |
{ | |
yield return CombinationLockState.OneRight; | |
} | |
else | |
{ | |
yield return CombinationLockState.NoneRight; | |
} | |
} | |
} | |
private void SetNumber(int number) | |
{ | |
if (this.firstNumber == null) | |
{ | |
this.firstNumber = number; | |
} | |
else if (this.secondNumber == null) | |
{ | |
this.secondNumber = number; | |
} | |
else if (this.thirdNumber == null) | |
{ | |
this.thirdNumber = number; | |
} | |
else | |
{ | |
this.firstNumber = number; | |
this.secondNumber = null; | |
this.thirdNumber = null; | |
} | |
} | |
} | |
public abstract class IteratorStateMachine<TState> | |
{ | |
private IEnumerator<TState> enumerator; | |
public TState CurrentState | |
{ | |
get | |
{ | |
return this.enumerator.Current; | |
} | |
} | |
public void Start() | |
{ | |
this.enumerator = this.States().GetEnumerator(); | |
this.enumerator.MoveNext(); | |
} | |
protected abstract IEnumerable<TState> States(); | |
protected void Trigger() | |
{ | |
this.enumerator.MoveNext(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment