Initial commit

This commit is contained in:
Wroclaw 2022-11-26 05:03:22 +01:00
commit 19e609e3b0
7 changed files with 339 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
build

13
.vscode/c_cpp_properties.json vendored Normal file
View file

@ -0,0 +1,13 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**"
],
"cppStandard": "c++17",
"cStandard": "c17"
}
],
"version": 4
}

53
example1.cpp Normal file
View file

@ -0,0 +1,53 @@
#include <iostream>
#include <vector>
#include "turing.cpp"
#include "utils/operators.cpp"
#include "utils/print.cpp"
int main() {
auto def = new Turing::Definition<char, char> {
.defaultState = '0',
.defaultValue = '#',
.instructions = {
// Palindrome checker
// if the last state is R or 0, then it is a palindrome
// otherwise it is not
"00a0r"_i,
"01b1r"_i,
"a0a0r"_i,
"a1a1r"_i,
"b0b0r"_i,
"b1b1r"_i,
"a#A#l"_i,
"b#B#l"_i,
"A0r#l"_i,
"B1r#l"_i,
"r0r0l"_i,
"r1r1l"_i,
"r#R#r"_i,
"R00#r"_i,
"R10#r"_i,
},
};
auto turing = new Turing::Machine<char, char>(def);
turing->setTape("0010110100"_v);
print(turing);
int i = 0;
while (i++ < 100) {
if (!turing->tick()) break;
print(turing);
}
print(turing);
return 0;
}

44
example2.cpp Normal file
View file

@ -0,0 +1,44 @@
#include <iostream>
#include "turing.cpp"
#include "utils/print.cpp"
enum values {
yes = 1,
no = 0,
blank = 6,
};
int main() {
auto def = new Turing::Definition<char, values> {
.defaultState = 'a',
.defaultValue = values::blank,
.instructions = {
// multiply binary represented number by 2
Turing::Instruction('a', values::yes, 'a', values::yes, Turing::Movement::right),
Turing::Instruction('a', values::no, 'a', values::no, Turing::Movement::right),
Turing::Instruction('a', values::blank, 'b', values::no, Turing::Movement::right),
}
};
auto turing = new Turing::Machine(def);
turing->setTape({
values::no,
values::no,
values::yes,
values::no,
values::yes,
values::no,
values::yes,
values::no
});
print(turing);
std::cout << '\n';
while(turing->tick());
print(turing);
return 0;
}

185
turing.cpp Normal file
View file

@ -0,0 +1,185 @@
#include <vector>
#pragma once
namespace Turing {
// Available movements on the turing machine
enum Movement {
left = false,
right = true,
};
// Turing instruction
template <typename S, typename V>
struct Instruction {
S currentState;
V currentValue;
S nextState;
V nextValue;
Movement tapeMovement;
constexpr Instruction(const S cS, const V cV, const S nS, const V nV, Movement tM) {
this->currentState = cS;
this->currentValue = cV;
this->nextState = nS;
this->nextValue = nV;
this->tapeMovement = tM;
}
Instruction() = default;
};
// Configuration of the Turing machine
template <typename S, typename V>
struct Definition {
S defaultState;
V defaultValue;
std::vector<Instruction<S, V>> instructions;
};
// The Turing Machine
template <typename S, typename V>
class Machine
{
const Definition<S, V>* definition;
int position = 0; // current position
S state; // current state
std::vector<V> memory; // aka tape
int memoryStart = 0; // the position of the beginning of the saved memory
V& value() {
this->ensure(position);
return this->memory[position - memoryStart];
}
public:
unsigned int runCount = 0;
S getState() { return this->state; }
int getPosition() {return this->position; }
auto getMemory() { return std::vector<V>(this->memory); }
// returns position of the behind last saved element in the saved memory
int getMemoryEnd() { return this->memoryStart + this->memory.size(); }
int getMemoryStart() { return this->memoryStart; }
Machine(const Definition<S, V>* definition) {
this->definition = definition;
this->state = definition->defaultState;
}
/**
* @brief Ensures that provided position is saved in memory and avaliable.
*
* @param pos the position
* @return true if changes were made, false otherwise
*/
bool ensure(const int pos) {
if (pos >= this->memoryStart && pos < this->getMemoryEnd()) return false;
// if ensuring pos is after memory ending
if (pos >= this->getMemoryEnd()) {
this->memory.insert(
this->memory.end(),
this->getMemoryEnd() - pos + 1,
this->definition->defaultValue
);
}
// if ensuring pos is before memory ending
if (pos < this->memoryStart) {
this->memory.insert(
this->memory.begin(),
this->memoryStart - pos,
this->definition->defaultValue
);
this->memoryStart = pos;
}
return true;
}
/**
* @brief Ensures that current position is saved in memory and available
*
* @return true if changes were made, false otherwise
*/
bool ensure() { return this->ensure(this->position); }
/**
* @brief sets the value at given position
*/
void set(const V& value, int pos) {
this->ensure(pos);
this->memory[pos - this->memoryStart] = value;
}
/**
* @brief Gets state from the memory
*
* @param pos from which position get the value from
*/
V& at(int pos) {
this->ensure(pos);
return this->memory[pos - this->memoryStart];
}
/**
* @brief Set the saved memory by copying values from the provided vector
*
* @param newTape vector of new memory values
* @param position the position of the head after loading the memory, default 0 (the beginning)
*/
void setTape(const std::vector<V>& newTape, int position = 0) {
this->memoryStart = 0;
this->memory = newTape;
this->position = position;
}
/**
* @brief do tick() for n times
*
* @return the ammount of remaining ticks after halting
*/
unsigned int tickFor(const unsigned int times) {
unsigned int i = times;
while (i > 0 && this->tick()) i--;
return i;
}
/**
* @brief evaluate what happens in the machine after one tick and check if the machine is halted
*
* @return false if halted, true if work has been done
*/
bool tick() {
V& value = this->value();
Turing::Instruction<S, V>* thatInstruction = nullptr;
for(auto i : this->definition->instructions) {
if (value == i.currentValue & this->state == i.currentState) {
thatInstruction = &i;
break;
}
}
if (thatInstruction == nullptr) return false;
this->set(thatInstruction->nextValue, this->position);
this->state = thatInstruction->nextState;
thatInstruction->tapeMovement == Movement::right ? this->position++ : this->position--;
this->runCount++;
return true;
}
}; // class Machine
} // namespace Turing

25
utils/operators.cpp Normal file
View file

@ -0,0 +1,25 @@
#include <cstdlib>
#include "../turing.cpp"
/**
* @brief Replaces provided string with appriopriate Turing::Instruction<char, char>
* it takes 'l' character as a left move
*/
constexpr Turing::Instruction<char, char> operator ""_i (const char* txt, const size_t len) {
char cS = *txt++;
char cV = *txt++;
char nS = *txt++;
char nV = *txt++;
Turing::Movement mv = *txt++ == 'l' ? Turing::Movement::left : Turing::Movement::right;
return Turing::Instruction<char, char>(cS, cV, nS, nV, mv);
};
// Replaces provided string with aprriopriate vector<char>
const std::vector<char> operator ""_v (const char* txt, const size_t len) {
auto rvalue = std::vector<char>(len);
for (int i = 0; i < len; i++) {
rvalue[i] = *txt++;
}
return rvalue;
}

18
utils/print.cpp Normal file
View file

@ -0,0 +1,18 @@
#include <iostream>
#include "../turing.cpp"
/**
* @brief Prints debug-like information about provided machine
*/
template <typename S, typename V>
void print(Turing::Machine<S, V>* machine) {
machine->ensure();
std::cout << "rc:" << machine->runCount << ", st:" << machine->getState() << '\n';
for (int i = machine->getMemoryStart(); i < machine->getMemoryEnd(); i++)
std::cout << (machine->at(i));
std::cout << '\n';
for (int i = machine->getMemoryStart(); i < machine->getPosition(); i++)
std::cout << ' ';
std::cout << "^\n\n";
}