#include <iostream>
#include <algorithm>
#include <stdint.h>
#include <string>
#include <tuple>
#include <map>
#include <vector>
#include <functional>
//var 0.03a
enum class Op {
	None,
	Add,
	Sub,
};

typedef std::map<char, std::uint32_t> Dic;
typedef std::tuple<std::string, std::string, std::string, Op> Data;
typedef std::vector<std::uint32_t> iVec;
typedef std::vector<std::tuple<std::uint32_t, std::uint32_t, std::uint32_t,Op,Dic>> RType;

std::int32_t MakeNumber(std::string S, Dic& D) {
	std::int32_t R = 0;

	for (auto& o : S) {
		R *= 10;
		R += D[o];
	}

	return R;
}

std::uint32_t CountDigit(std::uint32_t N) {
	std::uint32_t c = 0;

	while (N != 0) {
		N /= 10;
		c++;
	}
	return c;
}

RType MakeHoge(const Data& D){
	std::string A;
	std::string B;
	std::string C;
	Op op = Op::None;
	Dic Di;
	iVec v{ 0,1,2,3,4,5,6,7,8,9 };
	std::size_t i = 0;
	bool F=false;
	RType R;

	std::int32_t a = 0;
	std::int32_t b = 0;
	std::int32_t c = 0;

	std::tie(A, B, C, op) = D;
	for (auto& o : A) {
		Di[o] = 0;
	}
	for (auto& o : B) {
		Di[o] = 0;
	}
	for (auto& o : C) {
		Di[o] = 0;
	}
	do {
	for (auto& o : Di) {
		o.second = v[i];
		i++;
	}
	i = 0;
	a = MakeNumber(A, Di);
	b = MakeNumber(B, Di);
	c = MakeNumber(C, Di);

	switch (op)
	{
		case Op::Add:
			F = (a + b == c);
			break;
		case Op::Sub:
			F = (a - b == c);
			break;

		default:
			std::cout << "unknown op prametor" << std::endl;
			return{};
			break;
	}
	if (F == true) {
		R.push_back(std::make_tuple(a, b, c, op,Di));
	}
	} while (std::next_permutation(v.begin(), v.end()));

	return R;
}

bool Show(std::string A, std::string B, std::string C, RType& R) {
	std::int32_t a;
	std::int32_t b;	
	std::int32_t c;
	Op op = Op::None;
	Dic D;

	R.erase(std::unique(R.begin(), R.end()),R.end());

	for (auto& o : R) {
		std::tie(a, b, c, op,D) = o;

		if (A.size() != CountDigit(a)) continue;
		if (B.size() != CountDigit(b)) continue;
		if (C.size() != CountDigit(c)) continue;


		std::cout << A;
		switch (op)
		{
			case Op::Add:
			std::cout << " + ";
			break;
			case Op::Sub:
			std::cout << " - ";
			break;
		default:
			std::cout << " ? ";
			break;
		}

		std::cout << B;

		std::cout <<" = "<< C << std::endl;
		std::cout << a;
		switch (op)
		{
			case Op::Add:
			std::cout << " + ";
			break;
			case Op::Sub:
			std::cout << " - ";
			break;
		default:
			std::cout << " ? ";
			break;
		}

		std::cout << b;

		std::cout <<" = "<< c << std::endl;
		for (auto&o : D) {
			std::cout << o.first << '[' << static_cast<int>(o.second) << ']';
		}
		std::cout << std::endl<< std::endl;
	}

	return true;
}

int main() {

	std::string A;
	std::string B;
	std::string C;
	Op op = Op::None;
	RType R;

	A = "SEND";
	B = "MORE";
	C = "MONEY";

	R = MakeHoge(std::make_tuple(A, B, C, Op::Add));
	Show(A, B, C, R);

	A = "WWWDOT";
	B = "GOOGLE";
	C = "DOTCOM";

	R = MakeHoge(std::make_tuple(A, B, C, Op::Sub));
	Show(A, B, C, R);
	return 0;

}