java实现图灵机模型(XN*2)

一、算法介绍

Java实现XN x 2该图灵机模型指令如下      (其中未加粗正体的是当前内态,斜体加粗为输入态,R代表右移,STOP代表停止)

 1. 0   ***0*** --> 0  ***0***,R
 2. 0  ***1***  --> 1  ***0***,R
 3. 1  ***0***  --> 0  ***1***,R
 4. 1  ***1***  --> 10  ***0***,R
 5. 10  ***0***  --> 11  ***1***,R
 6. 11  ***0***  -->  0  ***1***,STOP

二、算法分析

  1. 首先需要将需要进行XN2指令的数转换成二进制*
  2. 在将得到的二进制转换成二进制编码。例如二进制11,的二进制编码就是01010110
  3. 然后根据指令再依次进行操作
    此处上图演示
    此过程也是本文中程序的运行实例结果
    java实现图灵机模型(XN*2)java实现图灵机模型(XN*2)

三、代码实现

(代码实现笔者用了两个类实现,下面我将两个类分开列出)
注:代码实现的主要思路在代码中的注释可以详细揣摩
1、Solution,java:

import java.util.ArrayList;
import java.util.List;

/**
 * Produce: <br>
 * 类Solution是类Result的父类主要。该类中有各种指令的执行方法和<br>
 * 和界面的主要打印方法,以及这个项目的数据。且对数据进行了封装工作。<br>
 *  <br>
 * Detail: <br>
 * 方法public void processPrint(int input, int ergodicNum)是打印命令过程。<br>
 * 方法public void listPrint()是打印二进制编码。<br>
 * 方法public void instruct_1 (int input, int ergodicNum)是当内态为0的时候做指令。<br>
 * 方法public void instruct_2 (int input, int ergodicNum)是当内态为1的时候做指令。<br>
 * 方法public void instruct_3 (int input, int ergodicNum)是当内态为10的时候做指令。<br>
 * 方法public void instruct_4 (int input, int ergodicNum)适当内态为11的时候做指令。<br>
 * <br>
 * Date:2019年3月17日
 */

class Solution {
	private int internalStatus;    //当前的内态
	private String binaryCoding; //二进制编码
	List<Integer> list = new ArrayList<Integer>(); //用list作图灵机工作时的可变二进制编码
	
	public Solution() {
		// TODO 自动生成的构造函数存根
		internalStatus = 0;
		binaryCoding = "0";
	}
	

	//对private 字段生成的getter和settet方法
	public void setInternalStatus (int internalStatus) {
		this.internalStatus = internalStatus;
	}
	public int getInternalStatus() {
		return internalStatus;
	}
	
	public void setBinaryCoding(String binaryCoding) {
		this.binaryCoding = binaryCoding;
	}
	public String getBinaryCoding() {
		return binaryCoding;
	}
	

	/**
	 * 方法public void listPrint()是打印二进制编码。
	 */
	public void listPrint() {
		for(int i = 0; i < list.size(); i++) {
			System.out.print(list.get(i));
		}
		System.out.println();
	}
	

	/**
	 * 方法public void processPrint(int input, int ergodicNum)是打印命令过程。
	 * @param input 输入态
	 * @param ergodicNum 遍历次数
	 */
	public void processPrint(int input, int ergodicNum) {
		String string = "";//用于判断此处执行到哪个地方
		for(int i = 0; i < ergodicNum; i++) {
			string += " ";
		}
		string += "|";//标记执行处
		System.out.println(string);
		//输出内态和输入态
		System.out.print("此处内态为" + getInternalStatus());
		System.out.println(",输入态为" + input);
	}
	
	/**
	 * 方法public void instruct_1 (int input, int ergodicNum)是当内态为0的时候做指令。
	 * @param input 输入态
	 * @param ergodicNum 遍历次数
	 */
	public void instruct_1 (int input, int ergodicNum) {
		//参数ergodicNum是指遍历次数
		System.out.print("step" + (ergodicNum + 1) + ":");//打印步骤
		listPrint();//打印未经指令工作时的二进制编码
		System.out.print("      ");
		if(input < 0 || input > 1) {
			//判断指令以防出错
			System.out.println("输入态指令错误!");
			return ;//若出错直接跳出程序
		}
		//当内态为0,且输入态也为0,内态和输入态都不做变换
		if(input == 0) {
			processPrint(input,ergodicNum);//打印指令过程
			//打印经过指令后的内态和输入
			System.out.print("经过指令处理之后此处的内态为" + getInternalStatus());
			System.out.print(",输入态为" + list.get(ergodicNum));
			System.out.println(",R(右移)");
			System.out.print("处理后的结果为:");
			listPrint();//打印经过指令之后的二进制编码
		}
		//当内态为0,且输入态为1时
		if(input == 1) {
			processPrint(input, ergodicNum);
			setInternalStatus(1);//内态变为1
			list.set(ergodicNum, 0);//输入态变为0
			System.out.print("经过指令处理之后此处的内态为" + getInternalStatus());
			System.out.print(",输入态为" + list.get(ergodicNum));
			System.out.println(",R(右移)");
			System.out.print("处理后的结果为:");
			listPrint();
		}
		System.out.println();
		System.out.println();
	}
	

	/**
	 * 方法public void instruct_2 (int input, int ergodicNum)是当内态为1的时候做指令。
	 * @param input 输入态
	 * @param ergodicNum 遍历次数
	 */
	public void instruct_2 (int input, int ergodicNum) {
		//如方法instruct_1(int input, int ergodicNum)中的注释
		System.out.print("step" + (ergodicNum + 1) + ":");
		listPrint();
		if(input < 0 || input > 1) {
			//保护程序代码块
			System.out.println("输入态指令错误!");
			return ;
		}
		System.out.print("      ");
		//内态为1且输入态为0
		if(input == 0) {
			//过程打印如方法instruct_1(int input, int ergodicNum)注释
			processPrint(input, ergodicNum);
			setInternalStatus(0);//把内态置为0
			list.set(ergodicNum, 1);//输入态置为1
			//过程打印如方法instruct_1(int input, int ergodicNum)注释
			System.out.print("经过指令处理之后此处的内态为" + getInternalStatus());
			System.out.print(",输入态为" + list.get(ergodicNum));
			System.out.println(",R(右移)");
			System.out.print("处理后的结果为:");
			listPrint();
		}
		//内态为1且输入态为1
		if(input == 1) {
			//过程打印如方法instruct_1(int input, int ergodicNum)注释
			processPrint(input, ergodicNum);
			setInternalStatus(10);//把内态置为10
			list.set(ergodicNum, 0);//输入态置为0
			//过程打印如方法instruct_1(int input, int ergodicNum)注释
			System.out.print("经过指令处理之后此处的内态为" + getInternalStatus());
			System.out.print(",输入态为" + list.get(ergodicNum));
			System.out.println(",R(右移)");
			System.out.print("处理后的结果为:");
			listPrint();
		}
		System.out.println();
		System.out.println();
	}
	
/**
	 * 方法public void instruct_3 (int input, int ergodicNum)是当内态为10的时候做指令。
	 * @param input 输入态
	 * @param ergodicNum 遍历次数
	 */
	public void instruct_3 (int input, int ergodicNum) {
		//过程打印如方法instruct_1(int input, int ergodicNum)注释
		System.out.print("step" + (ergodicNum + 1) + ":");
		listPrint();
		System.out.print("      ");
		if(input != 0) {
			//代码保护块
			System.out.println("输入态指令错误!");
			return ;
		}
		//当内态为10且输入态为0
		if(input == 0) {
			//过程打印如方法instruct_1(int input, int ergodicNum)注释
			processPrint(input, ergodicNum);
			setInternalStatus(11);//内态置为11
			list.set(ergodicNum, 1);//输入态置为1
			//过程打印如方法instruct_1(int input, int ergodicNum)注释
			System.out.print("经过指令处理之后此处的内态为" + getInternalStatus());
			System.out.print(",输入态为" + list.get(ergodicNum));
			System.out.println(",R(右移)");
			System.out.print("处理后的结果为:");
			listPrint();
		}
		System.out.println();
		System.out.println();
	}
	

	/**
	 * 方法public void instruct_4 (int input, int ergodicNum)是当内态11的时候做指令。
	 * @param input 输入态
	 * @param ergodicNum 遍历次数
	 */
	public void instruct_4 (int input, int ergodicNum) {
		//打印如方法instruct_1(int input, int ergodicNum)注释
		System.out.print("step" + (ergodicNum + 1) + ":");
		listPrint();
		System.out.print("      ");
		if(input != 0) {
			//代码保护块
			System.out.println("输入指令错误");
			return ;
		}
		//当内态为11且输入态为0
		if(input == 0) {
			//过程打印如方法instruct_1(int input, int ergodicNum)注释
			processPrint(input, ergodicNum);
			setInternalStatus(0);//内态置为0
			list.set(ergodicNum, 1);//输入态置为1
			//过程打印如方法instruct_1(int input, int ergodicNum)注释
			System.out.print("经过指令处理之后此处的内态为" + getInternalStatus());
			System.out.print(",输入态为" + list.get(ergodicNum));
			System.out.println(",STOP");
			System.out.print("处理后的结果为:");
			//打印最终得到的为二进制编码
			for(int i = 0; i < list.size(); i++) {
				System.out.print(list.get(i));
			}
			System.out.print(0);
		}
		System.out.println();
		System.out.println();
		System.out.println();
	}
}

2、Result.java:

import java.util.*;

/**
 * Produce:<br>
 * 类Result继承类Solution,需要得到其封装的字段和方法。<br>
 * <br>
 * Detail:<br>
 * 方法public void obtainbinaryData ()是获得二进制编码<br>
 * 方法public String transformData ()是将十进制数转换成二进制编码<br>
 * 方法public void transformNum ()是将二进制编码转换成十进制数<br>
 * 方法public void obtainResult ()是进行指令操作获得结果<br>
 * 方法public static void main(String[] args)是程序入口
 * <br>
 * Date:2019年3月17日
 */

public class Result extends Solution {
	//输入
	Scanner scanner = new Scanner(System.in);
	
	/**
	 * 方法public void obtainbinaryData ()是获得二进制编码
	 */
	public void obtainbinaryData () {
		super.setBinaryCoding(transformData());//得到二进制编码
		//为可变二进制编码list赋值
		for(int i = 0; i < super.getBinaryCoding().length(); i++) {
			//当得到的该处值是数字即加一层保护
			if(super.getBinaryCoding().charAt(i) >= 48 && super.getBinaryCoding().charAt(i) <= 57) {
				//就用list.add()为super.list的末尾加一个值
				super.list.add(Integer.parseInt(super.getBinaryCoding().charAt(i)+""));
			} else {
				//保护代码块
				System.out.println("输入指令错误!");
			}
		}
		super.list.add(0);
	}
	
	/**
	 * 方法public String transformData ()是将十进制数转换成二进制编码
	 * @return binaryCode
	 */
	public String transformData () {
		System.out.println("请输入需要执行XN*2的数(十进制):");
		int data = 0;//需要执行XN*2的数(十进制)
		String binary = "";//需要执行XN*2的数(二进制)
		String binaryCode = "0";//二进制编码
		data = scanner.nextInt();//输入
		binary = Integer.toBinaryString(data);//转换成二进制
		binary += ",";//给二进制末尾加","确保结束
		System.out.println("得到的二进制数:" + binary);
		//二进制转换成二进制编码
		for(int i = 0; i < binary.length(); i++) {
			//如果该处为0就给编码加一个0,确保得到的数00
			if(binary.charAt(i) == '0'){
				binaryCode += "0";
			} else if(binary.charAt(i) == '1') {
				//如果为1就给编码加10,确保得到的是010
				binaryCode += "10";
			} else {
				//不是1也不是0那就是",",就给末尾加110,确保为0110
				binaryCode += "110";
			}
		}
		System.out.println("得到的二进制编码:" + binaryCode);
		return binaryCode;
	}

	/**
	 * 方法public void transformNum ()是将二进制编码转换成十进制数
	 */
	public void transformNum () {
		String tempString = "";
		String binaryString = "";
		//把最终的二进制编码赋给字符串tempString
		for(int i = 0; i < super.list.size(); i++) {
			tempString += super.list.get(i);
		}
		//进行转换
		for(int i = 0; i < tempString.length(); i++) {
			//该处为0
			if(tempString.charAt(i) == '0') {
				//判断下一位置
				if(tempString.charAt(i + 1) == '1') {
					//下一位值是1且下一位置的下一位置也是1,则表明遇见了0110
					if(tempString.charAt(i + 2) == '1') {
						break;//就break掉完成转换
					} else {
						//此处代表下一位值是1且下一位置的下一位置是0,则表明遇见了010
						binaryString += 1;//就给二进制字符串压进一个1
					}
				} else {
					//此处代表该位置为0且下一位置也为0
					binaryString += 0;//就给二进制字符串压进一个0
				}
			} else {
				//保护代码块
				if(tempString.charAt(i + 1) == '0') {
					continue;
				} else {
					break;
				}
			}
		}
		System.out.println("得到的二进制结果为:" + binaryString);
		System.out.println("得到的十进制结果为:" + Integer.parseInt(binaryString, 2));
	}
	
	/**
	 * 方法public void obtainResult ()是进行指令操作获得结果
	 */
	public void obtainResult () {
		obtainbinaryData();//方法嵌套
		//进行命令执行,遍历
		for(int i = 0; i < super.list.size(); i++) {
			//switch当前状态
			switch (super.getInternalStatus()) {
				//为0,则进入内态为0的方法
			case 0:
				super.instruct_1(super.list.get(i), i);
				break;
				//为1,则进入内态为1的方法
			case 1:
				super.instruct_2(super.list.get(i), i);
				break;
				//为10,则进入内态为10的方法
			case 10:
				super.instruct_3(super.list.get(i), i);
				break;
				//为11,则进入内态为11的方法
			case 11:
				super.instruct_4(super.list.get(i), i);
				break;
			default:
				break;
			}
		}
		transformNum();//翻译得到的值
	}
	
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Result result = new Result();
		result.obtainResult();
	}

}

四、总结

在实现图灵机模型(XN x 2)这个题目中笔者最先想到的是使用线性表解决,其主要原因在与线性表的增删改查的实现比较容易,所以笔者采用这种方法。哈哈哈,毕竟可以复习数据结构嘛。。。。当然了条条大路通罗马,或许各位同胞会有更加简单的方法或者本文有不足的地方,希望评论指出。