模拟图灵机XN*2

一. 题目分析
题目要求为:模拟图灵机的运行过程,在本题中,模拟了图灵机的XN*2的过程,要求输出每一个指令步骤的结果。通过对图灵机运行过程的模拟,对于其中的原理理解更为深刻。

对于处理之后得到的字符串,初始化内态为零,进行单个字符的读入,对于每个字符,进行内态与输入字符的判断,对于不同的情况,得到不同的内态和相应的输入改变(可能改变,也可能不变),重复这个过程,直到进行到终止的命令。再将得到的终止命令进行相应的转化处理,得到相应的结果并输出。
二.算法构造

大致思路:
1.一开始将输入的数字转换为二进制数据,再将二进制数转换为图灵机对应的磁带编码,

2.对这个得到的编码,使用图灵机的指令集进行编码,在编码过程中,对于每一种指令的执行之后,输出相应的执行指令,内态以及相应的输入字符的改变情况,再递归,继续下一步的指令操作。

3.编码之后,将得到的编码进行还原,即将相应的编码先转化为二进制,再将二进制转换为相应的数字,输出,得到结果。

三. 算法实现

//模拟图灵机XN*2
//auhtor:lyq
// time:2019-3-17  
#include<iostream>
#include<string>
#include<stdlib.h> 
#include<cmath>
using namespace std;
string c;//全局变量--输入的原始数据对应的字符串 
int i=0;//全局变量--字符串计数变量 
string f(int a,char c1)//处理函数 
{
	int n=c.length();//输如字符串的长度 
	if(a== 0)
	{
		if(c1=='0')
			{
				cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"0"<<" "<<"0 R"<<endl;
				cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl; 
				cout<<"下一个内态为:"<<"0"<<"当前输入不变"<<endl; 
				if(i+1== n)//自动补零 
					c+='0';
				a=0;
				cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
				cout<<endl; 
				return (f(a,c[++i]));
			}
		else if(c1=='1')
			{
				cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"1"<<" "<<"0 R"<<endl;
				cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;  
				cout<<"下一个内态为:"<<"1"<<"当前输入更改为:0"<<endl;
				if(i+1== n)//自动补零 
					c+='0';
				a=1;
				c[i]='0';
				cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
				cout<<endl; 
				return (f(a,c[++i]));
			}
		else
			{
				cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl; 
				//cout<<"输入的字符串错误!"<<endl;//异常输入的处理 
				return " ";
			}
	}
	else if(a== 1)
	{
		if(c1=='0')
		{
			cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"0"<<" "<<"1 R"<<endl;
			cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl; 
			cout<<"下一个内态为:"<<"0"<<"当前输入更改为:1"<<endl;	
				if(i+1== n)//自动补零 
					c+='0';
			a=0;
			c[i]='1';
			cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
			cout<<endl; 
			return(f(a,c[++i]));
		}
		else if(c1=='1')
		{
			cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"10"<<" "<<"0 R"<<endl;
			cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
			cout<<"下一个内态为:"<<"10"<<"当前输入更改为:0"<<endl;
				if(i+1== n)//自动补零 
					c+='0';
			a=10;
			c[i]='0';
			cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
			cout<<endl; 
			return (f(a,c[++i]));
		}
		else 
		{
			cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl; 
			//cout<<"输入字符串错误"<<endl;
			return " ";
		}
	}
	else if(a== 10)
	{
		if(c1=='0')
		{
			cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"11"<<" "<<"1 R"<<endl;
			cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
			cout<<"下一个内态为:"<<"11"<<"当前输入更改为:1"<<endl; 
				if(i+1== n)//自动补零 
					c+='0';
			a=11;
			c[i]='1';
			cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
			cout<<endl; 
			return (f(a,c[++i]));
		}
		else
		{
			cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl; 
			//cout<<"字符串错误!"<<endl;
			return " ";
		}
	}
	else if(a== 11)
	{
		if(c1=='0')
		{
			cout<<"步骤"<<i+1<<": 操作指令为:"<<a<<" "<<c1<<"->"<<"0"<<" "<<"1 STOP"<<endl;
			cout<<"当前内态为:"<<a<<";当前输入为:"<<"第"<<i+1<<"个位置,即"<<c1<<endl;
				if(i+1==n)//自动补零 
					c+='0';
			a=0;
			c[i]='1';
			cout<<"当前步骤"<<i+1<<"的结果为:"<<c<<endl;
			cout<<endl; 
			return c;
		}
		else
		{
			cout<<"当前内态为:"<<a<<";当前输入为:"<<c1<<endl; 
			//cout<<"字符串错误!"<<endl;
			return " ";
		}
		
	} 
}
string turn_to(string c)//转换二进制数为磁带上的编码 
{
	string a;
	a+='0';
	for(int i=0;i<c.length();i++)
	{
		if(c[i] == '0')
			a+= '0';
			
		else if(c[i] =='1')//1转换为10
		{
			a+='1';
			a+='0';
		}
		else if(c[i]=',')//"," 转化为110
		{
			a+='1';
			a+='1';
			a+='0';
		}
	}
	return a;
}
string turn(string c)//转换为二进制 
{
	string b;
	int i=0;
	while(i<c.length())//找到第一个1 
		{
			if(c[i]=='1')
				break;
			i++;
		}
		int t=i;
	while(t<c.length())
	{
		if(c[t]=='0')//遇到零 
		{
			t++;
			b+='0';
		}
		else//当前指向为1 
		{
			if(c[t+1]=='0')//遇到10两个字符
			{
				t+=2;//后移两个位置 
				b+='1';
			}
			
			else if(c[t+1]=='1')//遇到11两个字符,转换为,结束
				return b;
		}
		
	}
 
}
int to(string c)//二进制转换为十进制 
{
	int n=0,m=0;
	int t=0;
	int a=c.length()-1;
	while(a>=0)
	{
		n=c[a]-'0';//转化为对应的数字 
		m+=n*pow(2,t);
		t++;
		a--;
	}
	return m;
}
int isnum(string c)//判断是否为数字对应的字符串 
{
	float b=atof(c.c_str());//将输入的字符串转换为数字 
	if(b<=0||(b!=(int)b))//进行输入的数的异常处理 
	{
		cout<<"输入的数"<<"不是一个正整数!"<<endl;
		cout<<endl; 
		return 0;
	}
	else
		return 1;//返回1带代表输入的数正确
}
int main(void)
{
	string x;
	int t;
	int r;
	string w;
	char p[100];//用于存储进制转换后对应的字符 
	string m;
	cout<<"请输入要进行操作的数:"<<endl;
	cin>>x;
	if(isnum(x))
	{
		cout<<"输入错误!"<<endl;
		return 1;
	} 
	else
	{
		t=atoi(x.c_str());
		itoa(t,p,2);//十进制转换为二进制
		m=p; 
		m+=',';//末尾自动加,表示结束 
		cout<<"此数对应的二进位记号为:0"<<m; 
		cout<<endl; 
		c=turn_to(m);//转换为对应的磁带编码 
		cout<<"此数对应的磁带编码为:"<<c<<endl;
		cout<<endl; 
		int a=0;//内态初始值为0; 
		string b=f(a,c[0]);//得到转换之后的编码
		w=turn(b);//将此编码转换为二进制
		cout<<"最终结果对应的磁带编码为:"<<b<<endl;
		cout<<"最终结果对应的二进制位:"<<w<<endl;
		r=to(w); //将二进制转换为对应的整数
		cout<<"最终结果为:"<<r<<endl;
		return 0;
	}
	
 }

四. 调试与测试截图
(1)调试截图:

输入:

在这里插入图片描述

转换成二进位符号:

在这里插入图片描述

转换成磁带编码:

在这里插入图片描述

指令操作之后得到的结果对应的二进制:

在这里插入图片描述

得到的最后结果:
在这里插入图片描述

(2).测试截图:
错误输入测试:

在这里插入图片描述

测试数据3:

在这里插入图片描述

输入数据:12

在这里插入图片描述

五.经验归纳
图灵机的运行过程与两个重要的参数有关,一个是当前图灵机的内态,一个是当前的输入,对于不同的情况,有不同的指令操作。
在这次的实验中,将所有情况罗列出来,运行一条指令之后赋予相关的新的内态,以及新的输入,进行递归调用,进行下一个指令的操作,直到遇见停止的指令。

遇到的问题,在实现过程中,对于相应的转换函数,比如二进制到十进制的相互转换,此类函数运用的不是很熟练,出现了一些小错误,考虑到可以自己写进制转换的函数,于是在转换为二进制时自己写了一个进制转换函数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值