低阶魔方自动复原

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

目录

一,二阶魔方

二,网页程序统一模型

1,配色

2,视角

3,旋转操作

4,整体旋转操作

5,编码

三,校验程序

1,统一模型

2,完整代码

3,使用方法

四,二阶魔方手动复原

五,三阶魔方

1,网页版程序

2,打乱校验

3,录入公式

4,手动复原

5,自动复原

6,操作序列化简

六,操作集扩充

七,四阶魔方

1,网页版程序

2,交换2个棱块

3,U位R位棱组交叉

4,自动复原

八,Bug修复

九,五阶魔方

1,网页版程序

2,自动复原V1

3,自动还原V2

4,case覆盖


一,二阶魔方

参考二阶魔方网页版

二,网页程序统一模型

因为网页版完全是AI生成的,我没有参与编码,只做了微调,所以本质上是AI完成的建模。

但是还是有必要自己建模,核对细节。

1,配色

按照标准配色,上白下黄左绿右蓝前红后橙,分别对应字母WYGBRO

2,视角

采用固定视角,不支持任意角度旋转。

正方体显示了上面、前面、右面,镜子显示了下面的一部分。

3,旋转操作

6个面 上下左右前后 对应 UDLRFB

6个顺时针操作即 UDLRFB

6个逆时针操作即U'D'L'R'F'B'

4,整体旋转操作

x y z分别表示右面、前面、上面视角的顺时针旋转。

x' y' z'分别表示对应的逆时针旋转。

5,编码

三,校验程序

1,统一模型

6个面的编码:按照上下左右前后的顺序,依次组成代码中的vector<vector<vector<char>>> cube,每个面都是一个正方形的二维数组。

2,完整代码

#include <iostream>
#include <string_view>
#include <string>
#include <string.h>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <array>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <iomanip>
#include <cmath>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
#include <thread>
using namespace std;

class SingleVectorOpt
{
public:
	//翻转vector、翻转二维vector的每一行
	template<typename T>
	static vector<T> frev(const vector<T>& v)
	{
		vector<T> ans;
		ans.resize(v.size());
		for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
		return ans;
	}
	template<typename T>
	static vector<vector<T>> frev(const vector<vector<T>>& v)
	{
		vector<vector<T>>ans;
		for (int i = 0; i < v.size(); i++)ans.push_back(frev(v[i]));
		return ans;
	}
	//沿主对角线(左上角到右下角)翻转二维vector
	template<typename T>
	static vector<vector<T>> foverturn(const vector<vector<T>>& v)
	{
		vector<vector<T>> ans(v[0].size());
		for (int i = 0; i < v[0].size(); i++) {
			ans[i].resize(v.size());
			for (int j = 0; j < v.size(); j++)ans[i][j] = v[j][i];
		}
		return ans;
	}
	//顺时针旋转二维vector
	template<typename T>
	static vector<vector<T>> frotation(const vector<vector<T>>& v)
	{
		return frev(foverturn(v));
	}
	//从vector(一维或2维)中删除所有的x
	template<typename T>
	static void deletAllX(vector<T>& v, T x)
	{
		for (int i = 0; i < v.size(); i++)if (v[i] == x)v.erase(v.begin() + i--);
	}
	template<typename T>
	static void deletAllX(vector<vector<T>>& v, T x)
	{
		for (auto& vi : v)deletAllX(vi, x);
	}
	// 去掉相邻重复元素
	template<typename T>
	static void deleteNeiborSame(vector<T>& v)
	{
		v.erase(std::unique(v.begin(), v.end()), v.end());
	}
	//判断数组去掉相邻重复数之后有多少个不同的数
	template<typename T>
	static int getDifNum(const vector<T>& v)
	{
		auto v2 = v;
		deleteNeiborSame(v2);
		return v2.size();
	}
	//vector乘一个数
	template<typename T1, typename T2>
	static void fcheng(vector<T1>& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] *= n;
	}
	//vector加一个数
	template<typename T1, typename T2>
	static void fjia(vector<T1>& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
	}
	//二维数组每一行排序
	template<typename T>
	static void sortEveryLine(vector<vector<T>>& v)
	{
		for (int i = 0; i < v.size(); i++)sort(v[i].begin(), v[i].end());
	}
	//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
	template<typename T, class P>
	static inline vector<int>firstInLeft(vector<T>v, P pr)
	{
		vector<int> ans;
		if (v.size() == 0)return ans;
		stack<T>st;
		st.push(0);
		ans.push_back(-1);
		for (int i = 1; i < v.size(); i++) //代码用单调栈实现,时间复杂度为O(n)
		{
			while (!st.empty() && !pr(v[st.top()], v[i]))st.pop();
			if (st.empty())ans.push_back(-1);
			else ans.push_back(st.top());
			st.push(i);
		}
		return ans;
	}

	//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fminlef(vector<T> v)
	{
		return firstInLeft(v, [](T a, T b) {return a < b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fminlef2(vector<T> v)
	{
		return firstInLeft(v, [](T a, T b) {return a <= b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fmaxlef(vector<T> v)
	{
		fcheng(v, -1);
		vector<int>ans = fminlef(v);
		return ans;
	}
	//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fmaxlef2(vector<T> v)
	{
		fcheng(v, -1);
		vector<int>ans = fminlef2(v);
		return ans;
	}

	//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fminrig(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fminlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fminrig2(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fminlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fmaxrig(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fmaxlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fmaxrig2(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fmaxlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	// v中都是非负数,对于v的任意一段[low,high],求满足[low,id]总和大于等于[low,high]总和的一半的最小id
	static map<int, map<int, int>> splitAtHalf(vector<int>& v)
	{
		vector<int>s;
		int n = 0;
		s.push_back(n);
		for (auto x : v) {
			n += x;
			s.push_back(n);
		}
		map<int, map<int, int>>ans;
		for (int i = 0; i < v.size(); i++) {
			int id = i;
			for (int j = i; j < v.size(); j++) {
				while (s[id + 1] - s[i] < s[j + 1] - s[id + 1])id++;
				ans[i][j] = id;
			}
		}
		return ans;
	}
	//获取所有的众数
	template<typename T>
	static vector<T> getMost(const vector<T>& v)
	{
		int n = 0;
		map<T, int>m;
		for (auto x : v)n = max(n, ++m[x]);
		vector<T>ans;
		for (auto p : m)if (p.second == n)ans.push_back(p.first);
		return ans;
	}
};


#define Frotation SingleVectorOpt::frotation//顺时针旋转二维vector
#define Frev SingleVectorOpt::frev//翻转vector、翻转二维vector的每一行

int N;

vector<vector<vector<char>>> Init()
{
	vector<vector<vector<char>>> ans;
	for (auto c : { 'W','Y','G','B','R','O' }) //上下左右前后
	{
		vector<char> temp(N, c);
		vector<vector<char>>v(N, temp);
		ans.push_back(v);
	}
	return ans;
}

void show(vector<vector<vector<char>>>& cube)
{
	cout << endl << "U: ";
	for (auto v : cube[0])for (auto ch : v)cout << ch;
	cout << endl << "D: ";
	for (auto v : cube[1])for (auto ch : v)cout << ch;
	cout << endl << "L: ";
	for (auto v : cube[2])for (auto ch : v)cout << ch;
	cout << endl << "R: ";
	for (auto v : cube[3])for (auto ch : v)cout << ch;
	cout << endl << "F: ";
	for (auto v : cube[4])for (auto ch : v)cout << ch;
	cout << endl << "B: ";
	for (auto v : cube[5])for (auto ch : v)cout << ch;
	cout << endl;
}

void rotate(vector<vector<vector<char>>>& cube, string c)
{
	if (c[1] == '\'') {
		string c2;
		c2 += c[0];
		rotate(cube, c2);
		rotate(cube, c2);
		rotate(cube, c2);
		return;
	}
	if (c == "U")
	{
		cube[0] = Frotation(cube[0]);
		auto v = cube[2][0];
		cube[2][0] = cube[4][0], cube[4][0] = cube[3][0], cube[3][0] = cube[5][0], cube[5][0] = v;
		return;
	}
	if (c == "D") {
		rotate(cube, "x");
		rotate(cube, "x");
		rotate(cube, "U");
		rotate(cube, "x");
		rotate(cube, "x");
		return;
	}
	if (c == "R")
	{
		rotate(cube, "y'");
		rotate(cube, "U");
		rotate(cube, "y");
		return;
	}
	if (c == "L")
	{
		rotate(cube, "y");
		rotate(cube, "U");
		rotate(cube, "y'");
		return;
	}
	if (c == "F")
	{
		rotate(cube, "x");
		rotate(cube, "U");
		rotate(cube, "x'");
		return;
	}
	if (c == "B")
	{
		rotate(cube, "x'");
		rotate(cube, "U");
		rotate(cube, "x");
		return;
	}
	if (c == "x")
	{
		cube[3] = Frotation(cube[3]);
		cube[2] = Frotation(Frotation(Frotation(cube[2])));
		auto v = cube[0];
		cube[0] = cube[4];
		cube[4] = Frev<vector<char>>(cube[1]);  //上下翻转
		cube[1] = Frev<char>(cube[5]); //翻转每一行
		cube[5] = Frev<char>(Frev<vector<char>>(v));
		return;
	}
	if (c == "z") {
		cube[0] = Frotation(cube[0]);
		cube[1] = Frotation(cube[1]);
		auto v = cube[2];
		cube[2] = cube[4], cube[4] = cube[3], cube[3] = cube[5], cube[5] = v;
		return;
	}
	if (c == "y") {
		rotate(cube, "z");
		rotate(cube, "z");
		rotate(cube, "z");
		rotate(cube, "x");
		rotate(cube, "z");
		return;
	}
}

void test1() //输入所有操作,只显示最终结果
{
	vector<string>opts;
	string c;
	while (cin >> c)opts.push_back(c);
	auto cube = Init();
	for (auto c : opts) {
		rotate(cube, c);
	}
	show(cube);
}

void test2() //每次输入1个操作,实时显示结果
{
	auto cube = Init();
	string c;
	while (cin >> c) {
		rotate(cube, c);
		show(cube);
		cout << endl;
	}
}

int main()
{
	N = 2;
	test1();
	return 0;
}

3,使用方法

任意时刻,只需要把完整序列一次性输入进去,即可得到当前局面。

例如:

输出的当前局面直接和html的当前局面对比,所有字符一模一样则校验通过。

这就完成了证明:AI输出的html程序、我纯手写的校验程序已经没有BUG了,且相关的所有模型都保持了一致。

四,二阶魔方手动复原

就用上面的这个打乱序列,手动复原之后得到操作序列:

F' D R U' L' F' L D' U' B U' L B' R' F R' D' B R B D' L' B L' D R z z R' z D z B R B' z' F D' B' L' B L' F' L y y z z F U F' U F U U F' z z z z U z z z z R R F F R' B' R R R' F F R R R B R' z z z z' z z z R R F F R' B' R F F R' B R'

校验:

校验通过。

五,三阶魔方

1,网页版程序

参考三阶魔方网页版

2,打乱校验

int main()
{
	N = 3;
	test1();
	return 0;
}

校验通过。

PS:需不需要check当前局面和显示的魔方是否对应?不需要,二阶魔方check过,后面所有魔方都不需要了,因为我们的最终目的是探索怎么样生成一个操作序列来复原魔方,而最终得到的操作序列是否真的能复原,只需要使用校验程序即可,和界面显示无关。

3,录入公式

录入9个公式

// 白色角块1 y' F R' F' y D D y' F R F' y 
// 白色角块2 y' F R F' y
// 白色角块3 R' D' R
// 中层棱块1 U' L' U L U F U' F'
// 中层棱块2 U R U' R' U' F' U F
// 顶层十字 F R U R' U' F'
// 小鱼1 R' U' R U' R' U U R
// 小鱼2 F U F' U F U U F'
// 换角 R R F F R' B' R F F R' B R'

4,手动复原

【完整操作序列】
F' U B U L R' L B' U' B' D' F L F' B U' R F' U' L' F' L' U B L' F' U R U F' U' z z U U F' U z z U U R z y' F R F' y U y' F R' F' y D D y' F R F' y z z' z D y' F R F' y z y' F R F' y D' y' F R F' y U U y y z U' z U R U' R' U' F' U F z z U' L' U L U F U' F' U' z U' L' U L U F U' F' z U U z' U R U' R' U' F' U F z z z z F U F' U F U U F' z R R F F R' B' R F F R' B R' U' z R' U' R U' R' U U R z z F U F' U F U U F'

校验:

校验通过。

到这一步,也顺便验证了这9个公式的正确性,可以用于自动复原了。

5,自动复原

#include <iostream>
#include <string_view>
#include <string>
#include <string.h>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <array>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <iomanip>
#include <cmath>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
#include <thread>
#include <filesystem>

using namespace std;
namespace fs = std::filesystem;

class SingleVectorOpt
{
public:
	//翻转vector、翻转二维vector的每一行
	template<typename T>
	static vector<T> frev(const vector<T>& v)
	{
		vector<T> ans;
		ans.resize(v.size());
		for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
		return ans;
	}
	template<typename T>
	static vector<vector<T>> frev(const vector<vector<T>>& v)
	{
		vector<vector<T>>ans;
		for (int i = 0; i < v.size(); i++)ans.push_back(frev(v[i]));
		return ans;
	}
	//沿主对角线(左上角到右下角)翻转二维vector
	template<typename T>
	static vector<vector<T>> foverturn(const vector<vector<T>>& v)
	{
		vector<vector<T>> ans(v[0].size());
		for (int i = 0; i < v[0].size(); i++) {
			ans[i].resize(v.size());
			for (int j = 0; j < v.size(); j++)ans[i][j] = v[j][i];
		}
		return ans;
	}
	//顺时针旋转二维vector
	template<typename T>
	static vector<vector<T>> frotation(const vector<vector<T>>& v)
	{
		return frev(foverturn(v));
	}
	//从vector(一维或2维)中删除所有的x
	template<typename T>
	static void deletAllX(vector<T>& v, T x)
	{
		for (int i = 0; i < v.size(); i++)if (v[i] == x)v.erase(v.begin() + i--);
	}
	template<typename T>
	static void deletAllX(vector<vector<T>>& v, T x)
	{
		for (auto& vi : v)deletAllX(vi, x);
	}
	// 去掉相邻重复元素
	template<typename T>
	static void deleteNeiborSame(vector<T>& v)
	{
		v.erase(std::unique(v.begin(), v.end()), v.end());
	}
	//判断数组去掉相邻重复数之后有多少个不同的数
	template<typename T>
	static int getDifNum(const vector<T>& v)
	{
		auto v2 = v;
		deleteNeiborSame(v2);
		return v2.size();
	}
	//vector乘一个数
	template<typename T1, typename T2>
	static void fcheng(vector<T1>& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] *= n;
	}
	//vector加一个数
	template<typename T1, typename T2>
	static void fjia(vector<T1>& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
	}
	//二维数组每一行排序
	template<typename T>
	static void sortEveryLine(vector<vector<T>>& v)
	{
		for (int i = 0; i < v.size(); i++)sort(v[i].begin(), v[i].end());
	}
	//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
	template<typename T, class P>
	static inline vector<int>firstInLeft(vector<T>v, P pr)
	{
		vector<int> ans;
		if (v.size() == 0)return ans;
		stack<T>st;
		st.push(0);
		ans.push_back(-1);
		for (int i = 1; i < v.size(); i++) //代码用单调栈实现,时间复杂度为O(n)
		{
			while (!st.empty() && !pr(v[st.top()], v[i]))st.pop();
			if (st.empty())ans.push_back(-1);
			else ans.push_back(st.top());
			st.push(i);
		}
		return ans;
	}

	//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fminlef(vector<T> v)
	{
		return firstInLeft(v, [](T a, T b) {return a < b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fminlef2(vector<T> v)
	{
		return firstInLeft(v, [](T a, T b) {return a <= b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fmaxlef(vector<T> v)
	{
		fcheng(v, -1);
		vector<int>ans = fminlef(v);
		return ans;
	}
	//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fmaxlef2(vector<T> v)
	{
		fcheng(v, -1);
		vector<int>ans = fminlef2(v);
		return ans;
	}

	//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fminrig(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fminlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fminrig2(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fminlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fmaxrig(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fmaxlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fmaxrig2(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fmaxlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	// v中都是非负数,对于v的任意一段[low,high],求满足[low,id]总和大于等于[low,high]总和的一半的最小id
	static map<int, map<int, int>> splitAtHalf(vector<int>& v)
	{
		vector<int>s;
		int n = 0;
		s.push_back(n);
		for (auto x : v) {
			n += x;
			s.push_back(n);
		}
		map<int, map<int, int>>ans;
		for (int i = 0; i < v.size(); i++) {
			int id = i;
			for (int j = i; j < v.size(); j++) {
				while (s[id + 1] - s[i] < s[j + 1] - s[id + 1])id++;
				ans[i][j] = id;
			}
		}
		return ans;
	}
	//获取所有的众数
	template<typename T>
	static vector<T> getMost(const vector<T>& v)
	{
		int n = 0;
		map<T, int>m;
		for (auto x : v)n = max(n, ++m[x]);
		vector<T>ans;
		for (auto p : m)if (p.second == n)ans.push_back(p.first);
		return ans;
	}
};


#define Frotation SingleVectorOpt::frotation//顺时针旋转二维vector
#define Frev SingleVectorOpt::frev//翻转vector、翻转二维vector的每一行

int N;

vector<vector<vector<char>>> Init()
{
	vector<vector<vector<char>>> ans;
	for (auto c : { 'W','Y','G','B','R','O' }) //上下左右前后
	{
		vector<char> temp(N, c);
		vector<vector<char>>v(N, temp);
		ans.push_back(v);
	}
	return ans;
}

void show(vector<vector<vector<char>>>& cube)
{
	cout << endl << "U: ";
	for (auto v : cube[0])for (auto ch : v)cout << ch;
	cout << endl << "D: ";
	for (auto v : cube[1])for (auto ch : v)cout << ch;
	cout << endl << "L: ";
	for (auto v : cube[2])for (auto ch : v)cout << ch;
	cout << endl << "R: ";
	for (auto v : cube[3])for (auto ch : v)cout << ch;
	cout << endl << "F: ";
	for (auto v : cube[4])for (auto ch : v)cout << ch;
	cout << endl << "B: ";
	for (auto v : cube[5])for (auto ch : v)cout << ch;
	cout << endl;
}

void rotate(vector<vector<vector<char>>>& cube, string c)
{
	if (c[1] == '\'') {
		string c2;
		c2 += c[0];
		rotate(cube, c2);
		rotate(cube, c2);
		rotate(cube, c2);
		return;
	}
	if (c == "U")
	{
		cube[0] = Frotation(cube[0]);
		auto v = cube[2][0];
		cube[2][0] = cube[4][0], cube[4][0] = cube[3][0], cube[3][0] = cube[5][0], cube[5][0] = v;
		return;
	}
	if (c == "D") {
		rotate(cube, "x");
		rotate(cube, "x");
		rotate(cube, "U");
		rotate(cube, "x");
		rotate(cube, "x");
		return;
	}
	if (c == "R")
	{
		rotate(cube, "y'");
		rotate(cube, "U");
		rotate(cube, "y");
		return;
	}
	if (c == "L")
	{
		rotate(cube, "y");
		rotate(cube, "U");
		rotate(cube, "y'");
		return;
	}
	if (c == "F")
	{
		rotate(cube, "x");
		rotate(cube, "U");
		rotate(cube, "x'");
		return;
	}
	if (c == "B")
	{
		rotate(cube, "x'");
		rotate(cube, "U");
		rotate(cube, "x");
		return;
	}
	if (c == "x")
	{
		cube[3] = Frotation(cube[3]);
		cube[2] = Frotation(Frotation(Frotation(cube[2])));
		auto v = cube[0];
		cube[0] = cube[4];
		cube[4] = Frev<vector<char>>(cube[1]);  //上下翻转
		cube[1] = Frev<char>(cube[5]); //翻转每一行
		cube[5] = Frev<char>(Frev<vector<char>>(v));
		return;
	}
	if (c == "z") {
		cube[0] = Frotation(cube[0]);
		cube[1] = Frotation(cube[1]);
		auto v = cube[2];
		cube[2] = cube[4], cube[4] = cube[3], cube[3] = cube[5], cube[5] = v;
		return;
	}
	if (c == "y") {
		rotate(cube, "z");
		rotate(cube, "z");
		rotate(cube, "z");
		rotate(cube, "x");
		rotate(cube, "z");
		return;
	}
}

void test1() //输入所有操作,只显示最终结果
{
	vector<string>opts;
	string c;
	while (cin >> c)opts.push_back(c);
	auto cube = Init();
	for (auto c : opts) {
		rotate(cube, c);
	}
	show(cube);
}

void test2() //每次输入1个操作,实时显示结果
{
	auto cube = Init();
	string c;
	while (cin >> c) {
		rotate(cube, c);
		show(cube);
		cout << endl;
	}
}

#define AnsAdd(s) ans += s;ans += " "; rotate(cube, s);
#define F1 AnsAdd("y'");AnsAdd("F");AnsAdd("R'");AnsAdd("F'");AnsAdd("y");AnsAdd("D");AnsAdd("D");AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块1 y' F R' F' y D D y' F R F' y
#define F2 AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块2 y' F R F' y
#define F3 AnsAdd("R'");AnsAdd("D");AnsAdd("R");// 白色角块3 R' D' R
#define F4 AnsAdd("U'");AnsAdd("L'");AnsAdd("U");AnsAdd("L");AnsAdd("U");AnsAdd("F");AnsAdd("U'");AnsAdd("F'");// 中层棱块1 U' L' U L U F U' F'
#define F5 AnsAdd("U");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");AnsAdd("U");AnsAdd("F");// 中层棱块2 U R U' R' U' F' U F
#define F6 AnsAdd("F");AnsAdd("R");AnsAdd("U");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");// 顶层十字 F R U R' U' F'
#define F7 AnsAdd("R'");AnsAdd("U'");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U");AnsAdd("U");AnsAdd("R");      // 小鱼1 R' U' R U' R' U U R
#define F8 AnsAdd("F");AnsAdd("U");AnsAdd("F'");AnsAdd("U");AnsAdd("F");AnsAdd("U");AnsAdd("U");AnsAdd("F'"); // 小鱼2 F U F' U F U U F'
#define F9 AnsAdd("R");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B'");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B");AnsAdd("R'"); // 换角 R R F F R' B' R F F R' B R'

bool checkAllCenter(const vector<vector<vector<char>>>& cube)
{
	for (int i = 0; i < 6; i++) {
		char centerColor = cube[i][N / 2][N / 2];
		for (int j = 1; j < N - 1; j++) {
			for (int k = 1; k < N - 1; k++) {
				if (cube[i][j][k] != centerColor) {
					return false;
				}
			}
		}
	}
	return true;
}
string makeAllCenter(vector<vector<vector<char>>>& cube)
{
	if (checkAllCenter(cube))return "";
	return "z";  //// 待更新
}

bool checkDir(const vector<vector<vector<char>>>& cube)
{
	if (cube[0][1][1] != 'W')return false;
	if (cube[2][1][1] != 'G')return false;
	return true;
}

string makeDir(vector<vector<vector<char>>>& cube)
{
	string ans;
	if (cube[1][1][1] == 'W') {
		AnsAdd("x");
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[4][1][1] == 'W')break;
	}
	if (cube[0][1][1] != 'W') {
		AnsAdd("x");
	}
	return ans;
}

bool checkAllEdge(const vector<vector<vector<char>>>& cube)
{
	for (int i = 0; i < 6; i++) {
		for (int j = 1; j < N - 1; j++) {
			if (cube[i][0][j] != cube[i][0][1] || cube[i][N - 1][j] != cube[i][N - 1][1] || cube[i][j][0] != cube[i][1][0] || cube[i][j][N - 1] != cube[i][1][N - 1]) {
				return false;
			}
		}
	}
	return true;
}

string makeAllEdge(const vector<vector<vector<char>>>& cube)
{
	if (checkAllEdge(cube))return "";
	return "z";  //// 待更新
}

string makeUUUU(vector<vector<vector<char>>>& cube) //白色层方向回正
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][N - 1][1] == 'W' && cube[4][0][1] == 'R') {
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][1][N - 1] == 'W' && cube[3][0][1] == 'B') {
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][1][0] == 'W' && cube[2][0][1] == 'G') {
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][0][1] == 'W' && cube[5][0][1] == 'O') {
			return ans;
		}
	}
	return ans;
}

bool checkWhiteCross(const vector<vector<vector<char>>>& cube)// 检查白色十字是否完成
{
	char whiteColor = 'W';
	if (cube[0][0][1] != whiteColor || cube[0][N - 1][1] != whiteColor || cube[0][1][0] != whiteColor || cube[0][1][N - 1] != whiteColor) {
		return false;
	}
	if (cube[2][0][1] != 'G' || cube[3][0][1] != 'B' || cube[4][0][1] != 'R') {
		return false;
	}
	return true;
}
string makeWhiteCrossOnce(vector<vector<vector<char>>>& cube)
{
	string ans = "";
	for (int i = 0; i < 4; i++) {
		AnsAdd("D");
		if (cube[4][N - 1][1] == 'W') {
			ans += makeUUUU(cube);
			char c = cube[1][N - 1][1];
			if (c == 'B') {
				AnsAdd("U");
			}
			if (c == 'O') {
				AnsAdd("U");
				AnsAdd("U");
			}
			if (c == 'G') {
				AnsAdd("U'");
			}
			AnsAdd("F'");
			AnsAdd("U'");
			AnsAdd("R");
			return ans;
		}
		if (cube[1][N - 1][1] == 'W') {
			ans += makeUUUU(cube);
			char c = cube[4][N - 1][1];
			if (c == 'B') {
				AnsAdd("U");
			}
			if (c == 'O') {
				AnsAdd("U");
				AnsAdd("U");
			}
			if (c == 'G') {
				AnsAdd("U'");
			}
			AnsAdd("F");
			AnsAdd("F");
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[4][1][N - 1] == 'W' || cube[3][1][0] == 'W') {
			while (cube[0][N - 1][1] == 'W') {
				AnsAdd("U");
			}
			AnsAdd("F");
			return ans;
		}
	}
	ans += makeUUUU(cube);
	string s = "BOGR";
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[0][N - 1][1] != 'W' || cube[4][0][1] != s[i]) {
			AnsAdd("F");
			AnsAdd("F");
			return ans;
		}
	}
	return ans;
}
string makeWhiteCross(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (true) {
		ans += makeDir(cube);
		ans += makeUUUU(cube);
		if (checkWhiteCross(cube))break;
		ans += makeWhiteCrossOnce(cube);
	}
	return ans;
}

bool checkWhite(const vector<vector<vector<char>>>& cube)// 检查白色是否完成
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][0][0] != cube[i][0][1] || cube[i][0][N - 1] != cube[i][0][1])return false;
	}
	return true;
}
string makeWhiteOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("D");
		ans += makeUUUU(cube);
		string t;
		t += cube[1][N - 1][N - 1];
		t += cube[3][N - 1][0];
		t += cube[4][N - 1][N - 1];
		sort(t.begin(), t.end());
		if (t == "BOW") {
			AnsAdd("U");
		}
		if (t == "GOW") {
			AnsAdd("U");
			AnsAdd("U");
		}
		if (t == "GRW") {
			AnsAdd("U");
			AnsAdd("U");
			AnsAdd("U");
		}
		if (cube[1][N - 1][N - 1] == 'W') {
			F1;
			return ans;
		}
		if (cube[4][N - 1][N - 1] == 'W') {
			F2;
			return ans;
		}
		if (cube[3][N - 1][0] == 'W') {
			F3;
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[4][0][N - 1] != cube[4][0][1] || cube[3][0][0] != cube[3][0][1]) {
			F2;
			return ans;
		}
	}
	return ans;
}
string makeWhite(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (true) {
		ans += makeDir(cube);
		if (checkWhite(cube))break;
		ans += makeWhiteOnce(cube);
	}
	return ans;
}

bool checkMid(const vector<vector<vector<char>>>& cube)
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][1][0] != cube[i][1][1] || cube[i][1][N - 1] != cube[i][1][1])return false;
	}
	return true;
}
string makeMidOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		string t;
		t += cube[0][N - 1][1];
		t += cube[4][0][1];
		if (t[0] != 'Y' && t[1] != 'Y') {
			while (cube[4][0][1] != cube[4][1][1]) {
				AnsAdd("z");
				AnsAdd("U'");
			}
			if (t == "BR" || t == "RG" || t == "GO" || t == "OB") {
				F4;
			}
			else {
				F5;
			}
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[4][1][0] != cube[4][1][1]) {
			F4;
		}
		else if (cube[4][1][N - 1] != cube[4][1][1]) {
			F5;
		}
	}
	return ans;
}
string makeMid(vector<vector<vector<char>>>& cube)
{
	string ans = makeDir(cube) + " ";
	ans += makeUUUU(cube);
	AnsAdd("y");
	AnsAdd("y");
	//从此,白色在下面,不能再调用makeDir和makeUUUU!!!!
	while (true) {
		if (checkMid(cube))break;
		ans += makeMidOnce(cube);
	}
	return ans;
}

bool checkTopCross(const vector<vector<vector<char>>>& cube)
{
	int num = 0;
	if (cube[0][0][1] == 'Y')num++;
	if (cube[0][N - 1][1] == 'Y')num++;
	if (cube[0][1][0] == 'Y')num++;
	if (cube[0][1][N - 1] == 'Y')num++;
	return num == 4;
}
string makeTopCrossOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	int num = 0;
	if (cube[0][0][1] == 'Y')num++;
	if (cube[0][N - 1][1] == 'Y')num++;
	if (cube[0][1][0] == 'Y')num++;
	if (cube[0][1][N - 1] == 'Y')num++;
	if (num == 2) {
		while (cube[0][1][0] != 'Y') {
			AnsAdd("U");
		}
		if(cube[0][N-1][1] == 'Y') {
			AnsAdd("U");
		}
	}
	F6;
	return ans;
}
string makeTopCross(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCross(cube)) {
		ans += makeTopCrossOnce(cube);
	}
	return ans;
}

bool checkTopDir(const vector<vector<vector<char>>>& cube)
{
	int num = 0;
	if (cube[0][0][0] == 'Y') num++;
	if (cube[0][0][N - 1] == 'Y') num++;
	if (cube[0][N - 1][0] == 'Y') num++;
	if (cube[0][N - 1][N - 1] == 'Y') num++;
	return num == 4;
}

string makeTopDirOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	int num = 0;
	if(cube[0][0][0] == 'Y') num++;
	if(cube[0][0][N - 1] == 'Y') num++;
	if(cube[0][N - 1][0] == 'Y') num++;
	if(cube[0][N - 1][N - 1] == 'Y') num++;
	if (num == 0) {
		while (cube[2][0][0] != 'Y') {
			AnsAdd("U");
		}
		F7;
		return ans;
	}
	if (num == 2) {
		while (cube[5][0][N-1] != 'Y') {
			AnsAdd("U");
		}
		F7;
		return ans;
	}
	while (cube[0][0][0] != 'Y') {
		AnsAdd("U");
	}
	if (cube[4][0][0] == 'Y') {
		F7;
		return ans;
	}
	F8;
	return ans;
}
string makeTopDir(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopDir(cube)) {
		ans += makeTopDirOnce(cube);
	}
	return ans;
}

bool checkTopCornerLoc(const vector<vector<vector<char>>>& cube)
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][0][0] != cube[i][0][N-1])return false;
	}
	return true;
}

string makeTopCornerLocOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[3][0][0] == cube[3][0][N - 1])break;
	}
	F9;
	return ans;
}
string makeTopCornerLoc(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCornerLoc(cube)) {
		ans += makeTopCornerLocOnce(cube);
	}
	return ans;
}

bool checkTopEdgeLoc(const vector<vector<vector<char>>>& cube)
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][0][0] != cube[i][0][1])return false;
	}
	return true;
}
string makeTopEdgeLocOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[4][0][0] == cube[4][0][1])break;
	}
	F7;
	AnsAdd("z");
	AnsAdd("z");
	F8;
	return ans;
}
string makeTopEdgeLoc(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopEdgeLoc(cube)) {
		ans += makeTopEdgeLocOnce(cube);
	}
	return ans;
}

string makeAll(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (cube[4][0][0] != cube[4][1][0]) {
		AnsAdd("U");
	}
	while (cube[4][N-1][0] != cube[4][1][0]) {
		AnsAdd("D");
	}
	return ans;
}

string autoRunOpts(vector<vector<vector<char>>>& cube)
{
	string ans = makeAllCenter(cube) ; //中心大正方形合并
	ans += makeDir(cube); //朝向
	ans += makeAllEdge(cube) ; //棱块合并
	ans += makeWhiteCross(cube) ; //白色十字
	ans += makeWhite(cube) ;//白色
	ans += makeMid(cube) ;//中间层
	ans += makeTopCross(cube);//顶层十字
	ans += makeTopDir(cube) ;//顶层朝向
	ans += makeTopCornerLoc(cube);	//角块归位
	ans += makeTopEdgeLoc(cube);//棱块归位
	ans += makeAll(cube);//复原
	return ans;
}

void atuoRun(vector<string>& lines)
{
	vector<vector<vector<char>>>cube;
	for (int i = 0; i < 6; i++) {
		string s = lines[i].substr(3, lines[i].length() - 3);
		vector<vector<char>>v(N, vector<char>(N));
		for (int i = 0; i < N; i++)for (int j = 0; j < N; j++)v[i][j] = s[i * N + j];
		cube.push_back(v);
	}
	string ans = autoRunOpts(cube);
	std::ofstream outFile("D:/cubeOutput.txt", std::ios::app);
	if (outFile.is_open()) {
		outFile << ans << "\n";
		outFile.close();
	}
}

// 读取文件的所有行,每一行存入一个 string
std::vector<std::string> readAllLines(const std::string& path) {
	std::vector<std::string> lines;
	std::ifstream in(path);
	if (!in.is_open()) {
		return lines;  // 打开失败,返回空
	}

	std::string line;
	while (std::getline(in, line)) {
		lines.push_back(line);   // 每行一个 string 对象
	}
	return lines;
}

// 判断文件内容是否不为空
bool fileHasContent(const std::string& path) {
	std::error_code ec;

	// 1. 文件必须存在
	if (!fs::exists(path, ec) || ec) {
		return false;
	}

	// 2. 文件大小必须大于 0
	if (fs::file_size(path, ec) == 0 || ec) {
		return false;
	}

	return true;
}

void run1() // 自动填写操作序列
{
	const std::string filePath = "D:/cubeInput.txt";
	while (true) {
		if (fileHasContent(filePath)) {
			// 内容不为空,读取所有行
			std::vector<std::string> lines = readAllLines(filePath);
			atuoRun(lines);
			std::ofstream clear(filePath, std::ios::trunc);
		}
		// 每隔 500ms 检查一次,避免忙等占用 CPU
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
	}
}

int main()
{
	N = 3;
	// test1() //输入所有操作,只显示最终结果
	// test2() //每次输入1个操作,实时显示结果
	run1(); // 自动填写操作序列
	return 0;
}



run1就是支持自动复原的接口,只要程序启动就行,后面就不用管了,所有操作都在网页端。

对于三阶魔方,这个代码已经完整了,只要点击一次网页上的自动运行,即可直接复原。

【完整操作序列】
F B R D B D' F B' L F L' U' D B' F' R F' R D F' R F B R B z z z z z z z z U D U U U U U' F' U' R z z z z U U D D U U U U U' F F z z z z U D U U U U U U F' U' R z z z z U U U D D D D z z z z U F z z z z U U U D D D D U U U U U U F' U' R z z z z U U U D D D D z z z U U F z z z z U U U D D D D U U U U U' F' U' R z z z z U U D D D D z z z U U F z z z z U U U D D D D U U U U F' U' R z z z z U U U U U U D D D D z z z U F z z z z U U U U U U U U D D D D U U U U U U U U F' U' R z z z z U z z z z D U U U U y' F R F' y z z z z D U U U U D U U U U D U U U U D U U U U U y' F R F' y z z z z D U U U D U U U U D U U U U U U R' D R z z z z D U U D U U U U U U y' F R F' y z z z z z z z z U U y y U U z U' z U' U' L' U L U F U' F' U U z U' z U' z U' U' L' U L U F U' F' U U z U' z U' z U' U' L' U L U F U' F' U U z U' z U' z U' U' L' U L U F U' F' U F R U R' U' F' F R U R' U' F' U R' U' R U' R' U U R U R R F F R' B' R F F R' B R' U U R' U' R U' R' U U R z z F U F' U F U U F' U U U D

校验:

校验通过。

6,操作序列化简

通过简单的化简,能稍微降低一些操作步数


std::string replaceStr(std::string str,	const std::string& from,const std::string& to) 
{
	size_t pos = 0;
	if ((pos = str.find(from, pos)) != std::string::npos) {
		str.replace(pos, from.length(), to);
	}
	return str;
}

string replaceAns(string ans)
{
	for (char c : {'U', 'D', 'L', 'R', 'F', 'B', 'x', 'y', 'z'})
	{
		string s1 = "";
		s1 += c;
		s1 += "' ";
		s1 += c;
		s1 += " ";
		string s2 = " ";
		ans = replaceStr(ans, s1 ,s2);
		s1 = "";
		s1 += c;
		s1 += " ";
		s1 += c;
		s1 += "' ";
		ans = replaceStr(ans, s1, s2);
		s1 = "";
		s1 += c;
		s1 += " ";
		s1 += c;
		s1 += " ";
		s1 += c;
		s1 += " ";
		s2 = "";
		s2 += c;
		s2 += "' ";
		ans = replaceStr(ans, s1, s2);
		s1 = "";
		s1 += c;
		s1 += "' ";
		s1 += c;
		s1 += "' ";
		s1 += c;
		s1 += "' ";
		s2 = "";
		s2 += c;
		s2 += " ";
		ans = replaceStr(ans, s1, s2);
		s1 = "    ";
		s2 = " ";
		ans = replaceStr(ans, s1, s2);
		s1 = "   ";
		ans = replaceStr(ans, s1, s2);
		s1 = "  ";
		ans = replaceStr(ans, s1, s2);
	}
	return ans;
}

void atuoRun(vector<string>& lines)
{
	vector<vector<vector<char>>>cube;
	for (int i = 0; i < 6; i++) {
		string s = lines[i].substr(3, lines[i].length() - 3);
		vector<vector<char>>v(N, vector<char>(N));
		for (int i = 0; i < N; i++)for (int j = 0; j < N; j++)v[i][j] = s[i * N + j];
		cube.push_back(v);
	}
	string ans = autoRunOpts(cube);
	for(int i=0;i<10000;i++)ans = replaceAns(ans);
	std::ofstream outFile("D:/cubeOutput.txt", std::ios::app);
	if (outFile.is_open()) {
		outFile << ans << "\n";
		outFile.close();
	}
}

这样,完整的复原过程就从300-400步化简到了150-200步(x y z操作不计入步数)

【完整操作序列】
L B' F D' R' L' D R F' R' U R B F U B' F' R' D' R L R' D' L' F D D F' U' R F' U' R U D' U' F' U' R U F' U' R U U z' U' F U' F' U' R z' U' F U' F' U' R z' U' F U U F' U' R U z' U' U' R U z F F U U F F U U F F U' D U y' F R F' y D U' D y' F R' F' y D D y' F R F' y D D U' y' F R F' y D U D' U U y' F R F' y U U y y U z R U' R' U' F' U F U U z R U' R' U' F' U F U' z U' z R U' R' U' F' U F U' F R U R' U' R U R' U' F' U R' U' R U' R' U U R U' R' U' R U' R' U U R U' R R F F R' B' R F F R' B R' R' U' R U' R' U U R z z F U F' U F U U F' U' D

六,操作集扩充

前面的二阶和三阶都是18种操作,即6+6*2=18,只涉及单层操作。

这里我们改成支持多层操作,N阶魔方有f(N) = 6+6*2*(N-1)种操作.

f(2)=18,f(3)=30,f(4)=42......

当然,三阶魔方的相关代码不用再改了,代码更新之后只用于N>3的情况。

为了兼容,以四阶魔方为例,我们把R方向的操作命名成R、R2、R3,把R'方向的操作命名成R'、R2'、R3'

七,四阶魔方

1,网页版程序

参考 四阶魔方 网页版

2,交换2个棱块

为了充分验证我提出的偶数阶魔方的状态恒等式,这里我采用阶段二算法。(如果用阶段三算法,就不用搞这些逆序运算了)

关于解决状态恒等式的三阶段,参考《魔方复原方法推导》

这里有2个编码技巧,第一就是用二次编码,就不需要自己一个个对颜色,第二就是用rotate,就不需要自己一个个算坐标。

首先运行:

#define showOneEdge cout << cube[4][0][id] << " " << cube[0][N - 1][id] << " ";

void test3(vector<vector<vector<char>>>& cube)
{
	int id = 1;
	showOneEdge;
	rotate(cube, "U");
	showOneEdge;
	rotate(cube, "U");
	showOneEdge;
	rotate(cube, "U");
	showOneEdge;
	rotate(cube, "x");
	rotate(cube, "x");
	showOneEdge;
	rotate(cube, "U");
	showOneEdge;
	rotate(cube, "U");
	showOneEdge;
	rotate(cube, "U");
	showOneEdge;
	rotate(cube, "F");
	showOneEdge;
	rotate(cube, "F");
	rotate(cube, "F");
	showOneEdge;
	rotate(cube, "z");
	rotate(cube, "z");
	rotate(cube, "F");
	showOneEdge;
	rotate(cube, "F");
	rotate(cube, "F");
	showOneEdge;
}

输入复原状态下的魔方,输出:

RW,BW,OW,GW,OY,BY,RY,GY,OG,OB,RB,RG,

这样就得到了对24个棱块进行编码的代码了:

int getId(char a, char b)
{
	vector<string> v{"RW", "BW", "OW", "GW", "OY", "BY", "RY", "GY", "OG", "OB", "RB", "RG"};
	for (int i = 0; i < 12; i++) {
		if (v[i][0] == a && v[i][1] == b)return i;
	}
	return getId(b, a) + 12;
}

然后再复用上面的代码,变成采集24个棱块的代码:

#define GetTwoEdgeId v.push_back(getId(cube[4][0][id], cube[0][N - 1][id]));v.push_back(getId(cube[0][N - 1][N - 1 - id], cube[4][0][N - 1 - id]));
bool checkEdgeLocStatus(vector<vector<vector<char>>> cube,int id) //check***系列函数中,少有的非const&的cube参数,这里不要用&
{
	vector<int>v;
	GetTwoEdgeId;
	rotate(cube, "U");
	GetTwoEdgeId;
	rotate(cube, "U");
	GetTwoEdgeId;
	rotate(cube, "U");
	GetTwoEdgeId;
	rotate(cube, "x");
	rotate(cube, "x");
	GetTwoEdgeId;
	rotate(cube, "U");
	GetTwoEdgeId;
	rotate(cube, "U");
	GetTwoEdgeId;
	rotate(cube, "U");
	GetTwoEdgeId;
	rotate(cube, "F");
	GetTwoEdgeId;
	rotate(cube, "F");
	rotate(cube, "F");
	GetTwoEdgeId;
	rotate(cube, "z");
	rotate(cube, "z");
	rotate(cube, "F");
	GetTwoEdgeId;
	rotate(cube, "F");
	rotate(cube, "F");
	GetTwoEdgeId;
	return true;//// 待更新
}

复原状态的魔方,v一定是0 12 1 13 2 14 3 15 4 16 5 17 6 18 7 19 8 20 9 21 10 22 11 23,逆序数是158

3,U位R位棱组交叉

对于四阶魔方,每次至少合并1个棱组,最后一定会小于3个待合并棱组,此时要么已完成,要么就是:

为了方便理解代码,我们把这种情况称为U位R位棱组交叉

判断“U位R位棱组交叉”的方法:首先让正面U位棱组mid处和正面R位棱组id处棱块属于同一棱组,且方向一致,如上图的红黄棱块,此时,如果U位id处和R位mid处属于同一棱组,那就是U位R位棱组交叉。

4,自动复原

#include <iostream>
#include <string_view>
#include <string>
#include <string.h>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <array>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <iomanip>
#include <cmath>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
#include <thread>
#include <filesystem>

using namespace std;
namespace fs = std::filesystem;

class SingleVectorOpt
{
public:
	//翻转vector、翻转二维vector的每一行
	template<typename T>
	static vector<T> frev(const vector<T>& v)
	{
		vector<T> ans;
		ans.resize(v.size());
		for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
		return ans;
	}
	template<typename T>
	static vector<vector<T>> frev(const vector<vector<T>>& v)
	{
		vector<vector<T>>ans;
		for (int i = 0; i < v.size(); i++)ans.push_back(frev(v[i]));
		return ans;
	}
	//沿主对角线(左上角到右下角)翻转二维vector
	template<typename T>
	static vector<vector<T>> foverturn(const vector<vector<T>>& v)
	{
		vector<vector<T>> ans(v[0].size());
		for (int i = 0; i < v[0].size(); i++) {
			ans[i].resize(v.size());
			for (int j = 0; j < v.size(); j++)ans[i][j] = v[j][i];
		}
		return ans;
	}
	//顺时针旋转二维vector
	template<typename T>
	static vector<vector<T>> frotation(const vector<vector<T>>& v)
	{
		return frev(foverturn(v));
	}
	//从vector(一维或2维)中删除所有的x
	template<typename T>
	static void deletAllX(vector<T>& v, T x)
	{
		for (int i = 0; i < v.size(); i++)if (v[i] == x)v.erase(v.begin() + i--);
	}
	template<typename T>
	static void deletAllX(vector<vector<T>>& v, T x)
	{
		for (auto& vi : v)deletAllX(vi, x);
	}
	// 去掉相邻重复元素
	template<typename T>
	static void deleteNeiborSame(vector<T>& v)
	{
		v.erase(std::unique(v.begin(), v.end()), v.end());
	}
	//判断数组去掉相邻重复数之后有多少个不同的数
	template<typename T>
	static int getDifNum(const vector<T>& v)
	{
		auto v2 = v;
		deleteNeiborSame(v2);
		return v2.size();
	}
	//vector乘一个数
	template<typename T1, typename T2>
	static void fcheng(vector<T1>& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] *= n;
	}
	//vector加一个数
	template<typename T1, typename T2>
	static void fjia(vector<T1>& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
	}
	//二维数组每一行排序
	template<typename T>
	static void sortEveryLine(vector<vector<T>>& v)
	{
		for (int i = 0; i < v.size(); i++)sort(v[i].begin(), v[i].end());
	}
	//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
	template<typename T, class P>
	static inline vector<int>firstInLeft(vector<T>v, P pr)
	{
		vector<int> ans;
		if (v.size() == 0)return ans;
		stack<T>st;
		st.push(0);
		ans.push_back(-1);
		for (int i = 1; i < v.size(); i++) //代码用单调栈实现,时间复杂度为O(n)
		{
			while (!st.empty() && !pr(v[st.top()], v[i]))st.pop();
			if (st.empty())ans.push_back(-1);
			else ans.push_back(st.top());
			st.push(i);
		}
		return ans;
	}

	//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fminlef(vector<T> v)
	{
		return firstInLeft(v, [](T a, T b) {return a < b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fminlef2(vector<T> v)
	{
		return firstInLeft(v, [](T a, T b) {return a <= b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fmaxlef(vector<T> v)
	{
		fcheng(v, -1);
		vector<int>ans = fminlef(v);
		return ans;
	}
	//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fmaxlef2(vector<T> v)
	{
		fcheng(v, -1);
		vector<int>ans = fminlef2(v);
		return ans;
	}

	//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fminrig(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fminlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fminrig2(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fminlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fmaxrig(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fmaxlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fmaxrig2(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fmaxlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	// v中都是非负数,对于v的任意一段[low,high],求满足[low,id]总和大于等于[low,high]总和的一半的最小id
	static map<int, map<int, int>> splitAtHalf(vector<int>& v)
	{
		vector<int>s;
		int n = 0;
		s.push_back(n);
		for (auto x : v) {
			n += x;
			s.push_back(n);
		}
		map<int, map<int, int>>ans;
		for (int i = 0; i < v.size(); i++) {
			int id = i;
			for (int j = i; j < v.size(); j++) {
				while (s[id + 1] - s[i] < s[j + 1] - s[id + 1])id++;
				ans[i][j] = id;
			}
		}
		return ans;
	}
	//获取所有的众数
	template<typename T>
	static vector<T> getMost(const vector<T>& v)
	{
		int n = 0;
		map<T, int>m;
		for (auto x : v)n = max(n, ++m[x]);
		vector<T>ans;
		for (auto p : m)if (p.second == n)ans.push_back(p.first);
		return ans;
	}
};


#define Frotation SingleVectorOpt::frotation//顺时针旋转二维vector
#define Frev SingleVectorOpt::frev//翻转vector、翻转二维vector的每一行

int N;

vector<vector<vector<char>>> Init()
{
	vector<vector<vector<char>>> ans;
	for (auto c : { 'W','Y','G','B','R','O' }) //上下左右前后
	{
		vector<char> temp(N, c);
		vector<vector<char>>v(N, temp);
		ans.push_back(v);
	}
	return ans;
}

void show(vector<vector<vector<char>>>& cube)
{
	cout << endl << "U: ";
	for (auto v : cube[0])for (auto ch : v)cout << ch;
	cout << endl << "D: ";
	for (auto v : cube[1])for (auto ch : v)cout << ch;
	cout << endl << "L: ";
	for (auto v : cube[2])for (auto ch : v)cout << ch;
	cout << endl << "R: ";
	for (auto v : cube[3])for (auto ch : v)cout << ch;
	cout << endl << "F: ";
	for (auto v : cube[4])for (auto ch : v)cout << ch;
	cout << endl << "B: ";
	for (auto v : cube[5])for (auto ch : v)cout << ch;
	cout << endl;
}

void rotate(vector<vector<vector<char>>>& cube, string s);
void rotate2(vector<vector<vector<char>>>& cube, string s)
{
	if (s.length() == 1)s += "1";
	if (s[0] == 'U')
	{
		cube[0] = Frotation(cube[0]);
		for (int i = 0; i < s[1] - '0'; i++) {
			auto v = cube[2][i];
			cube[2][i] = cube[4][i], cube[4][i] = cube[3][i], cube[3][i] = cube[5][i], cube[5][i] = v;
		}
		return;
	}
	string s2 = "U";
	if (s[0] == 'D') {
		rotate(cube, "x");
		rotate(cube, "x");
		rotate(cube, s2 + s[1]);
		rotate(cube, "x");
		rotate(cube, "x");
		return;
	}
	if (s[0] == 'R')
	{
		rotate(cube, "y'");
		rotate(cube, s2 + s[1]);
		rotate(cube, "y");
		return;
	}
	if (s[0] == 'L')
	{
		rotate(cube, "y");
		rotate(cube, s2 + s[1]);
		rotate(cube, "y'");
		return;
	}
	if (s[0] == 'F')
	{
		rotate(cube, "x");
		rotate(cube, s2 + s[1]);
		rotate(cube, "x'");
		return;
	}
	if (s[0] == 'B')
	{
		rotate(cube, "x'");
		rotate(cube, s2 + s[1]);
		rotate(cube, "x");
		return;
	}
}
void rotate(vector<vector<vector<char>>>& cube, string s)
{
	int len = s.length();
	if (s[len - 1] == '\'') {
		string s2 = s.substr(0, len - 1);
		rotate(cube, s2);
		rotate(cube, s2);
		rotate(cube, s2);
		return;
	}
	if (s == "x")
	{
		cube[3] = Frotation(cube[3]);
		cube[2] = Frotation(Frotation(Frotation(cube[2])));
		auto v = cube[0];
		cube[0] = cube[4];
		cube[4] = Frev<vector<char>>(cube[1]);  //上下翻转
		cube[1] = Frev<char>(cube[5]); //翻转每一行
		cube[5] = Frev<char>(Frev<vector<char>>(v));
		return;
	}
	if (s == "z") {
		cube[0] = Frotation(cube[0]);
		cube[1] = Frotation(cube[1]);
		auto v = cube[2];
		cube[2] = cube[4], cube[4] = cube[3], cube[3] = cube[5], cube[5] = v;
		return;
	}
	if (s == "y") {
		rotate(cube, "z");
		rotate(cube, "z");
		rotate(cube, "z");
		rotate(cube, "x");
		rotate(cube, "z");
		return;
	}
	rotate2(cube, s);
}

void test1() //输入所有操作,只显示最终结果
{
	vector<string>opts;
	string c;
	while (cin >> c)opts.push_back(c);
	auto cube = Init();
	for (auto c : opts) {
		rotate(cube, c);
	}
	show(cube);
}

void test2() //每次输入1个操作,实时显示结果
{
	auto cube = Init();
	string c;
	while (cin >> c) {
		rotate(cube, c);
		show(cube);
		cout << endl;
	}
}


string makeOpt(const string& opt, int num)
{
	if (num == 1)return opt;
	string s1 = opt;
	string s2 = std::to_string(num);
	if (s1.length() == 1)return s1 + s2;  //不带'
	//带'
	string s3, s4;
	s3 += s1[0], s4 += s1[1];
	return s3 + s2 + s4;
}

#define AnsAdd(s) ans += s;ans += " "; rotate(cube, s);
// F1-F9 是三阶魔方的公式
#define F1 AnsAdd("y'");AnsAdd("F");AnsAdd("R'");AnsAdd("F'");AnsAdd("y");AnsAdd("D");AnsAdd("D");AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块1 y' F R' F' y D D y' F R F' y
#define F2 AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块2 y' F R F' y
#define F3 AnsAdd("R'");AnsAdd("D");AnsAdd("R");// 白色角块3 R' D' R
#define F4 AnsAdd("U'");AnsAdd("L'");AnsAdd("U");AnsAdd("L");AnsAdd("U");AnsAdd("F");AnsAdd("U'");AnsAdd("F'");// 中层棱块1 U' L' U L U F U' F'
#define F5 AnsAdd("U");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");AnsAdd("U");AnsAdd("F");// 中层棱块2 U R U' R' U' F' U F
#define F6 AnsAdd("F");AnsAdd("R");AnsAdd("U");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");// 顶层十字 F R U R' U' F'
#define F7 AnsAdd("R'");AnsAdd("U'");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U");AnsAdd("U");AnsAdd("R");      // 小鱼1 R' U' R U' R' U U R
#define F8 AnsAdd("F");AnsAdd("U");AnsAdd("F'");AnsAdd("U");AnsAdd("F");AnsAdd("U");AnsAdd("U");AnsAdd("F'"); // 小鱼2 F U F' U F U U F'
#define F9 AnsAdd("R");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B'");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B");AnsAdd("R'"); // 换角 R R F F R' B' R F F R' B R'
//F10 单棱对换 R2 U U R2 U U R2' x' L2' U U L2 x' U U R2 U U R2'
#define F10_1(id)   AnsAdd(makeOpt("R",id+1));AnsAdd(makeOpt("R'",id)); //R2
#define F10_2(id)   AnsAdd(makeOpt("R'",id+1));AnsAdd(makeOpt("R",id)); //R2'
#define F10_3       AnsAdd("U");AnsAdd("U"); //U U
#define F10_4(id)   F10_3;F10_1(id);F10_3;F10_2(id); //U U R2 U U R2'
#define F10(id)     F10_1(id);F10_4(id);AnsAdd("x'");AnsAdd(makeOpt("L'",id+1));AnsAdd(makeOpt("L",id));F10_3;\
    AnsAdd(makeOpt("L",id+1));AnsAdd(makeOpt("L'",id));AnsAdd("x'");F10_4(id);
//F11 U位棱组翻转
#define F11 AnsAdd("U");AnsAdd("U");AnsAdd("B");AnsAdd("L");AnsAdd("U'");
//F12 棱块合并
#define F12 AnsAdd("F2'"); AnsAdd("F"); AnsAdd("R"); AnsAdd("U'"); AnsAdd("R'"); AnsAdd("U"); AnsAdd("F2");AnsAdd("F'");
//F13 双棱对换
#define F13_1 F10_3;AnsAdd("F");AnsAdd("F");
#define F13_2 AnsAdd("R2");F10_3;AnsAdd("R2'");
#define F13_3 F13_2;F13_1;F13_1;F13_1;F13_2;
#define F13 F13_3;AnsAdd("x'");F13_3;AnsAdd("x'");F13_3;

string makeDir(vector<vector<vector<char>>>& cube) //调整白色面朝上
{
	string ans;
	int id = N / 2;
	if (cube[1][id][id] == 'W') {
		AnsAdd("x");
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[4][id][id] == 'W')break;
	}
	if (cube[0][id][id] != 'W') {
		AnsAdd("x");
	}
	return ans;
}

bool checkTopCenter(const vector<vector<vector<char>>>& cube, char c)
{
	for (int j = 1; j < N - 1; j++) {
		for (int k = 1; k < N - 1; k++) {
			if (cube[0][j][k] != c) {
				return false;
			}
		}
	}
	return true;
}

string makeCenter4OnceTry(vector<vector<vector<char>>>& cube, char c)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		bool flag = false;
		for (int j = 1; j < N - 1; j++) {
			for (int k = 1; k < N - 1; k++) {
				if (cube[4][j][k] == c) {
					flag = true;
					break;
				}
			}
			if (flag)break;
		}
		if (!flag) {
			AnsAdd("z");
			continue;
		}
		while (cube[0][1][N - 2] == c) {
			AnsAdd("U");
		}
		while (cube[4][N - 2][1] != c) {
			AnsAdd("F");
		}
		AnsAdd("R2'");
		AnsAdd("F'");
		AnsAdd("R2");
		return ans;
	}
	return "";
}
string makeCenter4Once(vector<vector<vector<char>>>& cube, char c)
{
	string ans = makeCenter4OnceTry(cube, c);
	if (!ans.empty())return ans;
	AnsAdd("x");
	ans += makeCenter4OnceTry(cube, c);
	AnsAdd("x'");
	return ans;
}

string makeCenterWhiteOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		int j, k;
		bool flag = false;
		for (j = 1; j < N - 1; j++) {
			for (k = 1; k < N - 1; k++) {
				if (cube[4][j][k] == 'W') {
					flag = true;
					break;
				}
			}
			if (flag)break;
		}
		if (!flag)continue;
		while (cube[0][j][k] == 'W') {
			AnsAdd("U");
		}
		AnsAdd(makeOpt("B", j));
		AnsAdd(makeOpt("F'", N - 1 - j));
		AnsAdd("F");
		AnsAdd(makeOpt("R", N - k));
		AnsAdd(makeOpt("R'", N - 1 - k));
		AnsAdd(makeOpt("F", N - 1 - j));
		AnsAdd(makeOpt("B'", j));
		return ans;
	}
	AnsAdd("x");
	return "z";  //// 待更新"
}
string makeCenterWhite(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCenter(cube, 'W')) {
		ans += makeCenter4Once(cube, 'W'); //N>4时要切换到makeCenterWhiteOnce,目前还没写完这个函数
	}
	return ans;
}

string makeCenterYellowOnce(vector<vector<vector<char>>>& cube)
{
	return "";///待更新
}

string makeCenterYellow(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCenter(cube, 'Y')) {
		ans += makeCenter4Once(cube, 'Y'); //N>4时要切换到makeCenterYellowOnce,目前还没写完这个函数
	}
	return ans;
}

string makeCenterRedOnce(vector<vector<vector<char>>>& cube)
{
	return "";///待更新
}

string makeCenterRed(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCenter(cube, 'R')) {
		ans += makeCenter4Once(cube, 'R'); //N>4时要切换到makeCenterRedOnce,目前还没写完这个函数
	}
	return ans;
}

string makeCenterGreenOnce(vector<vector<vector<char>>>& cube)
{
	return "";///待更新
}

string makeCenterGreen(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCenter(cube, 'G')) {
		ans += makeCenter4Once(cube, 'G'); //N>4时要切换到makeCenterGreenOnce,目前还没写完这个函数
	}
	return ans;
}

string makeCenterOrangeOnce(vector<vector<vector<char>>>& cube)
{
	return "";///待更新
}

string makeCenterOrange(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCenter(cube, 'O')) {
		ans += makeCenter4Once(cube, 'O'); //N>4时要切换到makeCenterOrangeOnce,目前还没写完这个函数
	}
	return ans;
}

string makeAllCenter(vector<vector<vector<char>>>& cube)
{
	string ans = makeDir(cube);
	ans += makeCenterWhite(cube);
	AnsAdd("x");
	AnsAdd("x");
	ans += makeCenterYellow(cube);
	AnsAdd("x");
	AnsAdd("x");
	//上白下黄
	for (int i = 0; i < 4; i++) {
		if (cube[4][N / 2][N / 2] == 'R')break;
		AnsAdd("z");
	}
	//上白下黄 前红
	AnsAdd("x");
	AnsAdd("z'");
	//上红 左白 右黄
	ans += makeCenterRed(cube);
	ans += makeDir(cube);
	for (int i = 0; i < 4; i++) {
		if (cube[4][N / 2][N / 2] == 'R')break;
		AnsAdd("z");
	}
	//上白下黄 前红
	AnsAdd("z");
	AnsAdd("z");
	AnsAdd("y'");
	//上绿 左白 右黄
	ans += makeCenterGreen(cube);
	ans += makeDir(cube);
	for (int i = 0; i < 4; i++) {
		if (cube[4][N / 2][N / 2] == 'R')break;
		AnsAdd("z");
	}
	//上白下黄 前红
	AnsAdd("z");
	AnsAdd("y'");
	//上橙 左白 右黄
	ans += makeCenterOrange(cube);
	return ans;
}

int getId(char a, char b)
{
	vector<string> v{ "RW", "BW", "OW", "GW", "OY", "BY", "RY", "GY", "OG", "OB", "RB", "RG" };
	for (int i = 0; i < 12; i++) {
		if (v[i][0] == a && v[i][1] == b)return i;
	}
	return getId(b, a) + 12;
}

template<typename T>
int getInvertNum(vector<T>v)
{
	int n = 0;
	for (int i = 0; i < v.size(); i++) {
		for (int j = i + 1; j < v.size(); j++) {
			if (v[i] > v[j])n++;
		}
	}
	return n;
}


#define ForEachEdgeUp(func) func;rotate(cube, "U");func;rotate(cube, "U");func;rotate(cube, "U");func;
#define ForEachEdgeLR(func) rotate(cube, "F");func;rotate(cube, "F");rotate(cube, "F");func;
// 依次把12个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdge(func) ForEachEdgeUp(func);rotate(cube, "x");rotate(cube, "x");ForEachEdgeUp(func);\
	ForEachEdgeLR(func);rotate(cube, "z");rotate(cube, "z");ForEachEdgeLR(func);
#define GetTwoEdgeId v.push_back(getId(cube[4][0][id], cube[0][N - 1][id]));v.push_back(getId(cube[0][N - 1][N - 1 - id], cube[4][0][N - 1 - id]));

bool checkEdgeLocStatus(vector<vector<vector<char>>> cube, int id) //check***系列函数中,少有的非const&的cube参数,这里不要用&
{
	vector<int>v;
	ForEachEdge(GetTwoEdgeId);
	return getInvertNum(v) % 2 == 0;
}

string makeEdgeLocStatus(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 1; i < N / 2; i++) {
		if (!checkEdgeLocStatus(cube, i)) {
			F10(i);//交换2个棱块
		}
	}
	return ans;
}

#define ForEachEdgeUp2(func) func;AnsAdd("U");func;AnsAdd("U");func;AnsAdd("U");func;
#define ForEachEdgeLR2(func) AnsAdd("F");func;AnsAdd("F");AnsAdd("F");func;
// 依次把12个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdge2(func) ForEachEdgeUp2(func);AnsAdd( "x");AnsAdd( "x");ForEachEdgeUp2(func);\
	ForEachEdgeLR2(func);AnsAdd( "z");AnsAdd( "z");ForEachEdgeLR2(func);
// 依次把10个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdgeExceptLR(func) ForEachEdgeUp2(func);AnsAdd( "B");AnsAdd( "U");AnsAdd( "B");AnsAdd( "U");AnsAdd( "B");AnsAdd( "U");\
    AnsAdd( "D");AnsAdd( "B");AnsAdd( "B");	ForEachEdgeUp2(func);AnsAdd( "D");AnsAdd( "B");AnsAdd( "D");AnsAdd( "B");AnsAdd( "U");\
    AnsAdd( "B");AnsAdd( "U");func;AnsAdd( "U");func;

#define case1 (cube[0][N - 1][mid] == target[0] && cube[4][0][mid] == target[1])
#define case2 (cube[0][N - 1][mid] == target[1] && cube[4][0][mid] == target[0])
#define case3 (cube[0][N - 1][id] == target[0] && cube[4][0][id] == target[1])
#define case4 (cube[0][N - 1][id] == target[1] && cube[4][0][id] == target[0])
#define FindEdgeWithTarget  if (case1||case2||((N%2==0)&&(case3||case4)))goto here;
#define FindEdgeWithDif if (cube[0][N - 1][mid] != cube[0][N - 1][id] || cube[4][0][mid] !=cube[4][0][id])goto here2;

bool checkAllEdge(vector<vector<vector<char>>> &cube,int id, string &ans)//check***系列函数中,少有的非const&的cube参数,这里要用&
{
	int mid = (N - 1) / 2;
	ForEachEdge2(if (cube[4][0][id] != cube[4][0][mid] || cube[0][N - 1][id]!= cube[0][N - 1][mid])return false;)
	return true;
}

string makeAllEdgeOnce(vector<vector<vector<char>>>& cube,int id)
{
	string ans;	
	string target;
	target += cube[0][N - 1][id];
	target += cube[4][0][id];
	int mid = (N - 1) / 2;
	char c1 = cube[0][N - 1][mid], c2 = cube[4][0][mid];
	AnsAdd("F");//棱组停留在正面R位
	FindEdgeWithTarget;
	AnsAdd("U");
	AnsAdd("L");//一个不带mid的棱组停留在正面L位
	ForEachEdgeExceptLR(FindEdgeWithTarget);
here:
	//带mid的棱组停留在正面U位
	if (N % 2 == 1 && cube[0][N - 1][mid] == target[1] && cube[4][0][mid] == target[0]) {
		F11;
	}
	if (N % 2 == 0 && cube[0][N - 1][id] == target[1] && cube[4][0][id] == target[0]) {
		F11;
	}
    //此时,正面U位棱组mid处和正面R位棱组id处棱块属于同一棱组,且方向一致
	if (c1 == cube[0][N - 1][id] && c2 == cube[4][0][id]) {
		// U位R位棱组交叉
		F11;
		AnsAdd("z'");
		AnsAdd("x'");
		F12;  /////待更新    对于非4阶魔方,需要换公式
		AnsAdd("R'");
		AnsAdd("z'");
		AnsAdd("x'");
		AnsAdd("L'");
		AnsAdd("B");
		AnsAdd("D'");
		F12;  /////待更新    对于非4阶魔方,需要换公式
		return ans;
	}
	AnsAdd("U");
	AnsAdd("L");//带mid的棱组停留在正面L位
	ForEachEdgeExceptLR(FindEdgeWithDif);
here2:
	//带dif的棱组停留在正面U位
	AnsAdd("R");
	AnsAdd("R");
	AnsAdd("B");
	AnsAdd("U'");
	AnsAdd("R");
	AnsAdd("B");
	AnsAdd("B");
	AnsAdd("z");
	AnsAdd("z");
	AnsAdd("x'");
	F12;  /////待更新    对于非4阶魔方,需要换公式
	return ans;
}
string makeAllEdge(vector<vector<vector<char>>>& cube)
{
	string ans;
	int mid = (N - 1) / 2;
	for (int i = mid + 1; i < N - 1; i++) {
		while (true) {
			string s;
			bool ret = checkAllEdge(cube, i, s);
			ans += s;
			if (ret) {
				break;
			}
			ans += makeAllEdgeOnce(cube,i);
		}
	}
	for (int i = 1; i < mid; i++) {
		/////待更新   对于N>4涉及
	}
	return ans;
}

string makeUUUU(vector<vector<vector<char>>>& cube) //白色层方向回正
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][N - 1][1] == 'W' && cube[4][0][1] == 'R') {
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][1][N - 1] == 'W' && cube[3][0][1] == 'B') {
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][1][0] == 'W' && cube[2][0][1] == 'G') {
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][0][1] == 'W' && cube[5][0][1] == 'O') {
			return ans;
		}
	}
	return ans;
}

bool checkWhiteCross(const vector<vector<vector<char>>>& cube)// 检查白色十字是否完成
{
	char whiteColor = 'W';
	if (cube[0][0][1] != whiteColor || cube[0][N - 1][1] != whiteColor || cube[0][1][0] != whiteColor || cube[0][1][N - 1] != whiteColor) {
		return false;
	}
	if (cube[2][0][1] != 'G' || cube[3][0][1] != 'B' || cube[4][0][1] != 'R') {
		return false;
	}
	return true;
}

string makeWhiteCrossOnce(vector<vector<vector<char>>>& cube)
{
	string ans = "";
	for (int i = 0; i < 4; i++) {
		AnsAdd("D");
		if (cube[4][N - 1][1] == 'W') {
			ans += makeUUUU(cube);
			char c = cube[1][N - 1][1];
			if (c == 'B') {
				AnsAdd("U");
			}
			if (c == 'O') {
				AnsAdd("U");
				AnsAdd("U");
			}
			if (c == 'G') {
				AnsAdd("U'");
			}
			AnsAdd("F'");
			AnsAdd("U'");
			AnsAdd("R");
			return ans;
		}
		if (cube[1][N - 1][1] == 'W') {
			ans += makeUUUU(cube);
			char c = cube[4][N - 1][1];
			if (c == 'B') {
				AnsAdd("U");
			}
			if (c == 'O') {
				AnsAdd("U");
				AnsAdd("U");
			}
			if (c == 'G') {
				AnsAdd("U'");
			}
			AnsAdd("F");
			AnsAdd("F");
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[4][1][N - 1] == 'W' || cube[3][1][0] == 'W') {
			while (cube[0][N - 1][1] == 'W') {
				AnsAdd("U");
			}
			AnsAdd("F");
			return ans;
		}
	}
	ans += makeUUUU(cube);
	string s = "BOGR";
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[0][N - 1][1] != 'W' || cube[4][0][1] != s[i]) {
			AnsAdd("F");
			AnsAdd("F");
			return ans;
		}
	}
	return ans;
}

string makeWhiteCross(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (true) {
		ans += makeDir(cube);
		ans += makeUUUU(cube);
		if (checkWhiteCross(cube))break;
		ans += makeWhiteCrossOnce(cube);
	}
	return ans;
}

bool checkWhite(const vector<vector<vector<char>>>& cube)// 检查白色是否完成
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][0][0] != cube[i][0][1] || cube[i][0][N - 1] != cube[i][0][1])return false;
	}
	return true;
}
string makeWhiteOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("D");
		ans += makeUUUU(cube);
		string t;
		t += cube[1][N - 1][N - 1];
		t += cube[3][N - 1][0];
		t += cube[4][N - 1][N - 1];
		sort(t.begin(), t.end());
		if (t == "BOW") {
			AnsAdd("U");
		}
		if (t == "GOW") {
			AnsAdd("U");
			AnsAdd("U");
		}
		if (t == "GRW") {
			AnsAdd("U");
			AnsAdd("U");
			AnsAdd("U");
		}
		if (cube[1][N - 1][N - 1] == 'W') {
			F1;
			return ans;
		}
		if (cube[4][N - 1][N - 1] == 'W') {
			F2;
			return ans;
		}
		if (cube[3][N - 1][0] == 'W') {
			F3;
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[4][0][N - 1] != cube[4][0][1] || cube[3][0][0] != cube[3][0][1]) {
			F2;
			return ans;
		}
	}
	return ans;
}
string makeWhite(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (true) {
		ans += makeDir(cube);
		if (checkWhite(cube))break;
		ans += makeWhiteOnce(cube);
	}
	return ans;
}

bool checkMid(const vector<vector<vector<char>>>& cube)
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][1][0] != cube[i][1][1] || cube[i][1][N - 1] != cube[i][1][1])return false;
	}
	return true;
}
string makeMidOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		string t;
		t += cube[0][N - 1][1];
		t += cube[4][0][1];
		if (t[0] != 'Y' && t[1] != 'Y') {
			while (cube[4][0][1] != cube[4][1][1]) {
				AnsAdd("z");
				AnsAdd("U'");
			}
			if (t == "BR" || t == "RG" || t == "GO" || t == "OB") {
				F4;
			}
			else {
				F5;
			}
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[4][1][0] != cube[4][1][1]) {
			F4;
		}
		else if (cube[4][1][N - 1] != cube[4][1][1]) {
			F5;
		}
	}
	return ans;
}
string makeMid(vector<vector<vector<char>>>& cube)
{
	string ans = makeDir(cube) + " ";
	ans += makeUUUU(cube);
	AnsAdd("y");
	AnsAdd("y");
	//从此,白色在下面,不能再调用makeDir和makeUUUU!!!!
	while (true) {
		if (checkMid(cube))break;
		ans += makeMidOnce(cube);
	}
	return ans;
}

bool checkTopCross(const vector<vector<vector<char>>>& cube)
{
	int num = 0;
	if (cube[0][0][1] == 'Y')num++;
	if (cube[0][N - 1][1] == 'Y')num++;
	if (cube[0][1][0] == 'Y')num++;
	if (cube[0][1][N - 1] == 'Y')num++;
	return num == 4;
}
string makeTopCrossOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	int num = 0;
	if (cube[0][0][1] == 'Y')num++;
	if (cube[0][N - 1][1] == 'Y')num++;
	if (cube[0][1][0] == 'Y')num++;
	if (cube[0][1][N - 1] == 'Y')num++;
	if (num == 2) {
		while (cube[0][1][0] != 'Y') {
			AnsAdd("U");
		}
		if (cube[0][N - 1][1] == 'Y') {
			AnsAdd("U");
		}
	}
	F6;
	return ans;
}
string makeTopCross(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCross(cube)) {
		ans += makeTopCrossOnce(cube);
	}
	return ans;
}

bool checkTopDir(const vector<vector<vector<char>>>& cube)
{
	int num = 0;
	if (cube[0][0][0] == 'Y') num++;
	if (cube[0][0][N - 1] == 'Y') num++;
	if (cube[0][N - 1][0] == 'Y') num++;
	if (cube[0][N - 1][N - 1] == 'Y') num++;
	return num == 4;
}

string makeTopDirOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	int num = 0;
	if (cube[0][0][0] == 'Y') num++;
	if (cube[0][0][N - 1] == 'Y') num++;
	if (cube[0][N - 1][0] == 'Y') num++;
	if (cube[0][N - 1][N - 1] == 'Y') num++;
	if (num == 0) {
		while (cube[2][0][0] != 'Y') {
			AnsAdd("U");
		}
		F7;
		return ans;
	}
	if (num == 2) {
		while (cube[5][0][N - 1] != 'Y') {
			AnsAdd("U");
		}
		F7;
		return ans;
	}
	while (cube[0][0][0] != 'Y') {
		AnsAdd("U");
	}
	if (cube[4][0][0] == 'Y') {
		F7;
		return ans;
	}
	F8;
	return ans;
}
string makeTopDir(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopDir(cube)) {
		ans += makeTopDirOnce(cube);
	}
	return ans;
}

bool checkTopCornerLoc(const vector<vector<vector<char>>>& cube)
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][0][0] != cube[i][0][N - 1])return false;
	}
	return true;
}

string makeTopCornerLocOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[3][0][0] == cube[3][0][N - 1])break;
	}
	F9;
	return ans;
}
string makeTopCornerLoc(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCornerLoc(cube)) {
		ans += makeTopCornerLocOnce(cube);
	}
	return ans;
}

string makeChangeEdge(vector<vector<vector<char>>>& cube, bool &changed)
{
	string ans;
	changed = false;
	//方向回正
	while (cube[4][1][1] != 'O') {
		AnsAdd("z");
	}
	while (cube[4][0][0] != cube[4][1][0]) {
		AnsAdd("U");
	}
	vector<char>v;
	for (int i = 2; i <= 5; i++) {
		v.push_back(cube[i][0][1]);
	}
	// 复原是GBOR
	if (getInvertNum(v) % 2 == 0) {
		F13;
		changed = true;
	}
	return ans;
}

bool checkTopEdgeLoc(const vector<vector<vector<char>>>& cube)
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][0][0] != cube[i][0][1])return false;
	}
	return true;
}
string makeTopEdgeLocOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[4][0][0] == cube[4][0][1])break;
	}
	F7;
	AnsAdd("z");
	AnsAdd("z");
	F8;
	return ans;
}
string makeTopEdgeLoc(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopEdgeLoc(cube)) {
		ans += makeTopEdgeLocOnce(cube);
	}
	return ans;
}

string makeAll(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (cube[4][0][0] != cube[4][1][0]) {
		AnsAdd("U");
	}
	while (cube[4][N - 1][0] != cube[4][1][0]) {
		AnsAdd("D");
	}
	return ans;
}

string autoRunOpts(vector<vector<vector<char>>>& cube)
{
	string ans = makeAllCenter(cube); //中心大正方形合并
	ans += makeEdgeLocStatus(cube); //棱块位置奇偶性
	ans += makeAllEdge(cube); //棱块合并	
	ans += makeWhiteCross(cube); //白色十字
	ans += makeWhite(cube);//白色
	ans += makeMid(cube);//中间层
	ans += makeTopCross(cube);//顶层十字
	ans += makeTopDir(cube);//顶层朝向
	ans += makeTopCornerLoc(cube);	//角块归位
	bool changed;
	ans += makeChangeEdge(cube, changed);//双棱对换
	if (changed) {
		ans += makeWhiteCross(cube); //白色十字
		ans += makeWhite(cube);//白色
		ans += makeMid(cube);//中间层
		ans += makeTopCross(cube);//顶层十字
		ans += makeTopDir(cube);//顶层朝向
		ans += makeTopCornerLoc(cube);	//角块归位
	}
	ans += makeTopEdgeLoc(cube);//棱组归位
	ans += makeAll(cube);//复原
	return ans;
}

bool replaceStr(std::string &str, const std::string& from, const std::string& to)
{
	size_t pos = 0;
	if ((pos = str.find(from, pos)) != std::string::npos) {
		str.replace(pos, from.length(), to);
		return true;
	}
	return false;
}

bool replaceAns(string &ans)
{
	bool ret = false;
	for (char c : {'U', 'D', 'L', 'R', 'F', 'B', 'x', 'y', 'z'})
	{
		string s1 = "";
		s1 += c;
		s1 += "' ";
		s1 += c;
		s1 += " ";
		string s2 = " ";
		ret = ret || replaceStr(ans, s1, s2);
		s1 = "";
		s1 += c;
		s1 += " ";
		s1 += c;
		s1 += "' ";
		ret = ret || replaceStr(ans, s1, s2);
		s1 = "";
		s1 += c;
		s1 += " ";
		s1 += c;
		s1 += " ";
		s1 += c;
		s1 += " ";
		s2 = "";
		s2 += c;
		s2 += "' ";
		ret = ret || replaceStr(ans, s1, s2);
		s1 = "";
		s1 += c;
		s1 += "' ";
		s1 += c;
		s1 += "' ";
		s1 += c;
		s1 += "' ";
		s2 = "";
		s2 += c;
		s2 += " ";
		ret = ret || replaceStr(ans, s1, s2);
		s1 = "  ";
		s2 = " ";
		ret = ret || replaceStr(ans, s1, s2);
	}
	return ret;
}

void atuoRun(vector<string>& lines)
{
	vector<vector<vector<char>>>cube;
	for (int i = 0; i < 6; i++) {
		string s = lines[i].substr(3, lines[i].length() - 3);
		vector<vector<char>>v(N, vector<char>(N));
		for (int i = 0; i < N; i++)for (int j = 0; j < N; j++)v[i][j] = s[i * N + j];
		cube.push_back(v);
	}
	string ans = autoRunOpts(cube);
	while(replaceAns(ans));
	std::ofstream outFile("D:/cubeOutput.txt", std::ios::app);
	if (outFile.is_open()) {
		outFile << ans << "\n";
		outFile.close();
	}
}

// 读取文件的所有行,每一行存入一个 string
std::vector<std::string> readAllLines(const std::string& path) {
	std::vector<std::string> lines;
	std::ifstream in(path);
	if (!in.is_open()) {
		return lines;  // 打开失败,返回空
	}

	std::string line;
	while (std::getline(in, line)) {
		lines.push_back(line);   // 每行一个 string 对象
	}
	return lines;
}

// 判断文件内容是否不为空
bool fileHasContent(const std::string& path) {
	std::error_code ec;

	// 1. 文件必须存在
	if (!fs::exists(path, ec) || ec) {
		return false;
	}

	// 2. 文件大小必须大于 0
	if (fs::file_size(path, ec) == 0 || ec) {
		return false;
	}

	return true;
}

void run1() // 自动填写操作序列
{
	const std::string filePath = "D:/cubeInput.txt";
	while (true) {
		if (fileHasContent(filePath)) {
			// 内容不为空,读取所有行
			std::vector<std::string> lines = readAllLines(filePath);
			atuoRun(lines);
			std::ofstream clear(filePath, std::ios::trunc);
		}
		// 每隔 500ms 检查一次,避免忙等占用 CPU
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
	}
}

int main()
{
	N = 4;
	//test1(); //输入所有操作,只显示最终结果
	// test2(); //每次输入1个操作,实时显示结果
	run1(); // 自动填写操作序列
	return 0;
}

经过漫长的调试,解BUG,第一个全自动复原终于诞生。

随机打乱序列:

F F2' D2 L' B2 R' B U2 R' B D2 D L2 D2' F2 D F U2 B' B2 B F2 R F2 R' U2' D2' R2' L U

复原序列:

 x R2' F' R2 z F R2' F' R2 z z U U F R2' F' R2 x R2' F' R2 x' U F R2' F' R2 x x F R2' F' R2 F F R2' F' R2 z z U' F R2' F' R2 x' z' F' R2' F' R2 z z F R2' F' R2 x F F R2' F' R2 x' U U F R2' F' R2 z x y' F R2' F' R2 x F F R2' F' R2 x' U F R2' F' R2 z' x y' F R2' F' R2 F R2' F' R2 U F R2' F' R2 R2 R' U U R2 R' U U R2' R x' L2' L U U L2 L' x' U U R2 R' U U R2' R F U L U U L R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B B U U L R R B U' R B B z z x' F2' F R U' R' U F2 U L U U L R R B U' R B B z z x' F2' F R U' R' U F2 F' U U F U L U' B U B U B U D B' L L R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B B U U B L L R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B L L R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B B U U B L L R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B B U B L L U R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B B U' B L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F2' F R U' R' U F2 U L U' B U B U B U D B' L U' z' x' F2' F R U' R' U F2 F' R' z' x' L' B D' F2' F R U' R' U F2 F' U' x x U' F' z z F' x U U D D F F D D F' U' R U z' U U F U' F' U' R U z' U U F U' U' F' U' R U U z' U U F U' F' U' R U U z' R U z F F U' F' U' R z' U' F U' F' U' R U z' U U F U F' U' R U' z' U U F U F' U' R U' z' U U F U F' U' R U' z' U U F U' U' F' U' R U U z' U U F U' F' U' R U U z' R U D D U' y' F R' F' y D D y' F R F' y D U D R' D R D D y' F R F' y U y' F R' F' y D D y' F R F' y D U' D' U U y' F R F' y D U U D D U U y' F R' F' y D D y' F R F' y U U y y U z U' U' L' U L U F U' F' U U R U' R' U' F' U F U z U' z U' z U' U' L' U L U F U' F' z U' z R U' R' U' F' U F U' F R U R' U' R U R' U' F' R' U' R U' R' U U R U' R' U' R U' R' U U R U R R F F R' B' R F F R' B R' z z U U R' U' R U' R' U U R z z F U F' U F U U F' R' U' R U' R' U U R z z F U F' U F U U F' U U R' U' R U' R' U U R z z F U F' U F U U F' U U D D 

校验:

校验通过。

八,Bug修复

四阶魔方网页版有个小BUG,操作集支持的有遗漏。

在五阶魔方网页版中已修复。

九,五阶魔方

1,网页版程序

参考五阶魔方网页版

2,自动复原V1

因为四阶魔方自动复原里面,有些东西没考虑清楚,所以在这里,一些代码都被更通用的代码给替代了。

代码略

完整操作序列:


R4 U3 U2' B B3 F B' U4 F4 U2 B3' U3' B' D3 R' F' B' L2' R2 D3' B2 F' L R' F3 R4 B4 L2 B2 R2' U3' R4 L3 D3 B3 L3 D4' R' B4 F4' x x L2' U L2 x' F' U U L2' U L2 F z z F F U L2' U U L2 F L2' U L2 F z z x x z F L2' U L2 F L2' U L2 F F z F U L2' U' L2 F' z z x z x' F' U U L2' U L2 F z z F U L2' U U L2 F F L2' U L2 F x x U U L2' U U L2 x' F F U' L2' U L2 F L2' U L2 F L2' U L2 x F F U U L2' U U L2 F F L2' U L2 z x F U L2' U' L2 U' L2' U U L2 F' z' F' U L2' U' L2 U' L2' U U L2 F z x x F F U L2' U' L2 U' L2' U U L2 F F U L2' U' L2 U' L2' U U L2 z z F F U U L2' U' L2 U' L2' U U L2 F F U' L2' U' L2 U' L2' U U L2 z x z x' F U L2' U' L2 U' L2' U U L2 F' z z F F U L2' U' L2 U' L2' U U L2 F F x x U' L2' U' L2 U' L2' U U L2 x' F U L2' U' L2 U' L2' U U L2 F U L2' U' L2 U' L2' U U L2 F U L2' U' L2 U' L2' U U L2 F x F L2' U' L2 U' L2' U U L2 F' U U B L U' F U L U' B U B U B U D B B U' D B D B U B U' L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U U L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U U L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U U B L L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U U B L L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B' L L U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L B L L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U U L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U B L L U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U B L L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U B L L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B L U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U B L L U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L B L L U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U' D B D B U B B L L U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L B L L U' B U B U B U D B B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B' L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L L U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U B L L U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B B U U L R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L B L L U' B U B U B U D B B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U L U' B U B U B U D B B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U U B L U' F U L U' B U B U B U D B' L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 U L U' B U B U B U D B B U' L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 U L U U B L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 U L U' B U B U B U D B B U' D B D B U B B L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 U L U' B U B U B U D B B U' B L L U' B U B U B U D B B U' D B D B U B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' U' x x U' F' z z F' z x U' z U F U U F' U' R z z U F U' F F U F F U z U' U' R U D U' y' F R F' y D U D R' D R D D y' F R F' y U y' F R F' y D U' D' U U y' F R F' y D U U D D U U y' F R F' y U U y y U z U' z U' U' L' U L U F U' F' U U z U' z R U' R' U' F' U F z' U R U' R' U' F' U F z U' L' U L U F U' F' z U' z U' z R U' R' U' F' U F F R U R' U' R U R' U' F' U R' U' R U' R' U U R U F U F' U F U U F' R R F F R' B' R F F R' B R' z' U' R' U' R U' R' U U R z z F U F' U F U U F' R' U' R U' R' U U R z z F U F' U F U U F' U U R' U' R U' R' U U R z z F U F' U F U U F' U U

校验:

校验通过

3,自动还原V2

V1代码考虑的还是不够,V2更严谨。

#include <iostream>
#include <string_view>
#include <string>
#include <string.h>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <array>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <iomanip>
#include <cmath>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
#include <thread>
#include <filesystem>

using namespace std;
namespace fs = std::filesystem;

class SingleVectorOpt
{
public:
	//翻转vector、翻转二维vector的每一行
	template<typename T>
	static vector<T> frev(const vector<T>& v)
	{
		vector<T> ans;
		ans.resize(v.size());
		for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
		return ans;
	}
	template<typename T>
	static vector<vector<T>> frev(const vector<vector<T>>& v)
	{
		vector<vector<T>>ans;
		for (int i = 0; i < v.size(); i++)ans.push_back(frev(v[i]));
		return ans;
	}
	//沿主对角线(左上角到右下角)翻转二维vector
	template<typename T>
	static vector<vector<T>> foverturn(const vector<vector<T>>& v)
	{
		vector<vector<T>> ans(v[0].size());
		for (int i = 0; i < v[0].size(); i++) {
			ans[i].resize(v.size());
			for (int j = 0; j < v.size(); j++)ans[i][j] = v[j][i];
		}
		return ans;
	}
	//顺时针旋转二维vector
	template<typename T>
	static vector<vector<T>> frotation(const vector<vector<T>>& v)
	{
		return frev(foverturn(v));
	}
	//从vector(一维或2维)中删除所有的x
	template<typename T>
	static void deletAllX(vector<T>& v, T x)
	{
		for (int i = 0; i < v.size(); i++)if (v[i] == x)v.erase(v.begin() + i--);
	}
	template<typename T>
	static void deletAllX(vector<vector<T>>& v, T x)
	{
		for (auto& vi : v)deletAllX(vi, x);
	}
	// 去掉相邻重复元素
	template<typename T>
	static void deleteNeiborSame(vector<T>& v)
	{
		v.erase(std::unique(v.begin(), v.end()), v.end());
	}
	//判断数组去掉相邻重复数之后有多少个不同的数
	template<typename T>
	static int getDifNum(const vector<T>& v)
	{
		auto v2 = v;
		deleteNeiborSame(v2);
		return v2.size();
	}
	//vector乘一个数
	template<typename T1, typename T2>
	static void fcheng(vector<T1>& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] *= n;
	}
	//vector加一个数
	template<typename T1, typename T2>
	static void fjia(vector<T1>& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
	}
	//二维数组每一行排序
	template<typename T>
	static void sortEveryLine(vector<vector<T>>& v)
	{
		for (int i = 0; i < v.size(); i++)sort(v[i].begin(), v[i].end());
	}
	//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
	template<typename T, class P>
	static inline vector<int>firstInLeft(vector<T>v, P pr)
	{
		vector<int> ans;
		if (v.size() == 0)return ans;
		stack<T>st;
		st.push(0);
		ans.push_back(-1);
		for (int i = 1; i < v.size(); i++) //代码用单调栈实现,时间复杂度为O(n)
		{
			while (!st.empty() && !pr(v[st.top()], v[i]))st.pop();
			if (st.empty())ans.push_back(-1);
			else ans.push_back(st.top());
			st.push(i);
		}
		return ans;
	}

	//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fminlef(vector<T> v)
	{
		return firstInLeft(v, [](T a, T b) {return a < b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fminlef2(vector<T> v)
	{
		return firstInLeft(v, [](T a, T b) {return a <= b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fmaxlef(vector<T> v)
	{
		fcheng(v, -1);
		vector<int>ans = fminlef(v);
		return ans;
	}
	//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fmaxlef2(vector<T> v)
	{
		fcheng(v, -1);
		vector<int>ans = fminlef2(v);
		return ans;
	}

	//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fminrig(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fminlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fminrig2(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fminlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fmaxrig(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fmaxlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fmaxrig2(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fmaxlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	// v中都是非负数,对于v的任意一段[low,high],求满足[low,id]总和大于等于[low,high]总和的一半的最小id
	static map<int, map<int, int>> splitAtHalf(vector<int>& v)
	{
		vector<int>s;
		int n = 0;
		s.push_back(n);
		for (auto x : v) {
			n += x;
			s.push_back(n);
		}
		map<int, map<int, int>>ans;
		for (int i = 0; i < v.size(); i++) {
			int id = i;
			for (int j = i; j < v.size(); j++) {
				while (s[id + 1] - s[i] < s[j + 1] - s[id + 1])id++;
				ans[i][j] = id;
			}
		}
		return ans;
	}
	//获取所有的众数
	template<typename T>
	static vector<T> getMost(const vector<T>& v)
	{
		int n = 0;
		map<T, int>m;
		for (auto x : v)n = max(n, ++m[x]);
		vector<T>ans;
		for (auto p : m)if (p.second == n)ans.push_back(p.first);
		return ans;
	}
};


#define Frotation SingleVectorOpt::frotation//顺时针旋转二维vector
#define Frev SingleVectorOpt::frev//翻转vector、翻转二维vector的每一行

int N;

vector<vector<vector<char>>> Init()
{
	vector<vector<vector<char>>> ans;
	for (auto c : { 'W','Y','G','B','R','O' }) //上下左右前后
	{
		vector<char> temp(N, c);
		vector<vector<char>>v(N, temp);
		ans.push_back(v);
	}
	return ans;
}

void show(vector<vector<vector<char>>>& cube)
{
	cout << endl << "U: ";
	for (auto v : cube[0])for (auto ch : v)cout << ch;
	cout << endl << "D: ";
	for (auto v : cube[1])for (auto ch : v)cout << ch;
	cout << endl << "L: ";
	for (auto v : cube[2])for (auto ch : v)cout << ch;
	cout << endl << "R: ";
	for (auto v : cube[3])for (auto ch : v)cout << ch;
	cout << endl << "F: ";
	for (auto v : cube[4])for (auto ch : v)cout << ch;
	cout << endl << "B: ";
	for (auto v : cube[5])for (auto ch : v)cout << ch;
	cout << endl;
}

void rotate(vector<vector<vector<char>>>& cube, string s);
void rotate2(vector<vector<vector<char>>>& cube, string s)
{
	if (s.length() == 1)s += "1";
	if (s[0] == 'U')
	{
		cube[0] = Frotation(cube[0]);
		for (int i = 0; i < s[1] - '0'; i++) {
			auto v = cube[2][i];
			cube[2][i] = cube[4][i], cube[4][i] = cube[3][i], cube[3][i] = cube[5][i], cube[5][i] = v;
		}
		return;
	}
	string s2 = "U";
	if (s[0] == 'D') {
		rotate(cube, "x");
		rotate(cube, "x");
		rotate(cube, s2 + s[1]);
		rotate(cube, "x");
		rotate(cube, "x");
		return;
	}
	if (s[0] == 'R')
	{
		rotate(cube, "y'");
		rotate(cube, s2 + s[1]);
		rotate(cube, "y");
		return;
	}
	if (s[0] == 'L')
	{
		rotate(cube, "y");
		rotate(cube, s2 + s[1]);
		rotate(cube, "y'");
		return;
	}
	if (s[0] == 'F')
	{
		rotate(cube, "x");
		rotate(cube, s2 + s[1]);
		rotate(cube, "x'");
		return;
	}
	if (s[0] == 'B')
	{
		rotate(cube, "x'");
		rotate(cube, s2 + s[1]);
		rotate(cube, "x");
		return;
	}
}
void rotate(vector<vector<vector<char>>>& cube, string s)
{
	int len = s.length();
	if (s[len - 1] == '\'') {
		string s2 = s.substr(0, len - 1);
		rotate(cube, s2);
		rotate(cube, s2);
		rotate(cube, s2);
		return;
	}
	if (s == "x")
	{
		cube[3] = Frotation(cube[3]);
		cube[2] = Frotation(Frotation(Frotation(cube[2])));
		auto v = cube[0];
		cube[0] = cube[4];
		cube[4] = Frev<vector<char>>(cube[1]);  //上下翻转
		cube[1] = Frev<char>(cube[5]); //翻转每一行
		cube[5] = Frev<char>(Frev<vector<char>>(v));
		return;
	}
	if (s == "z") {
		cube[0] = Frotation(cube[0]);
		cube[1] = Frotation(cube[1]);
		auto v = cube[2];
		cube[2] = cube[4], cube[4] = cube[3], cube[3] = cube[5], cube[5] = v;
		return;
	}
	if (s == "y") {
		rotate(cube, "z");
		rotate(cube, "z");
		rotate(cube, "z");
		rotate(cube, "x");
		rotate(cube, "z");
		return;
	}
	rotate2(cube, s);
}

void test1() //输入所有操作,只显示最终结果
{
	vector<string>opts;
	string c;
	while (cin >> c)opts.push_back(c);
	auto cube = Init();
	for (auto c : opts) {
		rotate(cube, c);
	}
	show(cube);
}

void test2() //每次输入1个操作,实时显示结果
{
	auto cube = Init();
	string c;
	while (cin >> c) {
		rotate(cube, c);
		show(cube);
		cout << endl;
	}
}


string makeOpt(const string& opt, int num)
{
	if (num == 1)return opt;
	string s1 = opt;
	string s2 = std::to_string(num);
	if (s1.length() == 1)return s1 + s2;  //不带'
	//带'
	string s3, s4;
	s3 += s1[0], s4 += s1[1];
	return s3 + s2 + s4;
}

#define AnsAdd(s) ans += s;ans += " "; rotate(cube, s);
// F1-F9 是三阶魔方的公式
#define F1 AnsAdd("y'");AnsAdd("F");AnsAdd("R'");AnsAdd("F'");AnsAdd("y");AnsAdd("D");AnsAdd("D");AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块1 y' F R' F' y D D y' F R F' y
#define F2 AnsAdd("y'");AnsAdd("F");AnsAdd("R");AnsAdd("F'");AnsAdd("y");// 白色角块2 y' F R F' y
#define F3 AnsAdd("R'");AnsAdd("D");AnsAdd("R");// 白色角块3 R' D' R
#define F4 AnsAdd("U'");AnsAdd("L'");AnsAdd("U");AnsAdd("L");AnsAdd("U");AnsAdd("F");AnsAdd("U'");AnsAdd("F'");// 中层棱块1 U' L' U L U F U' F'
#define F5 AnsAdd("U");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");AnsAdd("U");AnsAdd("F");// 中层棱块2 U R U' R' U' F' U F
#define F6 AnsAdd("F");AnsAdd("R");AnsAdd("U");AnsAdd("R'");AnsAdd("U'");AnsAdd("F'");// 顶层十字 F R U R' U' F'
#define F7 AnsAdd("R'");AnsAdd("U'");AnsAdd("R");AnsAdd("U'");AnsAdd("R'");AnsAdd("U");AnsAdd("U");AnsAdd("R");      // 小鱼1 R' U' R U' R' U U R
#define F8 AnsAdd("F");AnsAdd("U");AnsAdd("F'");AnsAdd("U");AnsAdd("F");AnsAdd("U");AnsAdd("U");AnsAdd("F'"); // 小鱼2 F U F' U F U U F'
#define F9 AnsAdd("R");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B'");AnsAdd("R");AnsAdd("F");AnsAdd("F");AnsAdd("R'");AnsAdd("B");AnsAdd("R'"); // 换角 R R F F R' B' R F F R' B R'
//F10 单棱对换 R2 U U R2 U U R2' x' L2' U U L2 x' U U R2 U U R2'
#define F10_1(id)   AnsAdd(makeOpt("R",id+1));AnsAdd(makeOpt("R'",id)); //R2
#define F10_2(id)   AnsAdd(makeOpt("R'",id+1));AnsAdd(makeOpt("R",id)); //R2'
#define F10_3       AnsAdd("U");AnsAdd("U"); //U U
#define F10_4(id)   F10_3;F10_1(id);F10_3;F10_2(id); //U U R2 U U R2'
#define F10(id)     F10_1(id);F10_4(id);AnsAdd("x'");AnsAdd(makeOpt("L'",id+1));AnsAdd(makeOpt("L",id));F10_3;\
    AnsAdd(makeOpt("L",id+1));AnsAdd(makeOpt("L'",id));AnsAdd("x'");F10_4(id);
//F11 U位棱组翻转
#define F11 AnsAdd("U");AnsAdd("U");AnsAdd("B");AnsAdd("L");AnsAdd("U'");
//F12 棱块合并
#define F12(id) AnsAdd(makeOpt("F'",id)); AnsAdd("F"); AnsAdd("R"); AnsAdd("U'"); AnsAdd("R'"); AnsAdd("U"); AnsAdd(makeOpt("F",id));AnsAdd("F'");
//F13 双棱对换
#define F13_1 F10_3;AnsAdd("F");AnsAdd("F");
#define F13_2 AnsAdd("R2");F10_3;AnsAdd("R2'");
#define F13_3 F13_2;F13_1;F13_1;F13_1;F13_2;
#define F13 F13_3;AnsAdd("x'");F13_3;AnsAdd("x'");F13_3;
// U位R位棱组交叉
#define F14(id) F11;AnsAdd("z'");AnsAdd("x'");F12(id);AnsAdd("R'");AnsAdd("z'");AnsAdd("x'");AnsAdd("L'");AnsAdd("B");AnsAdd("D'");F12(id);
#define F15 AnsAdd("z'");AnsAdd("x'");F12(high);AnsAdd("x'");AnsAdd("F");AnsAdd("R'");AnsAdd("F'");AnsAdd("D");F12(high);AnsAdd("U'");\
	AnsAdd("x'");AnsAdd("U'");AnsAdd("B'");AnsAdd("D'");F12(high);
#define F16 AnsAdd("z'");AnsAdd("x'");F12(high);AnsAdd("F'");AnsAdd("U");AnsAdd("R");AnsAdd("R");AnsAdd("L");AnsAdd("D");AnsAdd("D");AnsAdd("F");F12(high);

string makeDir(vector<vector<vector<char>>>& cube) //调整白色面朝上
{
	string ans;
	int id = N / 2;
	if (cube[1][id][id] == 'W') {
		AnsAdd("x");
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[4][id][id] == 'W')break;
	}
	if (cube[0][id][id] != 'W') {
		AnsAdd("x");
	}
	return ans;
}

string makeCenterEdge(vector<vector<vector<char>>>& cube, int id)
{
	string ans; //待更新  对于N>5涉及
	return ans;
}

string makeCenterWithFunc(vector<vector<vector<char>>>& cube, int id, string(*func)(vector<vector<vector<char>>>&, int, char))
{
	string ans = makeDir(cube);
	AnsAdd("x");
	//前黄 后白
	ans += func(cube, id, 'W');
	AnsAdd("x'");
	//上白
	for (int i = 0; i < 4; i++) {
		ans += func(cube, id, 'W');
		AnsAdd("z");
	}
	AnsAdd("x");
	AnsAdd("x");
	//上黄
	for (int i = 0; i < 4; i++) {
		ans += func(cube, id, 'Y');
		AnsAdd("z");
	}
	for (int i = 0; i < 4; i++) {
		if (cube[4][N / 2][N / 2] == 'R')break;
		AnsAdd("z");
	}
	//上黄 前红
	AnsAdd("x");
	AnsAdd("z");
	//上红 前绿
	ans += func(cube, id, 'B');
	AnsAdd("x'");
	ans += func(cube, id, 'B');
	AnsAdd("z");
	AnsAdd("z");
	ans += func(cube, id, 'B');
	//至此,左黄 上蓝 右白 都完成了
	AnsAdd("x");
	AnsAdd("x");
	ans += func(cube, id, 'O');
	AnsAdd("x'");
	ans += func(cube, id, 'O');
	AnsAdd("x");
	ans += func(cube, id, 'G');
	return ans;
}
string makeCenterEdgeLocFtoU(vector<vector<vector<char>>>& cube, int id, char c)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("F");
		if (cube[4][N / 2][id] != c)continue;
		for (int i = 0; i < 4; i++) {
			if (cube[0][N / 2][id] == c)break;
			AnsAdd("U");
		}
		AnsAdd(makeOpt("L'", id + 1));
		for (int i = 0; i < 4; i++) {
			AnsAdd("U");
			if (cube[0][N / 2][id] != c)break;
		}
		AnsAdd(makeOpt("L", id + 1));
	}
	return ans;
}
string makeCenterEdgeLoc(vector<vector<vector<char>>>& cube, int id)
{
	return makeCenterWithFunc(cube, id, makeCenterEdgeLocFtoU);
}
string makeCenterCornerLocFtoU(vector<vector<vector<char>>>& cube, int id, char c)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("F");
		if (cube[4][id][id] != c)continue;
		for (int i = 0; i < 4; i++) {
			AnsAdd("U");
			if (cube[0][N - 1 - id][id] != c)break;
		}
		AnsAdd(makeOpt("L'", id + 1));
		AnsAdd("U'");
		AnsAdd(makeOpt("L", id + 1));
		AnsAdd("U'");
		AnsAdd(makeOpt("L'", id + 1));
		AnsAdd("U");
		AnsAdd("U");
		AnsAdd(makeOpt("L", id + 1));
	}
	return ans;
}
string makeCenterCornerLoc(vector<vector<vector<char>>>& cube, int id)
{
	return makeCenterWithFunc(cube, id, makeCenterCornerLocFtoU);
}

string makeCenterId(vector<vector<vector<char>>>& cube, int id)
{
	string ans = makeCenterEdge(cube, id);
	ans += makeCenterEdgeLoc(cube, id);
	ans += makeCenterCornerLoc(cube, id);
	return ans;
}

string makeAllCenterCenter(vector<vector<vector<char>>>& cube)
{
	if (N % 2)return "";
	return makeCenterWithFunc(cube, N / 2 - 1, makeCenterCornerLocFtoU);
}

string makeAllCenter(vector<vector<vector<char>>>& cube)
{
	string ans = makeAllCenterCenter(cube);
	for (int i = (N - 3) / 2; i > 0; i--) { //中心大正方形逐步扩圈
		ans += makeCenterId(cube, i);
	}
	return ans;
}

int getId(char a, char b)
{
	vector<string> v{ "RW", "BW", "OW", "GW", "OY", "BY", "RY", "GY", "OG", "OB", "RB", "RG" };
	for (int i = 0; i < 12; i++) {
		if (v[i][0] == a && v[i][1] == b)return i;
	}
	return getId(b, a) + 12;
}

template<typename T>
int getInvertNum(vector<T>v)
{
	int n = 0;
	for (int i = 0; i < v.size(); i++) {
		for (int j = i + 1; j < v.size(); j++) {
			if (v[i] > v[j])n++;
		}
	}
	return n;
}


#define ForEachEdgeUp(func) func;rotate(cube, "U");func;rotate(cube, "U");func;rotate(cube, "U");func;
#define ForEachEdgeLR(func) rotate(cube, "F");func;rotate(cube, "F");rotate(cube, "F");func;
// 依次把12个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdge(func) ForEachEdgeUp(func);rotate(cube, "x");rotate(cube, "x");ForEachEdgeUp(func);\
	ForEachEdgeLR(func);rotate(cube, "z");rotate(cube, "z");ForEachEdgeLR(func);
#define GetTwoEdgeId v.push_back(getId(cube[4][0][id], cube[0][N - 1][id]));v.push_back(getId(cube[0][N - 1][N - 1 - id], cube[4][0][N - 1 - id]));

bool checkEdgeLocStatus(vector<vector<vector<char>>> cube, int id) //check***系列函数中,少有的非const&的cube参数,这里不要用&
{
	vector<int>v;
	ForEachEdge(GetTwoEdgeId);
	return getInvertNum(v) % 2 == 0;
}

string makeEdgeLocStatus(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 1; i < N / 2; i++) {
		if (!checkEdgeLocStatus(cube, i)) {
			F10(i);//交换2个棱块
		}
	}
	return ans;
}

#define ForEachEdgeUp2(func) func;AnsAdd("U");func;AnsAdd("U");func;AnsAdd("U");func;
#define ForEachEdgeLR2(func) AnsAdd("F");func;AnsAdd("F");AnsAdd("F");func;
// 依次把12个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdge2(func) ForEachEdgeUp2(func);AnsAdd( "x");AnsAdd( "x");ForEachEdgeUp2(func);\
	ForEachEdgeLR2(func);AnsAdd( "z");AnsAdd( "z");ForEachEdgeLR2(func);
// 依次把10个棱组挪到cube[4][0][1]所在的位置
#define ForEachEdgeExceptLR(func) ForEachEdgeUp2(func);AnsAdd( "B");AnsAdd( "U");AnsAdd( "B");AnsAdd( "U");AnsAdd( "B");AnsAdd( "U");\
    AnsAdd( "D");AnsAdd( "B");AnsAdd( "B");	ForEachEdgeUp2(func);AnsAdd( "D");AnsAdd( "B");AnsAdd( "D");AnsAdd( "B");AnsAdd( "U");\
    AnsAdd( "B");AnsAdd( "U");func;AnsAdd( "U");func;

#define case1 (cube[0][N - 1][mid] == target[0] && cube[4][0][mid] == target[1])
#define case2 (cube[0][N - 1][mid] == target[1] && cube[4][0][mid] == target[0])
#define case3 (cube[0][N - 1][high] == target[0] && cube[4][0][high] == target[1])
#define case4 (cube[0][N - 1][high] == target[1] && cube[4][0][high] == target[0])
#define FindEdgeWithTarget  if (case1||case2||((N%2==0 && high==mid+1)&&(case3||case4)))goto here1;
#define FindEdgeWithDif(h) if (cube[0][N - 1][mid] != cube[0][N - 1][high] || cube[4][0][mid] !=cube[4][0][high] || \
	cube[0][N - 1][mid] != cube[0][N - 1][low] || cube[4][0][mid] != cube[4][0][low])goto h;


int checkFinishEdgeNum(vector<vector<vector<char>>> cube, int low, int mid, int high)//check***系列函数中,少有的非const&的cube参数,这里不要用&
{
	int num = 0;
	ForEachEdge(if (cube[4][0][high] == cube[4][0][mid] && cube[0][N - 1][high] == cube[0][N - 1][mid] &&
		cube[4][0][low] == cube[4][0][mid] && cube[0][N - 1][low] == cube[0][N - 1][mid])num++;);
	return num;
}

string makeEdge1(vector<vector<vector<char>>>& cube, int low, int mid, int high)
{
	string ans;
	//checkFinishEdgeNum<10, 正面U位棱组mid和high不属于同一棱组
	string target;
	target += cube[0][N - 1][high];
	target += cube[4][0][high];
	char c1 = cube[0][N - 1][mid], c2 = cube[4][0][mid];
	AnsAdd("F");//high处是target的棱组停留在正面R位
	FindEdgeWithTarget;
	AnsAdd("U");
	AnsAdd("L");//一个mid/high处不是target的棱组停留在正面L位
	ForEachEdgeExceptLR(FindEdgeWithTarget);
here1:
	//mid/high处是target的棱组停留在正面U位
	if (cube[0][N - 1][mid] == target[1] && cube[4][0][mid] == target[0]) {
		F11;
	}
	if (N % 2 == 0 && high == mid + 1 && cube[0][N - 1][high] == target[1] && cube[4][0][high] == target[0]) {
		F11;
	}
	//此时,正面U位棱组mid处和正面R位棱组high处属于同一棱组,且方向一致
	AnsAdd("U");
	AnsAdd("L");//mid处是target的棱组停留在正面L位
	ForEachEdgeExceptLR(FindEdgeWithDif(here2));
here2:
	//带dif的棱组停留在正面U位
	if (cube[0][N - 1][mid] == cube[0][N - 1][low] && cube[4][0][mid] == cube[4][0][low]) {
		F11;
		AnsAdd("L'");
	}
	//正面U位棱组mid处和high处不属于同一棱组
	AnsAdd("R");
	AnsAdd("R");
	AnsAdd("B");
	AnsAdd("U'");
	AnsAdd("R");
	AnsAdd("B");
	AnsAdd("B");
	AnsAdd("z");
	AnsAdd("z");
	AnsAdd("x'");
	F12(high);
	return ans;
}
string makeEdge2(vector<vector<vector<char>>>& cube, int low, int mid, int high)
{
	string ans;
	//checkFinishEdgeNum<10, 所有棱组的low、mid和high都属于同一棱组,但是有2k(k>=2)个棱组都存在2个棱块互换,且其中一个就在正面U位
	AnsAdd("F"); //R位
	ForEachEdgeExceptLR(if (cube[0][N - 1][mid] != cube[0][N - 1][high])goto here3;);//U位
here3:
	AnsAdd("U");
	AnsAdd("L");//L位
here4:
	ForEachEdgeExceptLR(if (cube[0][N - 1][mid] != cube[0][N - 1][high])goto here4;);//U位
	AnsAdd("z'");
	AnsAdd("x'");
	F12(high);
	return ans;
}

#define InSame(a, b, c, d) (a == c || a == d) && (b == c || b == d)

string makeAllEdgeLast(vector<vector<vector<char>>>& cube, int low, int mid, int high)
{
	string ans;
	//2个棱组有问题
	ForEachEdge2(FindEdgeWithDif(here6));
here6:
	//U位棱组有问题
	AnsAdd("F"); //R位
	FindEdgeWithDif(here7);
	AnsAdd("U");
	AnsAdd("L");
	ForEachEdgeExceptLR(FindEdgeWithDif(here7));
here7:
	//U位和R位棱组有问题
	if (high == low + 1) {
		// U位R位棱组交叉
		F14(high);
		return ans;
	}
	bool flag1 = InSame(cube[0][N - 1][low], cube[4][0][low], cube[0][N - 1][mid], cube[4][0][mid]);
	bool flag2 = InSame(cube[0][N - 1][high], cube[4][0][high], cube[0][N - 1][mid], cube[4][0][mid]);
	if (flag1 && flag2) {
		// case1
		F15;
		return ans;
	}
	if (flag1 || flag2) {
		//case3
		bool flag3 = cube[0][N - 1][low] == cube[0][N - 1][mid] && cube[4][0][low] == cube[4][0][mid];
		bool flag4 = cube[0][N - 1][high] == cube[0][N - 1][mid] && cube[4][0][high] == cube[4][0][mid];
		if (flag3 || flag4) {
			AnsAdd("R");
			AnsAdd("F");
			AnsAdd("U");
		}
		AnsAdd("R");
		AnsAdd("F");
		AnsAdd("U");
		flag4 = cube[0][N - 1][high] == cube[0][N - 1][mid] && cube[4][0][high] == cube[4][0][mid];
		if (flag4) {
			F11;
		}
		AnsAdd("y'");
		flag1 = InSame(cube[0][N - 1][low], cube[4][0][low], cube[0][N - 1][mid], cube[4][0][mid]);
		if (flag1) {
			F11;
			AnsAdd("L'");
		}
		AnsAdd("z'");
		F12(high);
		return ans;
	}
	//case2
	char c1 = cube[0][N - 1][low];
	AnsAdd("F'");
	char c2 = cube[0][N - 1][mid];
	AnsAdd("F");
	if (c1 != c2) {
		F11;
	}
	F16;
	return ans;
}
string makeAllEdgeOnce(vector<vector<vector<char>>>& cube, int low, int mid, int high)
{
	if (checkFinishEdgeNum(cube, low, mid, high) == 10)return makeAllEdgeLast(cube, low, mid, high);
	string ans;
	bool flag = false;
	ForEachEdge2(if (cube[4][0][high] != cube[4][0][mid] && cube[4][0][high] != cube[0][N - 1][mid]) { flag = true; goto here5; }
	if (cube[0][N - 1][high] != cube[4][0][mid] && cube[0][N - 1][high] != cube[0][N - 1][mid]) { flag = true; goto here5; }
	if (cube[4][0][low] != cube[4][0][mid] && cube[4][0][low] != cube[0][N - 1][mid]) { flag = true; goto here5; }
	if (cube[0][N - 1][low] != cube[4][0][mid] && cube[0][N - 1][low] != cube[0][N - 1][mid]) { flag = true; goto here5; })
here5:
	if (flag) {
		if (cube[4][0][low] != cube[4][0][mid] && cube[4][0][low] != cube[0][N - 1][mid]) {
			F11;
		}
		else if (cube[0][N - 1][low] != cube[4][0][mid] && cube[0][N - 1][low] != cube[0][N - 1][mid]) {
			F11;
		}
		//此时,正面U位棱组一定满足,mid和high不属于同一棱组
		ans += makeEdge1(cube, low, mid, high);
	}
	else {
		//此时,所有棱组的low、mid和high都属于同一棱组,但是有2k(k>=2)个棱组都存在2个棱块互换,且其中一个就在正面U位
		ans += makeEdge2(cube, low, mid, high);
	}
	return ans;
}

//难点在于精确定义用什么量作为无穷递降法的依据,所有情况都要考虑到,否则就会出现低概率无限循环
//我这套方案是基于二元组,第一顺位是提高checkFinishEdgeNum,checkFinishEdgeNum不变的情况下是提高mid=high的配对数
string makeAllEdge(vector<vector<vector<char>>>& cube)
{
	string ans;
	int mid = (N - 1) / 2;
	for (int i = N / 2 - 1; i > 0; i--) { //棱块从内往外扩
		int id = N - 1 - i; // i <= mid < id, mid是基准,i和id是一对
		while (true) {
			auto num = checkFinishEdgeNum(cube, i, mid, id);
			if (num == 12)break;
			ans += makeAllEdgeOnce(cube, i, mid, id); //一般每次调用makeAllEdgeOnce二元组都会进步,保证每次都不能退步,且不会连续2次原地踏步
		}
	}
	return ans;
}

string makeUUUU(vector<vector<vector<char>>>& cube) //白色层方向回正
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][N - 1][1] == 'W' && cube[4][0][1] == 'R') {
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][1][N - 1] == 'W' && cube[3][0][1] == 'B') {
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][1][0] == 'W' && cube[2][0][1] == 'G') {
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[0][0][1] == 'W' && cube[5][0][1] == 'O') {
			return ans;
		}
	}
	return ans;
}

bool checkWhiteCross(const vector<vector<vector<char>>>& cube)// 检查白色十字是否完成
{
	char whiteColor = 'W';
	if (cube[0][0][1] != whiteColor || cube[0][N - 1][1] != whiteColor || cube[0][1][0] != whiteColor || cube[0][1][N - 1] != whiteColor) {
		return false;
	}
	if (cube[2][0][1] != 'G' || cube[3][0][1] != 'B' || cube[4][0][1] != 'R') {
		return false;
	}
	return true;
}

string makeWhiteCrossOnce(vector<vector<vector<char>>>& cube)
{
	string ans = "";
	for (int i = 0; i < 4; i++) {
		AnsAdd("D");
		if (cube[4][N - 1][1] == 'W') {
			ans += makeUUUU(cube);
			char c = cube[1][N - 1][1];
			if (c == 'B') {
				AnsAdd("U");
			}
			if (c == 'O') {
				AnsAdd("U");
				AnsAdd("U");
			}
			if (c == 'G') {
				AnsAdd("U'");
			}
			AnsAdd("F'");
			AnsAdd("U'");
			AnsAdd("R");
			return ans;
		}
		if (cube[1][N - 1][1] == 'W') {
			ans += makeUUUU(cube);
			char c = cube[4][N - 1][1];
			if (c == 'B') {
				AnsAdd("U");
			}
			if (c == 'O') {
				AnsAdd("U");
				AnsAdd("U");
			}
			if (c == 'G') {
				AnsAdd("U'");
			}
			AnsAdd("F");
			AnsAdd("F");
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[4][1][N - 1] == 'W' || cube[3][1][0] == 'W') {
			while (cube[0][N - 1][1] == 'W') {
				AnsAdd("U");
			}
			AnsAdd("F");
			return ans;
		}
	}
	ans += makeUUUU(cube);
	string s = "BOGR";
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[0][N - 1][1] != 'W' || cube[4][0][1] != s[i]) {
			AnsAdd("F");
			AnsAdd("F");
			return ans;
		}
	}
	return ans;
}

string makeWhiteCross(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (true) {
		ans += makeDir(cube);
		ans += makeUUUU(cube);
		if (checkWhiteCross(cube))break;
		ans += makeWhiteCrossOnce(cube);
	}
	return ans;
}

bool checkWhite(const vector<vector<vector<char>>>& cube)// 检查白色是否完成
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][0][0] != cube[i][0][1] || cube[i][0][N - 1] != cube[i][0][1])return false;
	}
	return true;
}
string makeWhiteOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("D");
		ans += makeUUUU(cube);
		string t;
		t += cube[1][N - 1][N - 1];
		t += cube[3][N - 1][0];
		t += cube[4][N - 1][N - 1];
		sort(t.begin(), t.end());
		if (t == "BOW") {
			AnsAdd("U");
		}
		if (t == "GOW") {
			AnsAdd("U");
			AnsAdd("U");
		}
		if (t == "GRW") {
			AnsAdd("U");
			AnsAdd("U");
			AnsAdd("U");
		}
		if (cube[1][N - 1][N - 1] == 'W') {
			F1;
			return ans;
		}
		if (cube[4][N - 1][N - 1] == 'W') {
			F2;
			return ans;
		}
		if (cube[3][N - 1][0] == 'W') {
			F3;
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[4][0][N - 1] != cube[4][0][1] || cube[3][0][0] != cube[3][0][1]) {
			F2;
			return ans;
		}
	}
	return ans;
}
string makeWhite(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (true) {
		ans += makeDir(cube);
		if (checkWhite(cube))break;
		ans += makeWhiteOnce(cube);
	}
	return ans;
}

bool checkMid(const vector<vector<vector<char>>>& cube)
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][1][0] != cube[i][1][1] || cube[i][1][N - 1] != cube[i][1][1])return false;
	}
	return true;
}
string makeMidOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		string t;
		t += cube[0][N - 1][1];
		t += cube[4][0][1];
		if (t[0] != 'Y' && t[1] != 'Y') {
			while (cube[4][0][1] != cube[4][1][1]) {
				AnsAdd("z");
				AnsAdd("U'");
			}
			if (t == "BR" || t == "RG" || t == "GO" || t == "OB") {
				F4;
			}
			else {
				F5;
			}
			return ans;
		}
	}
	for (int i = 0; i < 4; i++) {
		AnsAdd("z");
		if (cube[4][1][0] != cube[4][1][1]) {
			F4;
		}
		else if (cube[4][1][N - 1] != cube[4][1][1]) {
			F5;
		}
	}
	return ans;
}
string makeMid(vector<vector<vector<char>>>& cube)
{
	string ans = makeDir(cube) + " ";
	ans += makeUUUU(cube);
	AnsAdd("y");
	AnsAdd("y");
	//从此,白色在下面,不能再调用makeDir和makeUUUU!!!!
	while (true) {
		if (checkMid(cube))break;
		ans += makeMidOnce(cube);
	}
	return ans;
}

bool checkTopCross(const vector<vector<vector<char>>>& cube)
{
	int num = 0;
	if (cube[0][0][1] == 'Y')num++;
	if (cube[0][N - 1][1] == 'Y')num++;
	if (cube[0][1][0] == 'Y')num++;
	if (cube[0][1][N - 1] == 'Y')num++;
	return num == 4;
}
string makeTopCrossOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	int num = 0;
	if (cube[0][0][1] == 'Y')num++;
	if (cube[0][N - 1][1] == 'Y')num++;
	if (cube[0][1][0] == 'Y')num++;
	if (cube[0][1][N - 1] == 'Y')num++;
	if (num == 2) {
		while (cube[0][1][0] != 'Y') {
			AnsAdd("U");
		}
		if (cube[0][N - 1][1] == 'Y') {
			AnsAdd("U");
		}
	}
	F6;
	return ans;
}
string makeTopCross(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCross(cube)) {
		ans += makeTopCrossOnce(cube);
	}
	return ans;
}

bool checkTopDir(const vector<vector<vector<char>>>& cube)
{
	int num = 0;
	if (cube[0][0][0] == 'Y') num++;
	if (cube[0][0][N - 1] == 'Y') num++;
	if (cube[0][N - 1][0] == 'Y') num++;
	if (cube[0][N - 1][N - 1] == 'Y') num++;
	return num == 4;
}

string makeTopDirOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	int num = 0;
	if (cube[0][0][0] == 'Y') num++;
	if (cube[0][0][N - 1] == 'Y') num++;
	if (cube[0][N - 1][0] == 'Y') num++;
	if (cube[0][N - 1][N - 1] == 'Y') num++;
	if (num == 0) {
		while (cube[2][0][0] != 'Y') {
			AnsAdd("U");
		}
		F7;
		return ans;
	}
	if (num == 2) {
		while (cube[5][0][N - 1] != 'Y') {
			AnsAdd("U");
		}
		F7;
		return ans;
	}
	while (cube[0][0][0] != 'Y') {
		AnsAdd("U");
	}
	if (cube[4][0][0] == 'Y') {
		F7;
		return ans;
	}
	F8;
	return ans;
}
string makeTopDir(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopDir(cube)) {
		ans += makeTopDirOnce(cube);
	}
	return ans;
}

bool checkTopCornerLoc(const vector<vector<vector<char>>>& cube)
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][0][0] != cube[i][0][N - 1])return false;
	}
	return true;
}

string makeTopCornerLocOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[3][0][0] == cube[3][0][N - 1])break;
	}
	F9;
	return ans;
}
string makeTopCornerLoc(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopCornerLoc(cube)) {
		ans += makeTopCornerLocOnce(cube);
	}
	return ans;
}

string makeChangeEdge(vector<vector<vector<char>>>& cube, bool& changed)
{
	string ans;
	changed = false;
	//方向回正
	while (cube[4][1][1] != 'O') {
		AnsAdd("z");
	}
	while (cube[4][0][0] != cube[4][1][0]) {
		AnsAdd("U");
	}
	vector<char>v;
	for (int i = 2; i <= 5; i++) {
		v.push_back(cube[i][0][1]);
	}
	// 复原是GBOR
	if (getInvertNum(v) % 2 == 0) {
		F13;
		changed = true;
	}
	return ans;
}

bool checkTopEdgeLoc(const vector<vector<vector<char>>>& cube)
{
	for (int i = 2; i <= 5; i++) {
		if (cube[i][0][0] != cube[i][0][1])return false;
	}
	return true;
}
string makeTopEdgeLocOnce(vector<vector<vector<char>>>& cube)
{
	string ans;
	for (int i = 0; i < 4; i++) {
		AnsAdd("U");
		if (cube[4][0][0] == cube[4][0][1])break;
	}
	F7;
	AnsAdd("z");
	AnsAdd("z");
	F8;
	return ans;
}
string makeTopEdgeLoc(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (!checkTopEdgeLoc(cube)) {
		ans += makeTopEdgeLocOnce(cube);
	}
	return ans;
}

string makeAll(vector<vector<vector<char>>>& cube)
{
	string ans;
	while (cube[4][0][0] != cube[4][1][0]) {
		AnsAdd("U");
	}
	while (cube[4][N - 1][0] != cube[4][1][0]) {
		AnsAdd("D");
	}
	return ans;
}

string autoRunOpts(vector<vector<vector<char>>>& cube)
{
	string ans = makeAllCenter(cube); //中心大正方形合并
	ans += makeEdgeLocStatus(cube); //棱块位置奇偶性
	ans += makeAllEdge(cube); //棱块合并
	ans += makeWhiteCross(cube); //白色十字
	ans += makeWhite(cube);//白色
	ans += makeMid(cube);//中间层
	ans += makeTopCross(cube);//顶层十字
	ans += makeTopDir(cube);//顶层朝向
	ans += makeTopCornerLoc(cube);	//角块归位
	bool changed;
	ans += makeChangeEdge(cube, changed);//双棱对换
	if (changed) {
		ans += makeWhiteCross(cube); //白色十字
		ans += makeWhite(cube);//白色
		ans += makeMid(cube);//中间层
		ans += makeTopCross(cube);//顶层十字
		ans += makeTopDir(cube);//顶层朝向
		ans += makeTopCornerLoc(cube);	//角块归位
	}
	ans += makeTopEdgeLoc(cube);//棱组归位
	ans += makeAll(cube);//复原
	return ans;
}

bool replaceStr(std::string& str, const std::string& from, const std::string& to)
{
	size_t pos = 0;
	if ((pos = str.find(from, pos)) != std::string::npos) {
		str.replace(pos, from.length(), to);
		return true;
	}
	return false;
}

bool replaceAns(string& ans)
{
	bool ret = false;
	for (char c : {'U', 'D', 'L', 'R', 'F', 'B', 'x', 'y', 'z'})
	{
		string s1 = "";
		s1 += c;
		s1 += "' ";
		s1 += c;
		s1 += " ";
		string s2 = " ";
		ret = ret || replaceStr(ans, s1, s2);
		s1 = "";
		s1 += c;
		s1 += " ";
		s1 += c;
		s1 += "' ";
		ret = ret || replaceStr(ans, s1, s2);
		s1 = "";
		s1 += c;
		s1 += " ";
		s1 += c;
		s1 += " ";
		s1 += c;
		s1 += " ";
		s2 = "";
		s2 += c;
		s2 += "' ";
		ret = ret || replaceStr(ans, s1, s2);
		s1 = "";
		s1 += c;
		s1 += "' ";
		s1 += c;
		s1 += "' ";
		s1 += c;
		s1 += "' ";
		s2 = "";
		s2 += c;
		s2 += " ";
		ret = ret || replaceStr(ans, s1, s2);
		s1 = "  ";
		s2 = " ";
		ret = ret || replaceStr(ans, s1, s2);
	}
	return ret;
}

void atuoRun(vector<string>& lines)
{
	vector<vector<vector<char>>>cube;
	for (int i = 0; i < 6; i++) {
		string s = lines[i].substr(3, lines[i].length() - 3);
		vector<vector<char>>v(N, vector<char>(N));
		for (int i = 0; i < N; i++)for (int j = 0; j < N; j++)v[i][j] = s[i * N + j];
		cube.push_back(v);
	}
	string ans = autoRunOpts(cube);
	while (replaceAns(ans));
	std::ofstream outFile("D:/cubeOutput.txt", std::ios::app);
	if (outFile.is_open()) {
		outFile << ans << "\n";
		outFile.close();
	}
}

// 读取文件的所有行,每一行存入一个 string
std::vector<std::string> readAllLines(const std::string& path) {
	std::vector<std::string> lines;
	std::ifstream in(path);
	if (!in.is_open()) {
		return lines;  // 打开失败,返回空
	}

	std::string line;
	while (std::getline(in, line)) {
		lines.push_back(line);   // 每行一个 string 对象
	}
	return lines;
}

// 判断文件内容是否不为空
bool fileHasContent(const std::string& path) {
	std::error_code ec;

	// 1. 文件必须存在
	if (!fs::exists(path, ec) || ec) {
		return false;
	}

	// 2. 文件大小必须大于 0
	if (fs::file_size(path, ec) == 0 || ec) {
		return false;
	}

	return true;
}

void run1() // 自动填写操作序列
{
	const std::string filePath = "D:/cubeInput.txt";
	while (true) {
		if (fileHasContent(filePath)) {
			// 内容不为空,读取所有行
			std::vector<std::string> lines = readAllLines(filePath);
			atuoRun(lines);
			std::ofstream clear(filePath, std::ios::trunc);
		}
		// 每隔 500ms 检查一次,避免忙等占用 CPU
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
	}
}

int main()
{
	N = 5;
	//test1(); //输入所有操作,只显示最终结果
	// test2(); //每次输入1个操作,实时显示结果
	run1(); // 自动填写操作序列
	return 0;
}
 

4,case覆盖

对于makeAllEdgeLast里面的U位R位棱组交叉、case1、case2、case3做白盒覆盖:

U位R位棱组交叉对于N=5测不了,只有N是偶数涉及。

case1+case3:

 x x z z x z x' z z x x z x' z' x z x' z z x x U F U L U' B U B U B U D B B U U z' x' F3' F R U' R' U F3 F' x' F R' F' D F3' F R U' R' U F3 F' U' x' U' B' D' F3' F R U' R' U F3 U L U' B U B U B U D B B U U R F U R F U y' z' F3' F R U' R' U F3 U L U U B L L U' B U B U B U D B B U U R R B U' R B B z z x' F3' F R U' R' U F3 F' x x U D U' F' U' R U D D U' F F U z' U U F U' F' U' R U U z' U F U' F' U' R U z' U R z F F U F F U' F F y' F R F' y D U' D D U' R' D R D U D U' y' F R F' y D U D' U R' D R D U' D U y' F R F' y D U' D' U U y' F R F' y D U U D D y' F R' F' y D D y' F R F' y U U R' D R D U U D U U y' F R F' y U U y y U' R U' R' U' F' U F U z U' z U' U' L' U L U F U' F' U R U' R' U' F' U F U U z U' z U' U' L' U L U F U' R U R' U' F' U U F R U R' U' R U R' U' F' U F U F' U F U U F' R R F F R' B' R F F R' B R' U R R F F R' B' R F F R' B R' z z U R' U' R U' R' U U R z z F U F' U F U U F' 
 

case2:

U' x x U F U L U' B U B U B U D B B U B L U' z' x' F3' F R U' R' U F3 F' F' U R R L D D F F3' F R U' R' U F3 U L U' B U B U B U D B' L L U' B U B U B U D B B U' R R B U' R B B z z x' F3' F R U' R' U F3 F' x U F F U z F' U' D U R' D R D U y' F R' F' y D D y' F R F' y D U U D U y' F R F' y D U' D' U' y' F R F' y D U D D y' F R' F' y D D y' F R F' y U' y' F R' F' y D D y' F R F' y U y y U z R U' R' U' F' U F z U' z U' z R U' R' U' F' U F z z U R U' R' U' F' U F z z U' L' U L U F U' F' U U z U' z U' z U' U' L' U L U F U' F' z U' L' U L U F U' F' z' U R U' R' U' F' U F z U' U' L' U L U F U' R U R' U' F' U U F R U R' U' R U R' U' F' U U R' U' R U' R' U U R U' R' U' R U' R' U U R U R R F F R' B' R F F R' B R' z z U R' U' R U' R' U U R z z F U F' U F U U F' U U R' U' R U' R' U U R z z F U F' U F U U F' U' 
 

PS:不太好的一点是,代码稍微改一点,就得重新生成用例。

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值