From cc0813ef5affb811c5ccccd8fc65024153ff64f1 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 21 Jun 2023 00:54:03 +0200 Subject: [PATCH 1/5] ignore generated files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a52afa --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +tm From f9386a36a7945b9ac90ddb1b7b3cf068113a16c3 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 21 Jun 2023 02:19:53 +0200 Subject: [PATCH 2/5] keep reading input on missing file, instead of crashing --- main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index 056fdbe..fee595b 100644 --- a/main.cpp +++ b/main.cpp @@ -8,10 +8,10 @@ int main(int argc, char const *argv[]){ for (int i = 1; i < argc; ++i){ std::cout << argv[i] << ":\n"; TuringMachine t(argv[i]); - t.parseFile(); + if(t.parseFile()){ continue; } t.makeTransitionTables(); t.turingSimulator(); std::cout << "\n\n"; } return 0; -} \ No newline at end of file +} From 18cb4b8fab7b0c811a1a4b3ad100efba98a2c288 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 21 Jun 2023 15:44:46 +0200 Subject: [PATCH 3/5] added alternative display mode --- turing_machine.cpp | 153 +++++++++++++++++++++++++++++++++++++++++---- turing_machine.h | 18 ++++-- 2 files changed, 154 insertions(+), 17 deletions(-) diff --git a/turing_machine.cpp b/turing_machine.cpp index d314ca3..dbd7412 100644 --- a/turing_machine.cpp +++ b/turing_machine.cpp @@ -1,11 +1,140 @@ #include "turing_machine.h" +#define COUT_N(times, input){ \ + for(int i_ = 0; i_ < times; i_++){ \ + std::cout << input; \ + } \ +} + +#define COUT_CENTERED(N, input, len){ \ + const int padding = ((N - len) / 2); \ + COUT_N(padding, ' '); \ + std::cout << input; \ + COUT_N((len % 2 ? padding : padding+1), ' '); \ +} + +std::string TuringMachine::state_id_to_name(const int &id){ + for(const auto& i : state_id){ + if(i.second == id){ + return i.first; + } + } + return ""; +} + +char TuringMachine::char_id_to_symbol(const int &id){ + for(const auto& i : alph_id){ + if(i.second == id){ + return i.first; + } + } + return '?'; +} + +char dir_int_to_char(const int &d){ + switch(d){ + case -1: + return '<'; + case 0: + return '-'; + case 1: + return '>'; + } + return '?'; +} + void TuringMachine::displayTape() { - std::cout << "\r" << tape.substr(0, ptr); // display tape contents before the pointer head - std::cout << "[" << tape[ptr] << "]"; // display tape content under the pointer head - std::cout << tape.substr(ptr + 1); // display tape contents after the pointer head - std::cout << std::flush; - usleep(200000); + switch(tape_display_mode){ + case TapeDisplayMode::SINGLE_LINE: + std::cout << "\r" << tape.substr(0, ptr); // display tape contents before the pointer head + std::cout << "[" << tape[ptr] << "]"; // display tape content under the pointer head + std::cout << tape.substr(ptr + 1); // display tape contents after the pointer head + std::cout << std::flush; + usleep(200000); + break; + case TapeDisplayMode::DRAW: + // machine body + constexpr int ASSUMED_MAX_STATE_NAME_WIDTH = 13; + constexpr int MARGIN = 2; + constexpr char MACHINE_NAME[] = "TM"; + constexpr int MACHINE_NAME_PADDING = (ASSUMED_MAX_STATE_NAME_WIDTH - (sizeof(MACHINE_NAME)-1) + 1) / 2; + constexpr int PIN_PADDING = (ASSUMED_MAX_STATE_NAME_WIDTH+(MARGIN*2-(2*1)))/2; + constexpr int PIN_POSITION = (ASSUMED_MAX_STATE_NAME_WIDTH+(MARGIN*2-(2*1)))/2 + MARGIN; + const int ARROW_PADDING = 2+(4*ptr); + // top + std::cout << "┏"; + COUT_N(ASSUMED_MAX_STATE_NAME_WIDTH+(MARGIN*2-(2*1)), "━"); + std::cout << "┓" << std::endl; + // body + std::cout << "┃ "; + COUT_CENTERED(ASSUMED_MAX_STATE_NAME_WIDTH, MACHINE_NAME, (sizeof(MACHINE_NAME)-1)); + std::cout << " ┃" << std::endl; + // state + std::cout << "┃ "; + std::string state_name = state_id_to_name(present_state_id); + COUT_CENTERED(ASSUMED_MAX_STATE_NAME_WIDTH, state_name, state_name.size()); + std::cout << " ┃" << std::endl; + // bottom + std::cout << "┗"; + COUT_N(PIN_PADDING, "━"); + std::cout << "┰"; + COUT_N(PIN_PADDING, "━"); + std::cout << "┛" << std::endl; + // arrow + COUT_N(PIN_POSITION - 1, ' '); + std::cout << "│" << std::endl; + if(ARROW_PADDING < PIN_POSITION){ + COUT_N(ARROW_PADDING, ' '); + std::cout << "┌"; + COUT_N(PIN_POSITION-ARROW_PADDING-2, "─"); + std::cout << "┘" << std::endl; + }else if(ARROW_PADDING > PIN_POSITION){ + COUT_N(PIN_POSITION-1, ' '); + std::cout << "└"; + COUT_N(ARROW_PADDING-PIN_POSITION, "─"); + std::cout << "┐" << std::endl; + }else{ + COUT_N(ARROW_PADDING, ' '); + std::cout << "│" << std::endl; + } + COUT_N(ARROW_PADDING, ' '); + std::cout << "│" << std::endl; + COUT_N(ARROW_PADDING, ' '); + std::cout << "V" << std::endl; + // tape + std::cout << '+'; + COUT_N(tape.size(), "---+"); + std::cout << std::endl; + std::cout << '|'; + COUT_N(tape.size(), ' ' << tape[i_] << " |"); + std::cout << std::endl; + std::cout << '+'; + COUT_N(tape.size(), "---+"); + std::cout << std::endl; + // rules + for(const auto &i : state_id){ + state_name = i.first; + for(int h = 0; h < state_table[i.second].size(); h++){ + if(state_id_to_name(state_table[i.second][h]) == ""){ continue; } + std::cout << "δ(" + << state_name << ", " + << char_id_to_symbol(h) + << ") := (" + << state_id_to_name(state_table[i.second][h]) << ", " + << write_table[i.second][h] << ", " + << dir_int_to_char(dir_table[i.second][h]) + << ")"; + if(present_state_id == i.second && tape[ptr] == char_id_to_symbol(h)){ + std::cout << "\t<"; + } + std::cout << std::endl << std::endl; + } + } + // separator + COUT_N(5, std::endl); + std::cout << std::flush; + break; + } } int TuringMachine::parseFile() { @@ -53,7 +182,7 @@ int TuringMachine::parseFile() { void TuringMachine::makeTransitionTables(){ std::string line, present_state, next_state, tape; char read_char, write_char, direction; - int present_state_id, next_state_id, read_char_id, dir_id; + int current_state_id, next_state_id, read_char_id, dir_id; std::ifstream ifs; ifs.open(file_name, std::ios:: in); @@ -68,7 +197,7 @@ void TuringMachine::makeTransitionTables(){ iss >> read_char >> write_char >> direction >> next_state; // find respective unique id's - present_state_id = state_id.find(present_state)->second; + current_state_id = state_id.find(present_state)->second; next_state_id = state_id.find(next_state)->second; read_char_id = alph_id.find(read_char)->second; if(direction == 'l') @@ -79,16 +208,14 @@ void TuringMachine::makeTransitionTables(){ dir_id = 0; // populate transition tables with unique id's - state_table[present_state_id][read_char_id] = next_state_id; - write_table[present_state_id][read_char_id] = write_char; - dir_table[present_state_id][read_char_id] = dir_id; + state_table[current_state_id][read_char_id] = next_state_id; + write_table[current_state_id][read_char_id] = write_char; + dir_table[current_state_id][read_char_id] = dir_id; } ifs.close(); } void TuringMachine::turingSimulator(){ - int present_state_id = 0, read_char_id, dir_id = 0; - displayTape(); while(true){ read_char_id = alph_id.find(tape[ptr])->second; @@ -118,4 +245,4 @@ void TuringMachine::turingSimulator(){ tape = tape + "_"; displayTape(); } -} \ No newline at end of file +} diff --git a/turing_machine.h b/turing_machine.h index b7da18d..be32a95 100644 --- a/turing_machine.h +++ b/turing_machine.h @@ -20,16 +20,26 @@ class TuringMachine { tape; // input tape on which turing machine works int num_states, // number of states num_alphs, // number of alphabets - ptr; // location of pointer head of turing machine + ptr, // location of pointer head of turing machine + present_state_id = 0, + read_char_id = 0, + dir_id = 0; std::map state_id; // maps each state to a unique key std::map alph_id; // maps each alphabet to a unique key std::vector accept_state; std::vector> state_table; // transition table storing next state - // for a given (present state, input char) pair + // for a given (state, input char) pair std::vector> dir_table; // transition table storing next direction - // for a given (state, char) pair + // for a given (state, input char) pair std::vector> write_table; // transition table storing next write char - // for a given (state, char) pair + // for a given (state, input char) pair + enum class TapeDisplayMode { + SINGLE_LINE, + DRAW + } tape_display_mode = TapeDisplayMode::SINGLE_LINE; + + std::string state_id_to_name(const int &id); + char char_id_to_symbol(const int &id); public: TuringMachine(std::string _file_name): file_name(_file_name), From d08d771883282cd3944d7ba6fa0db6f770f42ab6 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 21 Jun 2023 15:45:06 +0200 Subject: [PATCH 4/5] +sample --- sample/even_zeros | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 sample/even_zeros diff --git a/sample/even_zeros b/sample/even_zeros new file mode 100644 index 0000000..5a21e38 --- /dev/null +++ b/sample/even_zeros @@ -0,0 +1,9 @@ +s01010011 +q0 s s r e +e 0 0 r o +o 0 0 r e +e 1 1 r e +o 1 1 r o +e _ _ - n +o _ _ - n +accept n From 1291d42ff87cffa1882388f6afb479474db5e585 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 21 Jun 2023 16:04:57 +0200 Subject: [PATCH 5/5] improved makefile with patern rules and variables --- Makefile | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 3393741..a22038c 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,17 @@ -CC=g++ -CFLAGS=-c +CXX=g++ +CXXFLAGS= -all: tm +SRC=main.cpp turing_machine.cpp +OBJ=${SRC:.cpp=.o} +OUTPUT=tm -tm: main.o turing_machine.o - $(CC) main.o turing_machine.o -o tm +all: ${OUTPUT} -main.o: main.cpp - $(CC) $(CFLAGS) main.cpp +tm: ${OBJ} + ${LINK.cpp} main.o turing_machine.o -o ${OUTPUT} -turing_machine.o: turing_machine.cpp - $(CC) $(CFLAGS) turing_machine.cpp +%.o: %.c + ${COMPILE.cpp} -c $+ -o $@ clean: - rm -rf *.o tm + rm -rf ${OBJ} ${OUTPUT}