commit
c2312bcab1
@ -0,0 +1,4 @@
|
||||
[[package]]
|
||||
name = "imposters"
|
||||
version = "0.1.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "imposters"
|
||||
version = "0.1.0"
|
||||
authors = ["Jason Staten <jason.staten@domo.com>"]
|
||||
authors = ["Jason Staten <jstaten07@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
|
@ -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.
|
@ -0,0 +1,3 @@
|
||||
# Rust Turing Machine
|
||||
|
||||
I made a turing machine when reading Impostor's Handbook
|
@ -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);
|
||||
}
|
@ -1,7 +1,2 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
||||
pub mod fsm;
|
||||
pub mod turing;
|
||||
|
@ -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<Transition>,
|
||||
}
|
||||
|
||||
type Tape = Vec<Cell>;
|
||||
|
||||
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);
|
||||
}
|
Loading…
Reference in new issue