diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6b7ce11 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4 @@ +[[package]] +name = "imposters" +version = "0.1.0" + diff --git a/Cargo.toml b/Cargo.toml index 8daefe9..35c1855 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "imposters" version = "0.1.0" -authors = ["Jason Staten "] +authors = ["Jason Staten "] [dependencies] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8fcba53 --- /dev/null +++ b/LICENSE @@ -0,0 +1,16 @@ +ISC License (ISC) +Copyright (c) 2018, Jason Staten + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted, provided that the +above copyright notice and this permission notice appear in all +copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..1d7758b --- /dev/null +++ b/readme.md @@ -0,0 +1,3 @@ +# Rust Turing Machine + +I made a turing machine when reading Impostor's Handbook diff --git a/src/fsm.rs b/src/fsm.rs new file mode 100644 index 0000000..bd15636 --- /dev/null +++ b/src/fsm.rs @@ -0,0 +1,72 @@ +#[derive(Debug, PartialEq, Copy, Clone)] +enum State { + Idle, + TimeInput, + Cook, + Pause, + Done, +} + +enum Event { + DigitPressed, + StopPressed, + StartPressed, + TimerElapsed, +} + +struct Microwave { + state: State, +} + +impl Microwave { + fn dispatch(&mut self, event: Event) { + use self::Event::*; + use self::State::*; + + self.state = match (self.state, event) { + (Idle, DigitPressed) => TimeInput, + (TimeInput, DigitPressed) => TimeInput, + (TimeInput, StartPressed) => Cook, + (TimeInput, StopPressed) => Idle, + (Cook, TimerElapsed) => Done, + (Cook, StopPressed) => Pause, + (Pause, StartPressed) => Cook, + (Pause, StopPressed) => Idle, + (Done, StopPressed) => Idle, + _ => self.state, + } + } +} + +#[test] +fn test_fsm() { + use self::Event::*; + use self::State::*; + + let mut mic = Microwave { state: Idle }; + // Punch in numbers + mic.dispatch(DigitPressed); + mic.dispatch(DigitPressed); + mic.dispatch(DigitPressed); + assert_eq!(mic.state, TimeInput); + + // Start microwave + mic.dispatch(StartPressed); + assert_eq!(mic.state, Cook); + + // Check if food is hot + mic.dispatch(StopPressed); + assert_eq!(mic.state, Pause); + + // Continue cooking + mic.dispatch(StartPressed); + assert_eq!(mic.state, Cook); + + // Timer finished + mic.dispatch(TimerElapsed); + assert_eq!(mic.state, Done); + + // Clear "done" message + mic.dispatch(StopPressed); + assert_eq!(mic.state, Idle); +} diff --git a/src/lib.rs b/src/lib.rs index 31e1bb2..30c96e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,2 @@ -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -} +pub mod fsm; +pub mod turing; diff --git a/src/turing.rs b/src/turing.rs new file mode 100644 index 0000000..d60f10b --- /dev/null +++ b/src/turing.rs @@ -0,0 +1,118 @@ +type State = usize; + +#[derive(Debug, PartialEq, Clone)] +enum Cell { + Blank, + Zero, + One, +} + +#[derive(Debug)] +enum Move { + Stay, + Left, + Right, +} + +struct Transition { + start: State, + end: State, + read: Cell, + write: Cell, + operation: Move, +} + +struct Machine { + initial: State, + done: State, + transitions: Vec, +} + +type Tape = Vec; + +fn run(machine: Machine, code: Tape) -> Tape { + let mut position = 0; + let mut state = machine.initial; + let mut tape = code.to_vec(); + tape.resize(10, Cell::Blank); + + while state != machine.done { + let transition; + { + let cell = tape.get(position).unwrap_or(&Cell::Blank); + transition = machine + .transitions + .iter() + .find(|t| t.start == state && &t.read == cell) + .expect("Missing transition"); + } + state = transition.end; + tape[position] = transition.write.clone(); + position = match transition.operation { + Move::Left => position - 1, + Move::Right => position + 1, + Move::Stay => position, + }; + } + + return tape; +} + +#[test] +fn test_build() { + let machine = Machine { + initial: 0, + done: 2, + transitions: vec![ + Transition { + start: 0, + end: 0, + read: Cell::Zero, + write: Cell::Zero, + operation: Move::Right, + }, + Transition { + start: 0, + end: 0, + read: Cell::One, + write: Cell::One, + operation: Move::Right, + }, + Transition { + start: 0, + end: 1, + read: Cell::Blank, + write: Cell::Blank, + operation: Move::Left, + }, + Transition { + start: 1, + end: 1, + read: Cell::One, + write: Cell::Zero, + operation: Move::Left, + }, + Transition { + start: 1, + end: 2, + read: Cell::Zero, + write: Cell::One, + operation: Move::Stay, + }, + Transition { + start: 1, + end: 2, + read: Cell::Blank, + write: Cell::One, + operation: Move::Stay, + }, + ], + }; + + let result = run(machine, vec![Cell::One, Cell::One, Cell::Zero, Cell::One]); + println!("{:?}", result); + + let mut expected = vec![Cell::One, Cell::One, Cell::One, Cell::Zero]; + expected.resize(10, Cell::Blank); + assert_eq!(result, expected); +}