123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- #include <iostream>
- #include <array>
- #include <algorithm>
- #include <initializer_list>
- #include <cstdlib>
- #include <string.h>
- // #define NDEBUG
- #include <cassert>
- #ifdef ARDUINO
- void __assert(const char *__func, const char *__file, int __lineno, const char *__sexp) {
- // abort program execution.
- abort();
- }
- #endif
- constexpr short max_tape_len = 1024;
- struct tape_t {
- short head = 0;
- char tape_stg[max_tape_len];
- tape_t(short init_pos, const char *init, char blank = '.') {
- reset_tape(init_pos, init, blank);
- }
- void reset_tape(short init_pos, const char *init, char blank = '.') {
- head = init_pos;
- int i = 0;
- while(*init != '\0')
- tape_stg[i++] = *init++;
- std::fill(std::begin(tape_stg) + i, std::end(tape_stg), blank);
- }
- void shift_head_right(short s = 1) {
- head += s;
- assert(head < max_tape_len);
- }
- void shift_head_left(short s = 1) {
- head -= s;
- assert(head >= 0);
- }
- bool in_bounds(short pos) {
- return pos >= 0 && pos < max_tape_len;
- }
- char read() {
- return tape_stg[head];
- }
- void write(char symbol) {
- tape_stg[head] = symbol;
- }
- };
- enum class action_t : char {
- fail,
- left,
- right,
- succeed,
- stay,
- };
- struct rule {
- short state_in;
- char symbol_in;
- short state_out;
- char symbol_out;
- action_t action;
- };
- template<size_t N_FINALS, size_t N_RULES>
- struct turing_machine {
- short state = 0;
- const short final_states[N_FINALS];
- const rule rules[N_RULES];
- tape_t tape;
- char blank = '.';
- char wildcard = '*';
- short ticks = 0;
- // Disable copying the tm as well as moving it
- turing_machine(turing_machine&) = delete;
- turing_machine(turing_machine&&) = delete;
- void succeed() {
- std::cout << "Success\n";
- std::exit(0);
- }
- void fail() {
- std::cout << "Failed\n";
- std::exit(1);
- }
- bool is_final(short st) {
- return std::find(std::begin(final_states), std::end(final_states), st)
- != std::end(final_states);
- }
- bool step_forward(int steps = 1) {
- for(int i = 0; i < steps; ++i){
- char symbol = tape.read();
- short state = this->state; char wildcard = this->wildcard;
- char next_symbol; short next_state; action_t action;
- // std::cout << i << ": [" << tape.head << "] = \'" << symbol << "\'; s = " << state << "\n";
- // Find a rule matching the current state and either the current symbol
- // or the wildcard
- if(std::find_if(std::begin(rules), std::end(rules),
- // Capture these variables, so they can be accessed
- // inside the lambda
- [&next_state, &next_symbol, &action,
- symbol, state, wildcard](rule r) {
- // std::cout << "(" << state << ", \'" << symbol << "\') <=> "
- // << "(" << r.state_in << ", \'" << r.symbol_in << "\') \n";
- if(r.state_in == state &&
- (r.symbol_in == symbol || r.symbol_in == wildcard)) {
- // std::cout << (int) r.symbol_out << "\n";
- next_state = r.state_out;
- next_symbol = r.symbol_out;
- action = r.action;
- return true;
- }
- return false;
- }) != std::end(rules)) {
- if(next_symbol != wildcard)
- tape.write(next_symbol);
- ++ticks;
- this->state = next_state;
- if(is_final(this->state)){
- succeed();
- }
- switch(action) {
- case action_t::fail:
- fail();
- break;
- case action_t::left:
- tape.shift_head_left();
- break;
- case action_t::right:
- tape.shift_head_right();
- break;
- case action_t::succeed:
- succeed();
- break;
- case action_t::stay:
- break; // Do nothing
- }
- } else {
- fail();
- }
- // Reading an empty cell on the tape means we have failed
- // Doing this after the rest, in case a transition wasn't found
- // This should happen before, but, for compatibility with the reference,
- // it must be done afterwards, as it includes rules matching `blank`
- // // Therefore, TODO, move up
- // if(symbol == blank)
- // fail();
- }
- return true;
- }
- };
- template<typename T, size_t N1, size_t N2>
- turing_machine(short, const T (&)[N1], const rule (&)[N2], tape_t) -> turing_machine<N1, N2>;
- int main() {
- turing_machine tm{0, {100},
- // st, char, next_st, n_char, act
- {{0, '.', 100, '.', action_t::right},
- {0, '0', 1, '#', action_t::right},
- {1, '0', 1, '0', action_t::right},
- {1, '.', 2, '0', action_t::left},
- {2, '0', 2, '0', action_t::left},
- {2, '#', 3, '#', action_t::right},
- {3, '0', 4, 'A', action_t::right},
- {4, '.', 100, '.', action_t::left},
- {4, '0', 5, 'C', action_t::right},
- {5, '0', 6, 'C', action_t::right},
- {6, '0', 7, 'C', action_t::right},
- {7, '.', 100, '.', action_t::left},
- {7, 'a', 7, 'a', action_t::right},
- {7, 'A', 7, 'A', action_t::right},
- {7, 'C', 7, 'C', action_t::right},
- {7, '0', 9, '0', action_t::left},
- {9, 'C', 9, 'C', action_t::left},
- {9, 'A', 9, 'A', action_t::left},
- {9, 'a', 9, 'A', action_t::left},
- {9, '#', 10, '#', action_t::right},
- {10, 'A', 10, 'A', action_t::right},
- {10, 'C', 11, 'a', action_t::right},
- {11, 'a', 11, 'a', action_t::right},
- {11, 'C', 11, 'C', action_t::right},
- {11, '0', 8, 'C', action_t::right},
- {8, '0', 12, 'C', action_t::left},
- {12, 'C', 12, 'C', action_t::left},
- {12, 'a', 12, 'a', action_t::left},
- {12, 'A', 11, 'a', action_t::right},
- {12, '#', 13, '#', action_t::right},
- {13, 'a', 13, 'a', action_t::right},
- {13, 'C', 13, 'C', action_t::right},
- {13, '0', 14, 'C', action_t::right},
- {14, '.', 100, '.', action_t::left},
- {14, '0', 9, '0', action_t::left}
- // {100,'*', 100, '*', action_t::succeed}
- },
- {0, "0"}};
- tm.step_forward(1000);
- }
|