#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <map>
#include <tuple>

struct Item{
	virtual char GetToken()=0;
};
struct Num :public Item {
	int N;
	Num(int N_){
		N = N_;
	}
	char GetToken(){
		return 'N';
	}
};
struct Token :public Item {
	char C;
	Token(char C_){
		C = C_;
	}
	char GetToken(){
		return C;
	}
};

struct bunsuu :public Item {
public:
	int C,M;

	bunsuu(int C_, int M_){
		C = C_;
		M = M_;
	}

	char GetToken(){
		return ':';
	}

};
typedef std::shared_ptr<Item> IType;
typedef std::vector<IType> MType;
typedef std::tuple<MType, MType> PType;


int ToNumber(wchar_t C){
	std::map<wchar_t, int> m{ { L'０', 0 }, { L'１', 1 }, { L'２', 2 }, { L'３', 3 }, { L'４', 4 }, { L'５', 5 }, { L'６', 6 }, { L'７', 7 }, { L'８', 8 }, { L'９', 9 }, };

	return m[C];
}
char ToToken(wchar_t C){
	std::map<wchar_t, char> m{ { L'／', ':' }, { L'÷', '/' }, { L'＋', '+' }, { L'－', '-' }, { L'×', '*' }, { L'＊', '*' }};//分数記号はなんかいい案無いだろうか。
	
	return m[C];
}
bool IsNumber(wchar_t C){
	std::map<wchar_t, bool> m{ { L'０', true }, { L'１', true }, { L'２', true }, { L'３', true }, { L'４', true }, { L'５', true }, { L'６', true }, { L'７', true }, { L'８', true }, { L'９', true }, };

	return m[C];
}
bool IsToken(wchar_t C){
	std::map<wchar_t, bool> m{ { L'／', true }, { L'÷', true }, { L'＋', true }, { L'－', true }, { L'×', true }, { L'＊', true }};

	return m[C];
}

MType MakeSiki(std::wstring& s){
	MType R;
	std::shared_ptr<Item> I;
	for (std::size_t i = 0; i < s.length(); i++){
		switch (s[i])
		{
			case L'１':
			case L'２':	
			case L'３':
			case L'４':
			case L'５':	
			case L'６':
			case L'７':
			case L'８':	
			case L'９':
				R.push_back(std::make_shared<Num>(ToNumber(s[i])));
				break;
			case L'＋':
			case L'－':	
			case L'＊':
			case L'×':
			case L'÷':
				R.push_back(std::make_shared<Token>(ToToken(s[i])));
				break;
			case L'／':
				I = R.back();
				R.pop_back();
				R.push_back(std::make_shared<bunsuu>(static_cast<Num*>(&(*I))->N, ToNumber(s[i + 1])));
				i++;
				break;
			default:
				break;
		}
	}
	return R;
}

PType SepSiki(MType& s){
	MType N;
	MType T;
	for (auto&o : s){
		switch (o->GetToken())
		{
			case ':':
			case 'N':
				N.push_back(o);
				break;
			case '+':
			case '-':
			case '*':
			case '/':
				T.push_back(o);
				break;
			default:
				break;
		}
	}

	return std::make_tuple(N, T);
}

IType CalcOne(int A, int B,char o){
	switch (o)
	{
		case '+':
			return std::make_shared<Num>(A + B);
		case '-':
			return std::make_shared<Num>(A - B);
		case '*':
			return std::make_shared<Num>(A * B);
		case '/':
			return std::make_shared<bunsuu>(A , B);
		
		default:
			break;
	}
	return std::make_shared<Num>(0);
}
IType CalcOne(bunsuu A, bunsuu B,char o){
	bunsuu C(1,1);
	bunsuu D(A.C*B.M, A.M*B.M);//GCDが無いとオーバーフローする。
	bunsuu E(B.C*A.M, B.M*A.M);
	switch (o)
	{
		case '+':
			C.M = D.M;
			C.C = D.C+E.C;
			break;
		case '-':
			C.M = D.M;
			C.C = D.C-E.C;
			break;

		case '*':
			C.M = B.M*A.M;
			C.C = B.C*A.C;
			break;
		case '/':
			C.M = B.C*A.M;
			C.C = B.M*A.C;
			break;

		default:
			break;
	}

	if (C.C%C.M == 0){
		return std::make_shared<Num>(C.C / C.M);
	}
	else{
		return std::make_shared<bunsuu>(C);
	}	
}
IType CalcOne(bunsuu A, int B,char o){
		return std::make_shared<Num>(-1);
}
IType CalcOne(int A, bunsuu B,char o){
	bunsuu C(1,1);
	switch (o)
	{
		case '/':
			C.M = B.C;
			C.C = B.M*A;
			break;
		default:
			break;
	}

	if (C.C%C.M == 0){
		return std::make_shared<Num>(C.C / C.M);
	}
	else{
		return std::make_shared<bunsuu>(C);
	}

}

IType CalcOne(IType a, IType b, IType o){

	if (a->GetToken() == 'N'){
		if (b->GetToken() == 'N'){
			return CalcOne(static_cast<Num*>(&(*a))->N, static_cast<Num*>(&(*b))->N, o->GetToken());
		}
		else{
			return CalcOne(static_cast<Num*>(&(*a))->N, *static_cast<bunsuu*>(&(*b)), o->GetToken());
		}
	}
	else{
		if (b->GetToken() == 'N'){
			return CalcOne(*static_cast<bunsuu*>(&(*a)), static_cast<Num*>(&(*b))->N, o->GetToken());
		}
		else{
			return CalcOne(*static_cast<bunsuu*>(&(*a)), *static_cast<bunsuu*>(&(*b)), o->GetToken());
		}
	}

		/** /
	return CalcOne(
				a->GetToken() == 'N' ? (static_cast<Num*>(&(*a)))->N : *static_cast<bunsuu*>(&(*a)),
				a->GetToken() == 'N' ? (static_cast<Num*>(&(*a)))->N : *static_cast<bunsuu*>(&(*a)),
				o->GetToken()
		);
		*/
	return std::make_shared<Num>(-1);
}

IType Calc(PType& P){
	MType &N = std::get<0>(P);
	MType &T = std::get<1>(P);
	for (std::size_t i = 0; i < T.size(); i++){
		if (T[i]->GetToken() == '*' || T[i]->GetToken() == '/'){
			N[i] = CalcOne(N[i], N[i + 1], T[i]);
			N.erase(N.begin() + i + 1);
			T.erase(T.begin() + i);
			i--;
		}
	}
	for (std::size_t i = 0; i < T.size(); i++){
		if (T[i]->GetToken() == '+' || T[i]->GetToken() == '-'){
			N[i] = CalcOne(N[i], N[i + 1], T[i]);
			N.erase(N.begin() + i + 1);
			T.erase(T.begin() + i);
			i--;
		}
	}
	return N[0];
}

//コピペした。もう無理。
//http://w...content-available-to-author-only...l.edu/~victor/mfmm/
//http://w...content-available-to-author-only...l.edu/~victor/mfmm/compaa/gcd.c
int gcd(int a, int b)
{
	int c;
	while (a != 0) {
		c = a; a = b%a;  b = c;
	}
	return b;
}

bool Show(IType i){
	if (i->GetToken() == 'N'){
		std::cout<<static_cast<Num*>(&(*i))->N<<std::endl;
	}
	else{
		bunsuu &b = *static_cast<bunsuu*>(&(*i));
		int N = gcd(b.C, b.M);
		std::cout<<b.C/N<<'/'<<b.M/N<<std::endl;
	}
	return  true;
}

IType MakeHoge(std::wstring s){
	MType Siki = MakeSiki(s);
	PType P = SepSiki(Siki);

	IType R = Calc(P);

	return R;
}

int main(){
	IType A = 0;

	A = MakeHoge(L"９－３÷１／３＋１");
	Show(A);
	A = MakeHoge(L"１／２÷３／４÷５／６×７／８");
	Show(A);

	return 0;
}