-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolution770.cs
155 lines (138 loc) · 5.1 KB
/
Solution770.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
using System.Text;
using LeetCode.DataStructures;
namespace LeetCode.Solutions;
public class Solution770
{
/// <summary>
/// 770. Basic Calculator IV - Hard
/// <a href="https://leetcode.com/problems/basic-calculator-iv">See the problem</a>
/// </summary>
public IList<string> BasicCalculatorIV(string expression, string[] evalvars, int[] evalints)
{
// Substitute evalvars with evalints in the expression map
var evalMap = new Dictionary<string, int>();
for (int i = 0; i < evalvars.Length; i++)
{
evalMap[evalvars[i]] = evalints[i];
}
// Evaluate the expression and obtain the final result as a list of terms
var result = Evaluate(expression, evalMap);
// Convert the result to the required output format
return FormatResult(result);
}
private Dictionary<string, int> Evaluate(string expression, Dictionary<string, int> evalMap)
{
// Tokenize and recursively evaluate expression with correct operator precedence
return ParseExpression(expression, evalMap);
}
private Dictionary<string, int> ParseExpression(string expression, Dictionary<string, int> evalMap)
{
Stack<Dictionary<string, int>> values = new Stack<Dictionary<string, int>>();
Stack<char> ops = new Stack<char>();
int i = 0;
while (i < expression.Length)
{
char c = expression[i];
if (char.IsWhiteSpace(c))
{
i++;
continue;
}
else if (char.IsDigit(c) || char.IsLetter(c))
{
int start = i;
while (i < expression.Length && (char.IsDigit(expression[i]) || char.IsLetter(expression[i]))) i++;
string token = expression.Substring(start, i - start);
Dictionary<string, int> term;
if (int.TryParse(token, out int num))
{
term = new Dictionary<string, int> { { "", num } }; // constant term
}
else
{
term = new Dictionary<string, int> { { token, evalMap.ContainsKey(token) ? evalMap[token] : 1 } };
}
values.Push(term);
}
else if (c == '(')
{
ops.Push(c);
i++;
}
else if (c == ')')
{
while (ops.Peek() != '(')
{
ApplyOperation(values, ops.Pop());
}
ops.Pop(); // remove '('
i++;
}
else
{ // operators +, -, *
while (ops.Count > 0 && Precedence(ops.Peek()) >= Precedence(c))
{
ApplyOperation(values, ops.Pop());
}
ops.Push(c);
i++;
}
}
while (ops.Count > 0)
{
ApplyOperation(values, ops.Pop());
}
return values.Pop();
}
private int Precedence(char op)
{
return (op == '+' || op == '-') ? 1 : 2;
}
private void ApplyOperation(Stack<Dictionary<string, int>> values, char op)
{
var b = values.Pop();
var a = values.Pop();
if (op == '+') values.Push(AddTerms(a, b));
else if (op == '-') values.Push(AddTerms(a, NegateTerms(b)));
else values.Push(MultiplyTerms(a, b));
}
private Dictionary<string, int> AddTerms(Dictionary<string, int> a, Dictionary<string, int> b)
{
var result = new Dictionary<string, int>(a);
foreach (var kv in b)
{
if (result.ContainsKey(kv.Key)) result[kv.Key] += kv.Value;
else result[kv.Key] = kv.Value;
}
return result.Where(kv => kv.Value != 0).ToDictionary(kv => kv.Key, kv => kv.Value);
}
private Dictionary<string, int> NegateTerms(Dictionary<string, int> terms)
{
return terms.ToDictionary(kv => kv.Key, kv => -kv.Value);
}
private Dictionary<string, int> MultiplyTerms(Dictionary<string, int> a, Dictionary<string, int> b)
{
var result = new Dictionary<string, int>();
foreach (var kvA in a)
{
foreach (var kvB in b)
{
var vars = kvA.Key.Split('*').Concat(kvB.Key.Split('*')).Where(v => v != "").OrderBy(x => x).ToArray();
string newKey = string.Join("*", vars);
int newValue = kvA.Value * kvB.Value;
if (result.ContainsKey(newKey)) result[newKey] += newValue;
else result[newKey] = newValue;
}
}
return result.Where(kv => kv.Value != 0).ToDictionary(kv => kv.Key, kv => kv.Value);
}
private IList<string> FormatResult(Dictionary<string, int> terms)
{
var sortedTerms = terms
.OrderByDescending(kv => kv.Key.Count(c => c == '*')) // Sort by degree
.ThenBy(kv => kv.Key, StringComparer.Ordinal)
.Select(kv => kv.Value + (kv.Key == "" ? "" : "*" + kv.Key))
.ToList();
return sortedTerms;
}
}