Skip to content

Commit 39510bd

Browse files
committed
feat: add solution 2019. The Score of Students Solving Math Expression
1 parent 22f2b06 commit 39510bd

File tree

2 files changed

+219
-0
lines changed

2 files changed

+219
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# [2019. The Score of Students Solving Math Expression](https://leetcode.com/problems/the-score-of-students-solving-math-expression)
2+
3+
## Description
4+
5+
<div class="elfjS" data-track-load="description_content"><p>You are given a string <code>s</code> that contains digits <code>0-9</code>, addition symbols <code>'+'</code>, and multiplication symbols <code>'*'</code> <strong>only</strong>, representing a <strong>valid</strong> math expression of <strong>single digit numbers</strong> (e.g., <code>3+5*2</code>). This expression was given to <code>n</code> elementary school students. The students were instructed to get the answer of the expression by following this <strong>order of operations</strong>:</p>
6+
7+
<ol>
8+
<li>Compute <strong>multiplication</strong>, reading from <strong>left to right</strong>; Then,</li>
9+
<li>Compute <strong>addition</strong>, reading from <strong>left to right</strong>.</li>
10+
</ol>
11+
12+
<p>You are given an integer array <code>answers</code> of length <code>n</code>, which are the submitted answers of the students in no particular order. You are asked to grade the <code>answers</code>, by following these <strong>rules</strong>:</p>
13+
14+
<ul>
15+
<li>If an answer <strong>equals</strong> the correct answer of the expression, this student will be rewarded <code>5</code> points;</li>
16+
<li>Otherwise, if the answer <strong>could be interpreted</strong> as if the student applied the operators <strong>in the wrong order</strong> but had <strong>correct arithmetic</strong>, this student will be rewarded <code>2</code> points;</li>
17+
<li>Otherwise, this student will be rewarded <code>0</code> points.</li>
18+
</ul>
19+
20+
<p>Return <em>the sum of the points of the students</em>.</p>
21+
22+
<p>&nbsp;</p>
23+
<p><strong class="example">Example 1:</strong></p>
24+
<img alt="" src="https://assets.leetcode.com/uploads/2021/09/17/student_solving_math.png" style="width: 678px; height: 109px;">
25+
<pre><strong>Input:</strong> s = "7+3*1*2", answers = [20,13,42]
26+
<strong>Output:</strong> 7
27+
<strong>Explanation:</strong> As illustrated above, the correct answer of the expression is 13, therefore one student is rewarded 5 points: [20,<u><strong>13</strong></u>,42]
28+
A student might have applied the operators in this wrong order: ((7+3)*1)*2 = 20. Therefore one student is rewarded 2 points: [<u><strong>20</strong></u>,13,42]
29+
The points for the students are: [2,5,0]. The sum of the points is 2+5+0=7.
30+
</pre>
31+
32+
<p><strong class="example">Example 2:</strong></p>
33+
34+
<pre><strong>Input:</strong> s = "3+5*2", answers = [13,0,10,13,13,16,16]
35+
<strong>Output:</strong> 19
36+
<strong>Explanation:</strong> The correct answer of the expression is 13, therefore three students are rewarded 5 points each: [<strong><u>13</u></strong>,0,10,<strong><u>13</u></strong>,<strong><u>13</u></strong>,16,16]
37+
A student might have applied the operators in this wrong order: ((3+5)*2 = 16. Therefore two students are rewarded 2 points: [13,0,10,13,13,<strong><u>16</u></strong>,<strong><u>16</u></strong>]
38+
The points for the students are: [5,0,0,5,5,2,2]. The sum of the points is 5+0+0+5+5+2+2=19.
39+
</pre>
40+
41+
<p><strong class="example">Example 3:</strong></p>
42+
43+
<pre><strong>Input:</strong> s = "6+0*1", answers = [12,9,6,4,8,6]
44+
<strong>Output:</strong> 10
45+
<strong>Explanation:</strong> The correct answer of the expression is 6.
46+
If a student had incorrectly done (6+0)*1, the answer would also be 6.
47+
By the rules of grading, the students will still be rewarded 5 points (as they got the correct answer), not 2 points.
48+
The points for the students are: [0,0,5,0,0,5]. The sum of the points is 10.
49+
</pre>
50+
51+
<p>&nbsp;</p>
52+
<p><strong>Constraints:</strong></p>
53+
54+
<ul>
55+
<li><code>3 &lt;= s.length &lt;= 31</code></li>
56+
<li><code>s</code> represents a valid expression that contains only digits <code>0-9</code>, <code>'+'</code>, and <code>'*'</code> only.</li>
57+
<li>All the integer operands in the expression are in the <strong>inclusive</strong> range <code>[0, 9]</code>.</li>
58+
<li><code>1 &lt;=</code> The count of all operators (<code>'+'</code> and <code>'*'</code>) in the math expression <code>&lt;= 15</code></li>
59+
<li>Test data are generated such that the correct answer of the expression is in the range of <code>[0, 1000]</code>.</li>
60+
<li>Test data are generated such that value never exceeds 10<sup>9</sup> in intermediate steps of multiplication.</li>
61+
<li><code>n == answers.length</code></li>
62+
<li><code>1 &lt;= n &lt;= 10<sup>4</sup></code></li>
63+
<li><code>0 &lt;= answers[i] &lt;= 1000</code></li>
64+
</ul>
65+
</div>
66+
67+
<p>&nbsp;</p>
68+
69+
## Solutions
70+
71+
**Solution: `Dynamic Programming`**
72+
73+
- Time complexity: <em>O(n<sup>3</sup>limit<sup>2</sup>)</em>
74+
- Space complexity: <em>O(n<sup>2</sup>limit<sup>2</sup>)</em>
75+
76+
<p>&nbsp;</p>
77+
78+
### **JavaScript**
79+
80+
```js
81+
/**
82+
* @param {string} s
83+
* @param {number[]} answers
84+
* @return {number}
85+
*/
86+
const scoreOfStudents = function (s, answers) {
87+
const n = s.length;
88+
const ANSWER_LIMIT = 1000;
89+
90+
const compute = () => {
91+
const solves = s.split('+');
92+
93+
return solves.reduce((result, solve) => {
94+
let current = Number(solve[0]);
95+
96+
for (let index = 2; index < solve.length; index += 2) {
97+
current *= solve[index];
98+
}
99+
100+
return result + current;
101+
}, 0);
102+
};
103+
104+
const correctAnswer = compute();
105+
const dp = Array.from({ length: n }, () => new Array(n).fill(-1));
106+
107+
const getScores = (left, right) => {
108+
if (left === right) {
109+
const num = Number(s[left]);
110+
111+
dp[left][right] = new Set([num]);
112+
113+
return dp[left][right];
114+
}
115+
116+
if (dp[left][right] !== -1) return dp[left][right];
117+
118+
const result = new Set();
119+
120+
for (let index = left + 1; index < right; index += 2) {
121+
const leftScores = getScores(left, index - 1);
122+
const rightScores = getScores(index + 1, right);
123+
124+
for (const scoreA of leftScores) {
125+
for (const scoreB of rightScores) {
126+
const operation = s[index];
127+
const score = operation === '+' ? scoreA + scoreB : scoreA * scoreB;
128+
129+
if (score > ANSWER_LIMIT) continue;
130+
131+
result.add(score);
132+
}
133+
}
134+
}
135+
136+
dp[left][right] = result;
137+
138+
return result;
139+
};
140+
141+
const scores = getScores(0, n - 1);
142+
143+
return answers.reduce((result, answer) => {
144+
if (answer === correctAnswer) return result + 5;
145+
if (scores.has(answer)) return result + 2;
146+
147+
return result;
148+
}, 0);
149+
};
150+
```
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @param {string} s
3+
* @param {number[]} answers
4+
* @return {number}
5+
*/
6+
const scoreOfStudents = function (s, answers) {
7+
const n = s.length;
8+
const ANSWER_LIMIT = 1000;
9+
10+
const compute = () => {
11+
const solves = s.split('+');
12+
13+
return solves.reduce((result, solve) => {
14+
let current = Number(solve[0]);
15+
16+
for (let index = 2; index < solve.length; index += 2) {
17+
current *= solve[index];
18+
}
19+
20+
return result + current;
21+
}, 0);
22+
};
23+
24+
const correctAnswer = compute();
25+
const dp = Array.from({ length: n }, () => new Array(n).fill(-1));
26+
27+
const getScores = (left, right) => {
28+
if (left === right) {
29+
const num = Number(s[left]);
30+
31+
dp[left][right] = new Set([num]);
32+
33+
return dp[left][right];
34+
}
35+
36+
if (dp[left][right] !== -1) return dp[left][right];
37+
38+
const result = new Set();
39+
40+
for (let index = left + 1; index < right; index += 2) {
41+
const leftScores = getScores(left, index - 1);
42+
const rightScores = getScores(index + 1, right);
43+
44+
for (const scoreA of leftScores) {
45+
for (const scoreB of rightScores) {
46+
const operation = s[index];
47+
const score = operation === '+' ? scoreA + scoreB : scoreA * scoreB;
48+
49+
if (score > ANSWER_LIMIT) continue;
50+
51+
result.add(score);
52+
}
53+
}
54+
}
55+
56+
dp[left][right] = result;
57+
58+
return result;
59+
};
60+
61+
const scores = getScores(0, n - 1);
62+
63+
return answers.reduce((result, answer) => {
64+
if (answer === correctAnswer) return result + 5;
65+
if (scores.has(answer)) return result + 2;
66+
67+
return result;
68+
}, 0);
69+
};

0 commit comments

Comments
 (0)