pub struct Classic<S: Symbol> { /* private fields */ }Expand description
Classic is a common TuringMachine realization that can be used
freely for program execution.
Implementations§
Source§impl<S: Symbol> Classic<S>
impl<S: Symbol> Classic<S>
Sourcepub fn new(program: Program<S>, default: S) -> Result<Self, String>
pub fn new(program: Program<S>, default: S) -> Result<Self, String>
Constructs a new Classic Turing machine from the program
Program and the default symbol Symbol.
Returns [Ok(Classic)] when the default symbol is in the program
alphabet otherwise [Err(String)] with diagnostic information.
§Examples
Trying to return the new machine with a mismatched default symbol:
use turing_machine_rs::instruction::State;
use turing_machine_rs::machines::Classic;
use turing_machine_rs::program::Program;
let program = Program::new(vec!['0', '1'], State(1));
let machine = Classic::new(program, '!');
assert!(machine.is_err());Successful creation:
use turing_machine_rs::instruction::State;
use turing_machine_rs::machines::Classic;
use turing_machine_rs::program::Program;
let program = Program::new(vec!['0', '1'], State(1));
let machine = Classic::new(program, '0');
assert!(machine.is_ok());Examples found in repository?
11fn main() -> Result<(), String> {
12 let alphabet = vec!['t', 'e', 's', 'n', 'i', 'c', 'e', '_'];
13 let mut program = Program::new(alphabet, State(4));
14 program.extend([
15 (1, 't', 2, 'n', Move::Right),
16 (2, 'e', 3, 'i', Move::Right),
17 (3, 's', 4, 'c', Move::Right),
18 (4, 't', 0, 'e', Move::None),
19 // Revers
20 (1, 'n', 2, 't', Move::Right),
21 (2, 'i', 3, 'e', Move::Right),
22 (3, 'c', 4, 's', Move::Right),
23 (4, 'e', 0, 't', Move::None),
24 ])?;
25 let machine = Classic::new(program, '_')?;
26
27 let test = Tape::from("test");
28 let nice = machine.translate_nrm(test.clone())?;
29 println!(
30 "{} {}!",
31 String::from_iter(nice.as_vec()),
32 String::from_iter(test.as_vec())
33 );
34 Ok(())
35}More examples
11fn main() -> Result<(), String> {
12 let mut program = Program::new(vec![' ', '0', '1', '+'], State(8));
13 program.extend([
14 // Sub 1, also init zero check
15 (1, ' ', 0, ' ', Move::None),
16 (1, '0', 1, '0', Move::Left),
17 (1, '1', 2, '0', Move::Right),
18 (1, '+', 6, '+', Move::Right),
19 // Subs part
20 (2, ' ', 3, ' ', Move::Left),
21 (2, '0', 2, '1', Move::Right),
22 // 2, '1' -> Impl
23 // 2, '+' -> Err
24 //
25 // Find + on left
26 // 3, ' ' -> Err
27 (3, '0', 3, '0', Move::Left),
28 (3, '1', 3, '1', Move::Left),
29 (3, '+', 4, '+', Move::Left),
30 // Add 1
31 (4, ' ', 5, '1', Move::Right),
32 (4, '0', 5, '1', Move::Right),
33 (4, '1', 4, '0', Move::Left),
34 // 4, '+' -> Err
35 //
36 // Find + on rigth
37 // 5, ' ' -> Imp
38 (5, '0', 5, '0', Move::Right),
39 (5, '1', 5, '1', Move::Right),
40 (5, '+', 6, '+', Move::Right),
41 // Zero check
42 (6, ' ', 8, ' ', Move::Left),
43 (6, '0', 6, '0', Move::Right),
44 (6, '1', 7, '1', Move::Right),
45 // 6, '+' -> Err
46 //
47 // Find last num
48 (7, ' ', 1, ' ', Move::Left),
49 (7, '0', 7, '0', Move::Right),
50 (7, '1', 7, '1', Move::Right),
51 // 7, '+' -> Err
52 //
53 // Clear + and after
54 // 8, ' ' - Imp
55 (8, '0', 8, ' ', Move::Left),
56 // 8, '1' - Imp
57 (8, '+', 0, ' ', Move::Right),
58 ])?;
59 let machine = Classic::new(program, ' ')?;
60
61 // Change and try to run this example!
62 let lhs = "10101";
63 let rhs = "111";
64 // -----------------------------------
65 let tape = Tape::from(format!("{}+{}", lhs, rhs));
66
67 let res = machine.translate_std(tape)?;
68 println!("{} + {} = {}", lhs, rhs, String::from_iter(res.as_vec()));
69
70 Ok(())
71}11fn main() -> Result<(), String> {
12 use nrm_machines::*;
13
14 let stand = new_stand_machine();
15 let zerofy = new_zerofy_machine();
16 let l_shift = new_left_shift_machine();
17 let r_shift = new_right_shift_machine();
18 let trans = new_trans_machine();
19
20 let mut program = Program::new(
21 vec![
22 stand.clone(),
23 zerofy.clone(),
24 l_shift.clone(),
25 r_shift.clone(),
26 trans.clone(),
27 ],
28 State(9),
29 );
30 // This is simplest implementation of `change choose second to choose third` machine
31 program.extend([
32 // Find l_shift
33 (1, r_shift.clone(), 1, r_shift.clone(), Move::Right),
34 (1, trans.clone(), 1, trans.clone(), Move::Right),
35 (1, zerofy.clone(), 1, zerofy.clone(), Move::Right),
36 (1, l_shift.clone(), 2, stand.clone(), Move::Left),
37 // Clear until r_shift
38 (2, zerofy.clone(), 2, stand.clone(), Move::Left),
39 (2, trans.clone(), 2, stand.clone(), Move::Left),
40 (2, r_shift.clone(), 3, r_shift.clone(), Move::Right),
41 //
42 // Set second r_shift
43 (3, stand.clone(), 4, r_shift.clone(), Move::Right),
44 // Set first trans
45 (4, stand.clone(), 5, trans.clone(), Move::Right),
46 // Set first zerofy
47 (5, stand.clone(), 6, zerofy.clone(), Move::Right),
48 // Set first l_shift
49 (6, stand.clone(), 7, l_shift.clone(), Move::Right),
50 // Set second trans
51 (7, stand.clone(), 8, trans.clone(), Move::Right),
52 // Set second zerofy
53 (8, stand.clone(), 9, zerofy.clone(), Move::Right),
54 // Set second l_shift and stop execution
55 (9, stand.clone(), 0, l_shift.clone(), Move::None),
56 ])?;
57
58 let hyper_machine = Classic::new(program, stand.clone())?;
59 let choose_second = Tape::new([
60 r_shift.clone(),
61 trans.clone(),
62 zerofy.clone(),
63 l_shift.clone(),
64 ]);
65 let result_choose_third = hyper_machine.translate_nrm(choose_second)?;
66
67 let expected_choose_third = Tape::new([
68 r_shift.clone(),
69 r_shift.clone(),
70 trans.clone(),
71 zerofy.clone(),
72 l_shift.clone(),
73 trans.clone(),
74 zerofy.clone(),
75 l_shift.clone(),
76 ]);
77
78 assert_eq!(expected_choose_third, result_choose_third);
79 println!("If you're reading this, hyper machine successful transform choose second machine");
80
81 let tape = Tape::from("0101101110");
82 let mut conf = Configuration::new_nrm(tape.clone())?;
83 for machine in result_choose_third.as_vec() {
84 conf = machine.execute(conf).unwrap();
85 conf.state = State(1)
86 }
87 println!(
88 "Choose third machine translate {} into {}",
89 String::from_iter(tape.as_vec()),
90 String::from_iter(conf.tape().as_vec())
91 );
92
93 Ok(())
94}
95
96// This module just contains several nrm machines
97mod nrm_machines {
98 use super::*;
99
100 pub fn new_stand_machine() -> Classic<char> {
101 let mut program = Program::new(vec!['0', '1'], State(1));
102 program
103 .extend([(1, '0', 0, '0', Move::None), (1, '1', 0, '1', Move::None)])
104 .unwrap();
105 Classic::new(program, '0').unwrap()
106 }
107
108 pub fn new_zerofy_machine() -> Classic<char> {
109 let mut program = Program::new(vec!['0', '1'], State(4));
110 program
111 .extend([
112 (1, '0', 2, '0', Move::Right),
113 (2, '0', 3, '0', Move::Left),
114 (2, '1', 2, '1', Move::Right),
115 (3, '0', 0, '0', Move::None),
116 (3, '1', 4, '0', Move::None),
117 (4, '0', 3, '0', Move::Left),
118 ])
119 .unwrap();
120 Classic::new(program, '0').unwrap()
121 }
122
123 pub fn new_left_shift_machine() -> Classic<char> {
124 let mut program = Program::new(vec!['0', '1'], State(2));
125 program
126 .extend([
127 (1, '0', 2, '0', Move::Left),
128 (2, '0', 0, '0', Move::None),
129 (2, '1', 2, '1', Move::Left),
130 ])
131 .unwrap();
132 Classic::new(program, '0').unwrap()
133 }
134
135 pub fn new_right_shift_machine() -> Classic<char> {
136 let mut program = Program::new(vec!['0', '1'], State(2));
137 program
138 .extend([
139 (1, '0', 2, '0', Move::Right),
140 (2, '0', 0, '0', Move::None),
141 (2, '1', 2, '1', Move::Right),
142 ])
143 .unwrap();
144 Classic::new(program, '0').unwrap()
145 }
146
147 pub fn new_trans_machine() -> Classic<char> {
148 let mut program = Program::new(vec!['0', '1'], State(19));
149 program
150 .extend([
151 (1, '0', 2, '0', Move::Right),
152 (2, '0', 3, '0', Move::None),
153 (2, '1', 2, '1', Move::Right),
154 (3, '0', 4, '0', Move::Left),
155 (4, '0', 7, '0', Move::None),
156 (4, '1', 5, '0', Move::None),
157 (5, '0', 6, '0', Move::Left),
158 (6, '0', 7, '1', Move::None),
159 (6, '1', 6, '1', Move::Left),
160 (7, '0', 16, '1', Move::None),
161 (7, '1', 8, '1', Move::Left),
162 (8, '0', 18, '0', Move::Right),
163 (8, '1', 9, '0', Move::None),
164 (9, '0', 10, '0', Move::Right),
165 (10, '0', 11, '1', Move::None),
166 (10, '1', 10, '1', Move::Right),
167 (11, '1', 12, '1', Move::Left),
168 (12, '1', 13, '0', Move::None),
169 (13, '0', 14, '0', Move::Left),
170 (14, '0', 15, '1', Move::None),
171 (14, '1', 14, '1', Move::Left),
172 (15, '0', 7, '0', Move::None),
173 (15, '1', 7, '1', Move::None),
174 (16, '1', 17, '1', Move::Left),
175 (17, '0', 19, '0', Move::Right),
176 (17, '1', 15, '0', Move::None),
177 (18, '0', 0, '0', Move::None),
178 (18, '1', 18, '1', Move::Right),
179 (19, '1', 0, '0', Move::None),
180 ])
181 .unwrap();
182 Classic::new(program, '0').unwrap()
183 }Trait Implementations§
Source§impl<S: Symbol> TuringMachine<S> for Classic<S>
impl<S: Symbol> TuringMachine<S> for Classic<S>
Source§fn execute_once(
&self,
conf: Configuration<S>,
) -> Result<Configuration<S>, String>
fn execute_once( &self, conf: Configuration<S>, ) -> Result<Configuration<S>, String>
Executes Configuration once by mutation.
Returns [Ok(Configuration)] when an crate::instruction::Instruction
exists for the current Configuration symbol and state.
And otherwise returns [Err(String)] with diagnostic information.
Source§fn execute_until(
&self,
conf: Configuration<S>,
until: impl Fn(&Configuration<S>) -> bool,
) -> Result<Configuration<S>, String>
fn execute_until( &self, conf: Configuration<S>, until: impl Fn(&Configuration<S>) -> bool, ) -> Result<Configuration<S>, String>
Executes Configuration until predicate is false by mutation.
Returns [Ok(Configuration)] when an crate::instruction::Instruction
exists for the current Configuration symbol and state.
And otherwise returns [Err(String)] with diagnostic information.
Source§fn execute(&self, conf: Configuration<S>) -> Result<Configuration<S>, String>
fn execute(&self, conf: Configuration<S>) -> Result<Configuration<S>, String>
crate::program::Program and returns a mutated Configuration
using the TuringMachine::execute_until method with the conf.state == 0
predicate. This is the most commonly used method for crate::program::Program execution.Source§fn translate_std(&self, tape: Tape<S>) -> Result<Tape<S>, String>
fn translate_std(&self, tape: Tape<S>) -> Result<Tape<S>, String>
Tape using the TuringMachine::execute
method as the Configuration::new_std.Source§fn translate_nrm(&self, tape: Tape<S>) -> Result<Tape<S>, String>
fn translate_nrm(&self, tape: Tape<S>) -> Result<Tape<S>, String>
Tape using the TuringMachine::execute
method as the Configuration::new_nrm.Source§impl<S: Symbol> With<Classic<S>> for Classic<S>
impl<S: Symbol> With<Classic<S>> for Classic<S>
Source§fn with(&self, other: &Classic<S>) -> Self::Output
fn with(&self, other: &Classic<S>) -> Self::Output
Makes superposition with two or more Classic machines by chain.
This method accept only Classic struct and can be used only for
another Classic machine.
Returns a new [Ok(Classic)] when machines can be concatenated
and [Err(String)] with diagnostic information when machines
have different alphabets or default symbols.
Source§impl<S: Symbol> With<Classic<S>> for Result<Classic<S>, String>
impl<S: Symbol> With<Classic<S>> for Result<Classic<S>, String>
Source§fn with(&self, other: &Classic<S>) -> Self::Output
fn with(&self, other: &Classic<S>) -> Self::Output
Makes superposition with two or more Classic machines by chain.
This method accept only Classic struct and can be used only for
Result<Classic, String>.
Returns a new [Ok(Classic)] when self is Result::Ok and machines
can be concatenated and [Err(String)] when self is Result::Ok
but machines have different alphabets or default symbols.
And Returns a copy of [Err(String)] when self is Result::Err.