using System.Collections.Generic;
using MyState = System.Collections.Generic.HashSet<string>;
public static void Main()
var methods = new List<Method>();
methods.Add(new Method{name = "Start", inState = new MyState{"Stopped"}, outState = new MyState{ "Started" }});
methods.Add(new Method{name = "Stop", inState = new MyState{"Started"}, outState = new MyState{ "Stopped", "Paused" }});
methods.Add(new Method{name = "Unpause", inState = new MyState{"Paused"}, outState = new MyState{ "Started" }});
var uncallable = FindUncallableMethods(new MyState{"Started"}, methods);
foreach (var m in uncallable) {
Console.WriteLine(m.name);
public static HashSet<Method> FindUncallableMethods(MyState startState, List<Method> methods) {
HashSet<Method> notCalled = new HashSet<Method>(methods);
FindUncallableMethodsRec(startState, methods, notCalled);
private static void FindUncallableMethodsRec(MyState state, List<Method> methods, HashSet<Method> notCalled) {
foreach (var method in methods.Where(m => m.Accepts(state))) {
if (!notCalled.Contains(method)) continue;
notCalled.Remove(method);
FindUncallableMethodsRec(method.Produces(state), methods, notCalled);
public string name { get; set; }
public MyState inState { get; set; }
public MyState outState { get; set; }
public bool Accepts(MyState state) {
return inState.All(s => state.Contains(s));
public MyState Produces(MyState state) {
if (!Accepts(state)) throw new Exception("busted");
return new MyState(state.Where(s => !inState.Contains(s)).Union(outState));