#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cctype>
#include <cassert>
#include <string>
#include <vector>
#include <algorithm>
#include <map>

intmax_t gcd(intmax_t m, intmax_t n) {
  while (n) std::swap(m%=n, n);
  return m;
}

struct Atoms: std::map<std::string, intmax_t> {
  Atoms &operator +=(const Atoms &rhs) {
    for (const auto &p: rhs) {
      (*this)[p.first] += p.second;
    }
    return *this;
  }

  Atoms &operator *=(int n) {
    for (auto &p: *this) {
      p.second *= n;
    }
    return *this;
  }

  void debug() const {
    for (const auto &p: *this) {
      fprintf(stderr, "%s -> %jd\n", p.first.c_str(), p.second);
    }
  }
};

Atoms parse(const std::string &s, size_t &i) {
  Atoms res;
  while (i < s.length()) {
    Atoms cur;
    if (isupper(s[i])) {
      std::string a(1, s[i++]);
      if (islower(s[i]))
        a += s[i++];
      cur[a] = 1;
    } else if (s[i] == '(') {
      cur = parse(s, ++i);
      assert(s[i] == ')');
      ++i;
    } else {
      break;
    }
    if (i < s.length() && isdigit(s[i])) {
      int scl=s[i]-'0';
      while (++i < s.length() && isdigit(s[i]))
        scl = scl*10+s[i]-'0';
      cur *= scl;
    }
    res += cur;
  }
  return res;
}

void debug(const std::vector<std::vector<intmax_t>> &a) {
  fprintf(stderr, "{\n");
  for (size_t i=0; i<a.size(); ++i) {
    fprintf(stderr, "  ");
    for (size_t j=0; j<a[i].size(); ++j)
      fprintf(stderr, "%jd%c", a[i][j], j+1<a[i].size()? ' ':'\n');
  }
  fprintf(stderr, "}\n");
}

std::vector<intmax_t> solve(std::vector<std::vector<intmax_t>> mat) {
  size_t r=mat.size(), c=mat[0].size();
  for (size_t i=0; i+1<c; ++i) {
    if (mat[i][i] == 0) {
      for (size_t j=i; j<r; ++j) {
        if (mat[j][i] != 0) {
          std::swap(mat[i], mat[j]);
          break;
        }
      }
    }
    assert(mat[i][i] != 0);

    for (size_t j=0; j<r; ++j) {
      if (i == j) continue;
      if (mat[j][i] == 0) continue;

      intmax_t g=gcd(mat[i][i], mat[j][i]);
      intmax_t ai=mat[j][i]/g, aj=mat[i][i]/g;
      for (size_t k=0; k<c; ++k) {
        mat[j][k] *= aj;
        mat[j][k] -= ai*mat[i][k];
      }
    }
  }
  
  intmax_t lcm=abs(mat[0][0]);
  for (size_t i=1; i+1<c; ++i)
    lcm = lcm/gcd(lcm, abs(mat[i][i]))*abs(mat[i][i]);

  for (size_t i=0; i+1<c; ++i) {
    mat[i][c-1] *= lcm/mat[i][i];
    mat[i][i] = lcm;
  }

  std::vector<intmax_t> res(c);
  res[c-1] = lcm;
  for (size_t i=0; i+1<c; ++i)
    res[i] = -mat[i][c-1];

  intmax_t g=res[0];
  for (size_t i=1; i<res.size(); ++i)
    g = gcd(g, res[i]);
  for (size_t i=0; i<res.size(); ++i)
    res[i] /= g;

  return res;
}

int testcase_ends() {
  char buf[128];
  scanf("%s", buf);
  std::string s=buf;
  if (s == ".") return 1;

  size_t i=0;
  std::vector<Atoms> atms;
  bool neg=false;
  while (true) {
    atms.push_back(parse(s, i));
    if (neg) atms.back() *= -1;
    if (s[i] == '+') {
      ++i;
    } else if (s[i] == '-') {
      assert(s[i+1] == '>');
      i += 2;
      neg = true;
    } else if (s[i] == '.') {
      break;
    } else {
      __builtin_unreachable();
    }
  }

  std::map<std::string, size_t> ind;
  for (const auto &a: atms) {
    for (const auto &p: a) {
      auto it=ind.lower_bound(p.first);
      if (it == ind.end() || it->first != p.first) {
        size_t i=ind.size();
        ind.emplace_hint(it, p.first, i);
      }
    }
  }

  std::vector<std::vector<intmax_t>> mat(
      ind.size(), std::vector<intmax_t>(atms.size()));

  for (size_t i=0; i<atms.size(); ++i)
    for (const auto &p: atms[i])
      mat[ind[p.first]][i] = p.second;

  std::vector<intmax_t> sol=solve(mat);
  for (size_t i=0; i<sol.size(); ++i)
    printf("%jd%c", sol[i], i+1<sol.size()? ' ':'\n');
  return 0;
}

int main() {
  while (!testcase_ends()) {}
}



Measured memory_bytes: 2956