#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <functional>
#include <map>
#include <cctype>
using namespace std;
#define rep(i,n) for(int i=0;i<(n);++i)
#define rep1(i,n) for(int i=1;i<=(n);++i)
#define all(c) (c).begin(),(c).end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl;
typedef string::const_iterator State;
typedef map<string,int> msi;
typedef vector<int> vi;
typedef vector<vi> mat;
typedef pair<string,int> P;
typedef pair<int,int> Pa;

const int MAX_eq=26*27;
msi tonum;
mat a;
int ct;
Pa memo[MAX_eq];
bool visited[MAX_eq]={};
int cnt;

bool isC(char c){
	return'A'<=c && c<='Z';
}
bool isS(char c){
	return'a'<=c && c<='z';
}
void mul(msi& m,int x){
	for(auto& v : m){
		v.sc*=x;
	}
}
void add(msi& x,msi y){
	for(auto& v : y){
		x[v.fs]+=v.sc;
	}
}
msi atom(State &be){
	//cout << "atmo";
	msi ret;
	string a;
	a+=(*be);
	be++;
	if(isS(*be)) a+=(*be),be++;
	ret[a]++;
	return ret;
}
int num(State &be){
	//cout << "num";
	int ret=0;
	while(isdigit(*be)){
		ret*=10;
		ret+=(*be)-'0';
		be++;
	}
	return ret;
}
msi mol(State &be){
	msi ret;
	while(isC(*be) || (*be)=='('){
		//cout << *be;
		msi x;
		if(isC(*be)){
			x=atom(be);
			if(isdigit(*be)) mul(x,num(be));
		}else if(*be=='('){
			be++;
			x=mol(be);
			be++;
			if(isdigit(*be)) mul(x,num(be));
		}
		add(ret,x);
	}
	return ret;
}
void seqmol(State &be){
	while(*be=='+'){
		be++;
		msi ret=mol(be);
		//for(auto v : ret) cout << tonum[v.fs] << " " << ct<<endl;
		for(auto v : ret) a[tonum[v.fs]][ct]=v.sc;
		ct++;
	}
	be++;
	while(*be!='.'){
		be++;
		msi ret=mol(be);
		mul(ret,-1);
		//for(auto v : ret) cout << tonum[v.fs] << " " << ct<<endl;
		for(auto v : ret) a[tonum[v.fs]][ct]=v.sc;
		ct++;
	}
}
int gcd(int x,int y){
	if(x<0) x=-x;
	if(y<0) y=-y;
	if(y==0) return x;
	return gcd(y,x%y);
}
int lcm(int x,int y){
	return x/gcd(x,y)*y;
}
void sweep(int eq, int var, mat& a){
	int ans=0;
	bool used[MAX_eq]={};
	rep(j,var){
		int i=0;
		while( (i < eq) && (used[i] || (a[i][j] == 0) ) ) i++;
		if(i == eq) continue;
		ans++;
		used[i] = true;
		rep(k,eq){
			if(i==k || a[k][j]==0) continue;
			int g=gcd(a[k][j],a[i][j]),akj=a[k][j];
			rep(l,var){
				a[k][l] = a[k][l]*(a[i][j]/g) - a[i][l]*(akj/g);
			}
		}
	}
}
void dfs(int id,int bunshi,int bunbo){
	memo[id]=Pa(bunshi,bunbo);
//	cout << "id"<<id<< " "<<bunshi<<"/"<<bunbo<<endl;
	visited[id]=true;
	rep(i,cnt){
		if(a[i][id]!=-0){
			rep(j,ct){
				if(j!=id&&a[i][j]!=0&&!visited[j]){
					int nshi=bunshi*a[i][id],nbo=bunbo*a[i][j];
					if(nshi<0) nshi*=-1;
					if(nbo<0) nbo*=-1;
					int g=gcd(nshi,nbo);
					nshi/=g,nbo/=g;
					dfs(j,nshi,nbo);
				}
			}
		}
	}
}
int main(){
	cnt=0;
	rep(i,26){
		string st(1,'A'+i);
		tonum.insert(P(st,cnt++));
	}
	rep(i,26) rep(j,26){
		string st(1,'A'+i);
		st+=('a'+j);
		tonum.insert(P(st,cnt++));
	}
	while(true){
		string s;
		cin>>s;
		if(s[0]=='.') break;
		s="+"+s;
		State be=s.begin();
		ct=0;
		a.clear();
		rep(i,cnt) a.pb(vi(MAX_eq,0));
		seqmol(be);
		sweep(cnt,ct,a);
		rep(i,MAX_eq) visited[i]=false;
		dfs(0,1,1);
		int lc=1;
		rep(i,ct){
			lc=lcm(lc,memo[i].sc);
		}
		rep(i,ct){
			printf("%d",memo[i].fs*lc/memo[i].sc);
			printf((i!=ct-1 ? " " : "\n"));
		}
	}
}

Measured memory_bytes: 3112