Number of Atoms in C++



Suppose we have a chemical formula; we have to find the count of each atom.

An atomic element will always start with an uppercase character, there can be zero or more lowercase letters, representing the name. And 1 or more digits representing the count of that element may follow if the count is greater than 1. But if the count is 1, no digits will follow. As an example, H2O and H2O2 both are valid, but H1O2 is invalid.

So, if the input is like Na2(CO)3, then the output will be C3Na2O3, so this indicates 3 Carbon (C), 2 Sodium (Na), 3 Oxygen (O).

To solve this, we will follow these steps −

  • Define a function makeRet(), this will take one map m,

  • ret := blank string

  • for each key-value pair 'it' in m −

    • ret := ret + key of it

    • if value of it > 1, then −

      • ret := ret + value of it as string

  • return ret

  • Define a function countOfAtoms(), this will take s,

  • Define one map m

  • Define one stack st

  • i := 0, n := size of s

  • while i < n, do −

    • c := s[i]

    • (increase i by 1)

    • if c is same as '(', then −

      • insert m into st

      • m := Define one map

    • otherwise when c is same as ')', then −

      • val := 0

      • while (i < n and s[i] in range 0 to 9), do −

        • val := val * 10 + (s[i] - ASCII of '0')

        • (increase i by 1)

      • Define one map temp := top element of st

      • delete element from st

      • for each key-value pair 'it' in m −

        • value of it := value of it * val

        • temp[key of it] := temp[key of it] + value of it

      • m := temp

    • Otherwise

      • name := blank string

      • val := 0

      • name := name + c

      • while (i < n and s[i] in range 'a' to 'z'), do −

        • name := name + s[i]

        • (increase i by 1)

      • while (i < n and s[i] in range 0 to 9), do −

        • val := val * 10 + (s[i] - ASCII of '0')

        • (increase i by 1)

      • val := (if val is same as 0, then 1, otherwise val)

      • m[name] := m[name] + val

  • return makeRet(m)

Let us see the following implementation to get better understanding −

Example

 Live Demo

#include <bits/stdc++.h>
using namespace std;
class Solution {
   public:
   string makeRet(map<string, int> m){
      string ret = "";
      for (auto& it : m) {
         ret += it.first;
         if (it.second > 1) {
            ret += to_string(it.second);
         }
      }
      return ret;
   }
   string countOfAtoms(string s){
      map<string, int> m;
      stack<map<string, int> > st;
      int i = 0;
      int n = s.size();
      while (i < n) {
         char c = s[i];
         i++;
         if (c == '(') {
            st.push(m);
            m = map<string, int>();
         }
         else if (c == ')') {
            int val = 0;
            while (i < n && s[i] >= '0' && s[i] <= '9') {
               val = val * 10 + (s[i] - '0');
               i++;
            }
            map<string, int> temp = st.top();
            st.pop();
            for (auto& it : m) {
               it.second *= val;
               temp[it.first] += it.second;
            }
            m = temp;
         }  
         else {
            string name = "";
            int val = 0;
            name += c;
            while (i < n && s[i] >= 'a' && s[i] <= 'z') {
               name += s[i];
               i++;
            }
            while (i < n && s[i] >= '0' && s[i] <= '9') {
               val = val * 10 + (s[i] - '0');
               i++;
            }
            val = val == 0 ? 1 : val;
            m[name] += val;
         }
      }
      return makeRet(m);
   }
};
main(){
   Solution ob;
   cout << (ob.countOfAtoms("Na2(CO)3"));
}

Input

Na2(CO)3

Output

C3Na2O3

Advertisements