#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 85

enum Type{
	L,
	R,
};

struct Info{

	int index,count;
};

struct Data{

	ll denominator,numerator;
};


typedef vector<Data> V;
typedef vector<V> MATRIX;

int num_element;
int H,W;
ll table[2][SIZE],ans[SIZE];
bool check[SIZE];
char buf[SIZE];
string element_name[SIZE];
Info info[SIZE];

//最大公約数
ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

//最小公倍数
ll lcm(ll x,ll y){

	return (x*y)/gcd(x,y);
}

//分子・分母を約分する
Data reduction(Data A){

	ll common = gcd(A.denominator,A.numerator);

	if(common == 0){

		printf("BUGG!!\n");
		return A;
	}

	A.denominator /= common;
	A.numerator /= common;

	return A;
}

//A-B
Data subtract(Data A,Data B){

	Data ret;

	ll LCM = lcm(A.denominator,B.denominator);

	ll a_mult = LCM/A.denominator;
	ll b_mult = LCM/B.denominator;

	ret.denominator = LCM;

	A.numerator *= a_mult;
	B.numerator *= b_mult;

	ret.numerator = A.numerator-B.numerator;

	return reduction(ret);
}

//A/B
Data divide(Data A,Data B){

	Data ret;

	ret.numerator = A.numerator*B.denominator;
	ret.denominator = A.denominator*B.numerator;

	return reduction(ret);
}

//A*B
Data mult(Data A,Data B){

	Data ret;

	ret.numerator = A.numerator*B.numerator;
	ret.denominator = A.denominator*B.denominator;

	return reduction(ret);
}

bool is_bigger(Data A,Data B){

	return abs(A.numerator*B.denominator) > abs(B.numerator*A.denominator);
}


MATRIX gauss_jordan(MATRIX A){

	MATRIX C(H,V(W+1));

	for(int row = 0; row < H; row++){
		for(int col = 0; col <= W; col++){
			C[row][col] = A[row][col];
		}
	}

	int base_row;
	Data tmp;

	for(int i = 0; i < H; i++){
		base_row = i;
		for(int row = i+1; row < H; row++){
			if(is_bigger(C[row][i],C[base_row][i])){
				base_row = row;
			}
		}

		if(C[base_row][i].numerator == 0)continue; //操作不要

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数

		for(int col = 0; col <= W; col++){ //基準行の係数を1にする

			C[i][col] = divide(C[i][col],tmp);
		}

		for(int row = 0; row < H; row++){
			if(row == i || C[row][i].numerator == 0)continue; //基準行、または該当列が0ならSKIP

			tmp = C[row][i];

			for(int col = i; col <= W; col++){

				Data minus = mult(C[i][col],tmp);

				C[row][col] = subtract(C[row][col],minus);
			}
		}
	}

	//分母を揃える
	ll LCM = 1;
	for(int row = 0; row < H; row++){

		LCM = lcm(LCM,C[row][W].denominator);
	}

	for(int row = 0; row < H; row++){

		C[row][W].numerator *= LCM/C[row][W].denominator;
		C[row][W].denominator = LCM;
	}

	return C;
}

bool check_LowerCase(char ch){

	return ch >= 'a' && ch <= 'z';
}

bool check_UpperCase(char ch){

	return ch >= 'A' && ch <= 'Z';
}

bool check_Number(char ch){

	return ch >= '0' && ch <= '9';
}

vector<Info> calc_Compound(int left,int right){

	vector<Info> ret;

	int index,next,close_pos;
	ll number;

	for(int i = left; i <= right; ){

		if(buf[i] == '('){

			close_pos = i;
			while(buf[close_pos] != ')')close_pos++;

			vector<Info> tmp = calc_Compound(i+1,close_pos-1);

			i = close_pos+1;

			if(check_Number(buf[i])){

				number = 0;

				for(next = i; next <= right && check_Number(buf[next]) == true; next++){

					number = 10*number+(buf[next]-'0');
				}

				for(int k = 0; k < tmp.size(); k++){

					tmp[k].count *= number;
				}

				i = next;
			}

			for(int k = 0; k < tmp.size(); k++){

				ret.push_back(tmp[k]);
			}

		}else if(check_UpperCase(buf[i])){

			string name;

			Info info;

			name += buf[i];

			int add = 1;

			if(check_LowerCase(buf[i+1])){

				name += buf[i+1];
				add++;
			}

			for(int k = 0; k < num_element; k++){

				if(element_name[k] == name){

					index = k;
					break;
				}
			}

			info.index = index;
			info.count = 1;

			i += add;

			if(check_Number(buf[i])){

				number = 0;

				for(next = i; next <= right && check_Number(buf[next]) == true; next++){

					number = 10*number+(buf[next]-'0');
				}

				info.count *= number;
				i = next;
			}
			ret.push_back(info);
		}
	}

	//同じ元素をまとめる
	vector<Info> tmp = ret;
	ret.clear();

	for(int i = 0; i < num_element; i++){
		check[i] = false;
	}

	for(int i = 0; i < tmp.size(); i++){
		if(check[tmp[i].index])continue;

		ll sum = tmp[i].count;
		for(int k = i+1; k < tmp.size(); k++){
			if(tmp[k].index != tmp[i].index)continue;

			sum += tmp[k].count;
		}

		Info info;
		info.index = tmp[i].index;
		info.count = sum;

		ret.push_back(info);

		check[tmp[i].index] = true;
	}

	return ret;
}

vector<vector<Info>> calc_E(int left,int right){

	vector<vector<Info>> ret;

	//+を探す
	queue<int> Q;

	for(int i = left; i <= right; i++){

		if(buf[i] == '+'){

			Q.push(i);
		}
	}

	if(Q.empty()){

		ret.push_back(calc_Compound(left,right));

	}else{

		ret.push_back(calc_Compound(left,Q.front()-1));

		while(true){

			int pre = Q.front();
			Q.pop();

			if(Q.empty()){

				ret.push_back(calc_Compound(pre+1,right));
				break;

			}else{

				ret.push_back(calc_Compound(pre+1,Q.front()-1));
			}
		}
	}

	return ret;
}


void func(){

	for(int i = 0; i < SIZE; i++){

		element_name[i].clear();
	}

	num_element = 0;

	int length;

	for(length = 0; buf[length] != '.'; length++);

	//登場する元素を列挙する
	for(int i = 0; i < length; ){

		if(check_UpperCase(buf[i])){

			string name;

			name += buf[i];

			int add = 1;

			if(check_LowerCase(buf[i+1])){

				name += buf[i+1];
				add++;
			}

			bool FLG = false;

			for(int k = 0; k < num_element; k++){

				if(element_name[k] == name){

					FLG = true;
					break;
				}
			}

			if(!FLG){

				element_name[num_element++] = name;
			}

			i += add;

		}else{

			i++;
		}
	}

	for(int i = 0; i < num_element; i++){

		table[L][i] = 0;
		table[R][i] = 0;
	}

	int mid;
	for(int i = 0; i < length; i++){

		if(buf[i] == '-'){

			mid = i;
			break;
		}
	}

	//左辺
	vector<vector<Info>> LEFT = calc_E(0,mid-1);
	int num_left = LEFT.size(); //左辺の項の数

	//右辺
	vector<vector<Info>> RIGHT = calc_E(mid+2,length-1);

	int num_right = RIGHT.size(); //右辺の項の数

	H = num_element+1;
	W = num_left+num_right;

	MATRIX A(H,V(W+1));

	for(int row = 0; row < H; row++){
		for(int col = 0; col <= W; col++){

			A[row][col].denominator = 1;
			A[row][col].numerator = 0;
		}
	}

	for(int i = 0; i < LEFT.size(); i++){ //項のループ
		for(int k = 0; k < LEFT[i].size(); k++){
			A[LEFT[i][k].index][i].numerator += LEFT[i][k].count;
		}
	}

	for(int i = 0; i < RIGHT.size(); i++){
		for(int k = 0; k < RIGHT[i].size(); k++){
			A[RIGHT[i][k].index][num_left+i].numerator -= RIGHT[i][k].count;
		}
	}

	//1つだけ係数を決めておく
	A[H-1][W-1].numerator = 1;
	A[H-1][W].numerator = 1;

	A = gauss_jordan(A);

	for(int i = 0; i < W; i++){

		ans[i] = A[i][W].numerator;
	}

	ll common = 0;

	for(int i = 0; i < W; i++){

		common = gcd(common,ans[i]);
	}

	for(int i = 0; i < W; i++){

		ans[i] /= common;
	}

	printf("%lld",abs(ans[0]));

	for(int i = 1; i < W; i++){
		printf(" %lld",abs(ans[i]));
	}
	printf("\n");
}

int main(){

	while(true){

		scanf("%s",buf);
		if(buf[0] == '.')break;

		func();
	}

	return 0;
}



Measured memory_bytes: 3304