class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please enter a chemical");
Console.WriteLine("Default: K4(ON(SO3)2)2");
string source = "K4(ON(SO3)2)2";
var str = Console.ReadLine();
str = string.IsNullOrWhiteSpace(str) ? source : str;
var dict = Parse(str, 0, 1);
dict.ToList().ForEach(p => Console.WriteLine($"{p.Key}:{p.Value}"));
Console.WriteLine("Press any key to continue");
Console.ReadLine();
}
static bool IsUpper(char c)
{
return c >= 'A' && c <= 'Z';
}
static bool IsLower(char c)
{
return c >= 'a' && c <= 'z';
}
static bool IsNumber(char c)
{
return c >= '0' && c <= '9';
}
static int GetNextElemIndex(string str, int start)
{
if (start >= str.Length) return -1;
if (!IsUpper(str[start]))
{
return -1;
}
for (int i = start + 1; i < str.Length; i++)
{
if (!IsLower(str[i]) && !IsUpper(str[i])) return i - 1;
if (IsLower(str[i]))
{
continue;
}
if(IsUpper(str[i]))
{
return i - 1;
}
}
return str.Length - 1;
}
static int GetNextNumber(string str,int start)
{
if (start >= str.Length) return -1;
if (!IsNumber(str[start])) return -1;
for(int i=start;i<str.Length;i++)
{
if (!IsNumber(str[i]))
return i - 1;
}
if (IsNumber(str.Last())) return str.Length - 1;
else return -1;
}
static int GetRightParin(string str,int start)
{
for(int i=start;i<str.Length;i++)
{
if (str[i] == ')') return i;
}
return -1;
}
static Dictionary<string, int> Parse(string str,int startIndex,int multiplex)
{
Dictionary<string, int> dict = new Dictionary<string, int>();
while (true)
{
if (startIndex == str.Length)
{
return dict;
}
var elem = GetNextElemIndex(str, startIndex);
if (elem!=-1)
{
var name = str.Substring(startIndex, elem - startIndex + 1);
int value = 1;
startIndex = elem + 1;
var num = GetNextNumber(str, startIndex);
if(num!=-1)
{
value = int.Parse(str.Substring(startIndex, num - startIndex + 1));
startIndex = num + 1;
}
if (!dict.ContainsKey(name)) dict[name] = 0;
dict[name] += value;
}
else if(str[startIndex]=='(')
{
var right = GetRightParin(str, startIndex + 1)+1;
var nextNum = GetNextNumber(str, right);
int mul = int.Parse(str.Substring(nextNum, nextNum - right + 1));
var recursion = Parse(str, startIndex + 1, mul);
startIndex = nextNum + 1;
recursion.Keys.ToList().ForEach(k => { if (!dict.ContainsKey(k)) dict[k] = 0; });
recursion.ToList().ForEach(p => dict[p.Key] += p.Value);
} else if(str[startIndex]==')')
{
return dict.ToDictionary(i => i.Key, i => i.Value * multiplex);
}
}
}
}