Created
February 12, 2017 15:38
-
-
Save damonmcminn/2a863ca09de491e1621333e489f8e460 to your computer and use it in GitHub Desktop.
Garage Door Opener
This file contains hidden or 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
| type FiniteAutomataRule<'State, 'Input> = { | |
| State:'State | |
| Input:'Input | |
| NextState:'State | |
| } | |
| type DoorState = | |
| | Open | |
| | Closed | |
| | Opening | |
| | Closing | |
| | StoppedWhileOpening | |
| | StoppedWhileClosing | |
| | EmergencyOpening | |
| | OpenBlocked | |
| type Input = | |
| | ButtonClicked | |
| | CycleComplete | |
| | BlockDetected | |
| | BlockCleared | |
| type DeterminsticFiniteAutomata (rules, initialState) = | |
| let mutable currentState = initialState | |
| member dfa.State () = currentState | |
| member dfa.NextState input = | |
| let matchesStateAndInput r = | |
| r.State = currentState && r.Input = input | |
| currentState <- (List.find matchesStateAndInput rules).NextState | |
| static member CreateRule (state, input, next) = | |
| { State = state; Input = input; NextState = next } | |
| static member Cycle rules inputs initialState = | |
| let dfa = DeterminsticFiniteAutomata(rules, initialState) | |
| let printState = printfn "State: %A" | |
| let printInput = printfn "Input: %A" | |
| let mutateAndPrint input = | |
| printInput input | |
| dfa.NextState input |> ignore | |
| printState (dfa.State()) | |
| printState (dfa.State()) | |
| Seq.iter mutateAndPrint inputs | |
| let doorRules = | |
| [ | |
| Open, ButtonClicked, Closing | |
| Closed, ButtonClicked, Opening | |
| Opening, ButtonClicked, StoppedWhileOpening | |
| Closing, ButtonClicked, StoppedWhileClosing | |
| StoppedWhileOpening, ButtonClicked, Closing | |
| StoppedWhileClosing, ButtonClicked, Opening | |
| Opening, CycleComplete, Open | |
| Closing, CycleComplete, Closed | |
| Open, CycleComplete, Open | |
| Closed, CycleComplete, Closed | |
| StoppedWhileOpening, CycleComplete, StoppedWhileOpening | |
| StoppedWhileClosing, CycleComplete, StoppedWhileClosing | |
| ] | |
| |> List.map DeterminsticFiniteAutomata.CreateRule | |
| let inputs = [ | |
| ButtonClicked | |
| CycleComplete | |
| ButtonClicked | |
| ButtonClicked | |
| ButtonClicked | |
| ButtonClicked | |
| ButtonClicked | |
| CycleComplete | |
| ] | |
| let bonusRules = | |
| [ | |
| Closing, BlockDetected, EmergencyOpening | |
| EmergencyOpening, ButtonClicked, EmergencyOpening | |
| EmergencyOpening, CycleComplete, OpenBlocked | |
| OpenBlocked, BlockCleared, Open | |
| OpenBlocked, ButtonClicked, OpenBlocked | |
| ] | |
| |> List.map DeterminsticFiniteAutomata.CreateRule | |
| let bonusInputs = [ | |
| ButtonClicked | |
| CycleComplete | |
| ButtonClicked | |
| BlockDetected | |
| ButtonClicked | |
| CycleComplete | |
| ButtonClicked | |
| BlockCleared | |
| ButtonClicked | |
| CycleComplete | |
| ] | |
| printfn "Challenge" | |
| DeterminsticFiniteAutomata.Cycle doorRules inputs Closed | |
| printfn "\n" | |
| printfn "Bonus" | |
| DeterminsticFiniteAutomata.Cycle (doorRules @ bonusRules) bonusInputs Closed |
This file contains hidden or 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
| type Complete = Open | Closed | |
| type Stopped = WhileOpening | WhileClosing | |
| type Moving = Opening | Closing | |
| type Input = ButtonClicked | CycleComplete | Blocked | |
| type DoorState = | |
| | Complete of Complete | |
| | Moving of Moving | |
| | Stopped of Stopped | |
| let handleCycleComplete state = | |
| // do nothing if not moving i.e. return state | |
| match state with | |
| | Moving towards -> | |
| match towards with | |
| | Opening -> Complete Open | |
| | Closing -> Complete Closed | |
| | _ -> state | |
| let handleButtonClick state = | |
| match state with | |
| | Complete position -> | |
| match position with | |
| | Open -> Moving Closing | |
| | Closed -> Moving Opening | |
| | Moving towards -> | |
| match towards with | |
| | Opening -> Stopped WhileOpening | |
| | Closing -> Stopped WhileClosing | |
| | Stopped position -> | |
| match position with | |
| | WhileOpening -> Moving Closing | |
| | WhileClosing -> Moving Opening | |
| type GarageDoor () = | |
| let mutable state = Complete Closed | |
| member door.State = state | |
| member door.HandleInput input = | |
| state <- | |
| match input with | |
| | ButtonClicked -> handleButtonClick state | |
| | CycleComplete -> handleCycleComplete state | |
| door.State, input | |
| let inputs = [ | |
| ButtonClicked | |
| CycleComplete | |
| ButtonClicked | |
| ButtonClicked | |
| ButtonClicked | |
| ButtonClicked | |
| ButtonClicked | |
| CycleComplete | |
| ] | |
| let door = GarageDoor() | |
| let printState = printfn "Door: %A" | |
| let printStateAndInput (state, input) = | |
| printState state | |
| printfn "> %A" input | |
| printState door.State | |
| Seq.iter (door.HandleInput >> printStateAndInput) inputs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment