turingmachine_rs/
lib.rs

1//! A simulation crate for Turing Machines
2#![warn(missing_docs)]
3
4use std::cell::RefCell;
5use std::fmt;
6use std::rc::{Rc, Weak};
7
8/// A struct representing a node in a linked list
9#[derive(Clone)]
10struct Node<Alphabet> {
11    /// The previous node
12    prev: Option<Rc<Node<Alphabet>>>,
13    /// The next node
14    next: RefCell<Option<Weak<Node<Alphabet>>>>,
15    /// The data contained in the node
16    data: RefCell<Alphabet>,
17}
18
19impl<Alphabet: Clone> Node<Alphabet> {
20    /// Create a new node with a data and possibly a previous node
21    fn new(data: Alphabet, prev: Option<Rc<Node<Alphabet>>>) -> Node<Alphabet> {
22        Node {
23            prev,
24            next: RefCell::new(None),
25            data: RefCell::new(data),
26        }
27    }
28
29    /// Fetch previous node
30    fn prev(&self) -> Option<Rc<Node<Alphabet>>> {
31        self.prev.clone()
32    }
33
34    /// Fetch next node
35    fn next(&self) -> Option<Weak<Node<Alphabet>>> {
36        self.next.borrow().clone()
37    }
38
39    /// Replace next with possible new next node
40    fn replace_next(
41        &self,
42        new_value: Option<Weak<Node<Alphabet>>>,
43    ) -> Option<Weak<Node<Alphabet>>> {
44        self.next.replace(new_value)
45    }
46
47    /// Fetch the data contained in node
48    fn get(&self) -> Alphabet {
49        self.data.borrow().clone()
50    }
51
52    /// Replace the data contained in the node
53    fn replace(&self, new_value: Alphabet) -> Alphabet {
54        self.data.replace(new_value)
55    }
56}
57
58/// A possibly theorically infinite TuringTape
59pub struct TuringTape<Alphabet> {
60    /// The alphabet token put at empty spaces
61    empty: Alphabet,
62    /// The last node currently saved
63    last: RefCell<Rc<Node<Alphabet>>>,
64    /// The cursor point
65    cursor: RefCell<Rc<Node<Alphabet>>>,
66}
67
68impl<Alphabet: fmt::Display + Clone> fmt::Display for TuringTape<Alphabet> {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        write!(f, "|")?;
71        let mut s = String::new();
72
73        let mut head: Rc<Node<Alphabet>> = self.last.borrow().clone();
74
75        loop {
76            let backup = s.clone();
77            if Rc::ptr_eq(&self.cursor.borrow(), &head) {
78                s = format!("> {} <|", head.get());
79            } else {
80                s = format!("  {}  |", head.get());
81            }
82            s.push_str(&backup);
83
84            if let Some(new_head) = head.prev.clone() {
85                head = new_head;
86            } else {
87                break;
88            }
89        }
90
91        write!(f, "{}", s)
92    }
93}
94
95impl<Alphabet: Clone> TuringTape<Alphabet> {
96    /// Initialize a new TuringTape with:
97    ///
98    /// - __empty:__ The token put at empty tape cells
99    /// - __start:__ The token put in the first cell
100    /// - __initial:__ An vector of tokens to be put after the start token
101    pub fn new(empty: Alphabet, start: Alphabet, initial: Vec<Alphabet>) -> TuringTape<Alphabet> {
102        let fst_node = Rc::new(Node::new(start, None));
103        let tape = TuringTape {
104            empty,
105            last: RefCell::new(fst_node.clone()),
106            cursor: RefCell::new(fst_node),
107        };
108
109        initial.into_iter().for_each(|token| {
110            tape.append(token);
111        });
112
113        tape
114    }
115
116    /// Append a new token to the turing tape
117    fn append(&self, token: Alphabet) -> Rc<Node<Alphabet>> {
118        let new_node = Rc::new(Node::new(token, Some(self.last.borrow().clone())));
119        self.last
120            .borrow()
121            .replace_next(Some(Rc::downgrade(&new_node)));
122        self.last.replace(new_node.clone());
123        new_node
124    }
125
126    /// Fetch the token at the cursor
127    pub fn get_cursor(&self) -> Alphabet {
128        self.cursor.borrow().clone().get()
129    }
130
131    /// Set the token at the cursor and return the old token
132    pub fn set_cursor(&self, value: Alphabet) -> Alphabet {
133        self.cursor.borrow().clone().replace(value)
134    }
135
136    /// Make the cursor go one cell to the right
137    pub fn step_right(&self) -> Alphabet {
138        let new_cursor = match self.cursor.borrow().clone().next() {
139            Some(next) => next.clone().upgrade().expect("Unable to upgrade"),
140            None => self.append(self.empty.clone()),
141        };
142
143        self.cursor.replace(new_cursor);
144        self.get_cursor()
145    }
146
147    /// Make the cursor go one cell to the left
148    ///
149    /// Will panic if one goes off the tape.
150    pub fn step_left(&self) -> Alphabet {
151        let new_cursor = match self.cursor.borrow().clone().prev() {
152            Some(prev) => prev.clone(),
153            None => panic!("Went left side of the tape!"),
154        };
155
156        self.cursor.replace(new_cursor);
157        self.get_cursor()
158    }
159
160    /// Runs from start state until one of the end states has been reached.
161    /// Will return the end state.
162    pub fn run_states<S: TuringStates<Alphabet> + PartialEq>(
163        &self,
164        mut start_state: S,
165        end_states: Vec<S>,
166    ) -> S {
167        while !end_states.contains(&start_state) {
168            start_state.internal_step(self);
169        }
170
171        start_state
172    }
173}
174
175impl<Alphabet: Clone> From<TuringTape<Alphabet>> for Vec<Alphabet> {
176    fn from(tape: TuringTape<Alphabet>) -> Vec<Alphabet> {
177        let cursor_initial = tape.cursor.borrow().clone();
178        let mut v = Vec::new();
179
180        // Move all the way to the left
181        while tape.cursor.borrow().clone().prev().is_some() {
182            tape.step_left();
183        }
184
185        // Move all the way back to the right adding the cursor
186        // to the vector along the way
187        while tape.cursor.borrow().clone().next().is_some() {
188            v.push(tape.get_cursor());
189            tape.step_right();
190        }
191
192        // Add the last element
193        v.push(tape.get_cursor());
194
195        // Set the cursor back to it's previous position
196        let mut cursor = tape.cursor.borrow_mut();
197        *cursor = cursor_initial;
198
199        v
200    }
201}
202
203/// Define the movement direction
204pub enum Move {
205    /// Move left one cell
206    Left,
207    /// Dont move the cursor
208    Stay,
209    /// Move right one cell
210    Right,
211}
212
213/// A trait that implements the behaviour for turing states
214pub trait TuringStates<Alphabet: Clone>: Sized + PartialEq {
215    /// The internal step function
216    /// Output the new state, token at current cursor position, and move of the cursor position
217    fn step(&self, current_token: Alphabet) -> (Self, Alphabet, Move);
218
219    /// Execute one step of the turing machine
220    fn internal_step(&mut self, tape: &TuringTape<Alphabet>) {
221        let (state, replace, mv) = self.step(tape.get_cursor());
222
223        // Update the current state
224        *self = state;
225
226        // Update cursor token
227        tape.set_cursor(replace);
228
229        // Update cursor position
230        match mv {
231            Move::Left => {
232                tape.step_left();
233            }
234            Move::Stay => {}
235            Move::Right => {
236                tape.step_right();
237            }
238        };
239    }
240
241    /// Run this turing machine from a start state, until it eaches a final state.
242    /// Will return a tuple containing the end_state and a vector of the memory state.
243    fn run_until_end(
244        start_state: Self,
245        end_states: Vec<Self>,
246        empty_token: Alphabet,
247        start_token: Alphabet,
248        initial_state: Vec<Alphabet>,
249    ) -> (Self, Vec<Alphabet>) {
250        let tape = TuringTape::new(empty_token, start_token, initial_state);
251        let end_state = tape.run_states(start_state, end_states);
252        (end_state, tape.into())
253    }
254}
255
256#[cfg(test)]
257mod tests {
258    #[derive(PartialEq, Clone, Debug)]
259    pub enum Bit {
260        Delta,
261        Zero,
262        One,
263    }
264
265    impl fmt::Display for Bit {
266        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267            use Bit::*;
268
269            match self {
270                Delta => write!(f, "_"),
271                Zero => write!(f, "0"),
272                One => write!(f, "1"),
273            }
274        }
275    }
276
277    use super::*;
278
279    #[test]
280    fn fetch_cursor() {
281        use Bit::*;
282        assert_eq!(TuringTape::new(Delta, Zero, vec![]).get_cursor(), Zero);
283        assert_eq!(TuringTape::new(Delta, One, vec![]).get_cursor(), One);
284        assert_eq!(TuringTape::new(Delta, Delta, vec![]).get_cursor(), Delta);
285        assert_eq!(TuringTape::new(Delta, Zero, vec![Delta]).get_cursor(), Zero);
286        assert_eq!(TuringTape::new(Delta, One, vec![Delta]).get_cursor(), One);
287        assert_eq!(
288            TuringTape::new(Delta, Delta, vec![Delta]).get_cursor(),
289            Delta
290        );
291    }
292
293    #[test]
294    fn set_cursor() {
295        use Bit::*;
296        let tape = TuringTape::new(Delta, Delta, vec![Zero, One, Zero]);
297        assert_eq!(tape.get_cursor(), Delta);
298        tape.set_cursor(One);
299        assert_eq!(tape.get_cursor(), One);
300        tape.set_cursor(Zero);
301        assert_eq!(tape.get_cursor(), Zero);
302    }
303
304    #[test]
305    fn turing_tape_new() {
306        use Bit::*;
307        TuringTape::new(
308            Delta,
309            Delta,
310            vec![Zero, One, One, One, Zero, One, One, One, Zero],
311        );
312    }
313
314    #[test]
315    fn turing_into_vec() {
316        use Bit::*;
317        let tape = TuringTape::new(
318            Delta,
319            Delta,
320            vec![Zero, One, One, One, Zero, One, One, One, Zero],
321        );
322        assert_eq!(
323            <Vec<Bit>>::from(tape),
324            vec![Delta, Zero, One, One, One, Zero, One, One, One, Zero]
325        );
326    }
327
328    #[test]
329    fn turing_stepping() {
330        use Bit::*;
331        let tape = TuringTape::new(
332            Delta,
333            Delta,
334            vec![Zero, One, One, One, Zero, One, One, One, Zero],
335        );
336
337        assert_eq!(tape.get_cursor(), Delta);
338        tape.step_right();
339        assert_eq!(tape.get_cursor(), Zero);
340        tape.step_left();
341        assert_eq!(tape.get_cursor(), Delta);
342
343        tape.step_right();
344        tape.step_right();
345        assert_eq!(tape.get_cursor(), One);
346        tape.step_right();
347        assert_eq!(tape.get_cursor(), One);
348        tape.step_right();
349        assert_eq!(tape.get_cursor(), One);
350        tape.step_right();
351        assert_eq!(tape.get_cursor(), Zero);
352
353        assert_eq!(tape.step_right(), tape.get_cursor());
354        assert_eq!(tape.step_right(), tape.get_cursor());
355        assert_eq!(tape.step_right(), tape.get_cursor());
356        assert_eq!(tape.step_right(), tape.get_cursor());
357    }
358}