Skip to content

Instantly share code, notes, and snippets.

@gregmajor
Created August 25, 2012 19:57
Show Gist options
  • Save gregmajor/3470268 to your computer and use it in GitHub Desktop.
Save gregmajor/3470268 to your computer and use it in GitHub Desktop.
Combination Lock using the Iteration State Machine
/*
* 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