Skip to content

Commit 5d7ee9d

Browse files
committed
LeetCode 41 and bugfix with OpAssign
1 parent 39bdd50 commit 5d7ee9d

5 files changed

Lines changed: 301 additions & 4 deletions

File tree

compiler/src/ast/math_expr.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,9 @@ impl Expr {
234234
}
235235
Cow::Owned(lhs.for_type(flags)?)
236236
}
237+
index @ Expr::Index { .. } => Cow::Owned(index.for_type(flags)?),
237238
Expr::DotLookup { expected_type, .. } => Cow::Borrowed(expected_type),
238-
_ => bail!("invalid left operand for {op}"),
239+
_ => bail!("invalid left operand for {op} (cannot apply to {})", lhs.for_type(flags)?),
239240
}
240241
} else {
241242
Cow::Owned(lhs.for_type(flags)?)
@@ -537,14 +538,14 @@ fn compile_depth(
537538

538539
return Ok(rhs)
539540
}
540-
Expr::DotLookup { .. } => {
541+
// The bytecode instructions both expect a `HeapPrimitive`, so the code can be duplicated.
542+
Expr::DotLookup { .. } | Expr::Index { .. } => {
541543
rhs.push(instruction!(store_fast depth));
542544
rhs.append(&mut lhs);
543545
rhs.push(instruction!(load_fast depth));
544546
rhs.push(instruction!(bin_op_assign (op.symbol())));
545547

546548
return Ok(rhs)
547-
548549
}
549550
lhs => unimplemented!("bin_op_asign has not been implemented for this left hand operand: {lhs:?}")
550551
}

compiler/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod class;
1010
mod comments;
1111
mod functions;
1212
mod r#if;
13+
mod leetcode;
1314
mod maps;
1415
mod math;
1516
mod modify_edge_cases;

compiler/src/tests/leetcode.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
use crate::eval;
2+
3+
#[test]
4+
pub fn first_missing_positive() {
5+
eval(
6+
r#"
7+
8+
###
9+
Given an unsorted integer array nums. Return the smallest positive integer that is not present in nums.
10+
11+
You must implement an algorithm that runs in O(n) time and uses O(1) auxiliary space.
12+
13+
14+
15+
Example 1:
16+
17+
Input: nums = [1,2,0]
18+
Output: 3
19+
Explanation: The numbers in the range [1,2] are all in the array.
20+
Example 2:
21+
22+
Input: nums = [3,4,-1,1]
23+
Output: 2
24+
Explanation: 1 is in the array but 2 is missing.
25+
Example 3:
26+
27+
Input: nums = [7,8,9,11,12]
28+
Output: 1
29+
Explanation: The smallest positive integer 1 is missing.
30+
31+
32+
Constraints:
33+
34+
1 <= nums.length <= 105
35+
-231 <= nums[i] <= 231 - 1
36+
###
37+
38+
first_missing_positive = fn(nums: [int...]) -> int {
39+
from 0 to nums.len(), i {
40+
if nums[i] <= 0 {
41+
nums[i] = nums.len() + 1
42+
}
43+
}
44+
45+
from 0 to nums.len(), i {
46+
num_abs = (nums[i]).abs()
47+
48+
if num_abs - 1 < nums.len() && nums[num_abs - 1] > 0 {
49+
(nums[num_abs - 1]) *= -1
50+
}
51+
}
52+
53+
from 0 to nums.len(), i {
54+
if nums[i] > 0 {
55+
return i + 1
56+
}
57+
}
58+
59+
return nums.len() + 1
60+
}
61+
62+
test_cases = map[[int...], int] {
63+
[1,2,0]: 3,
64+
[3,4,-1,1]: 2,
65+
[7,8,9,11,12]: 1,
66+
[50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1]: 51,
67+
[1,2,6,3,5,4]: 7,
68+
}.pairs()
69+
70+
print "🔵 Starting testing suite"
71+
72+
from 0 to test_cases.len(), i {
73+
[input, expected] = test_cases[i]
74+
75+
output = first_missing_positive(input)
76+
77+
if output != expected {
78+
print "🛑 Error in test suite: expected " + expected.to_str() + ", found: " + output.to_str()
79+
assert false
80+
}
81+
82+
print " ☐ Passed test #" + i
83+
}
84+
85+
print "✅ Passed " + test_cases.len() + " test cases"
86+
"#
87+
)
88+
.unwrap();
89+
}
90+
91+
#[test]
92+
pub fn product_of_array_except_self() {
93+
eval(
94+
r#"
95+
###
96+
Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].
97+
98+
The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.
99+
100+
You must write an algorithm that runs in O(n) time and without using the division operation.
101+
102+
103+
104+
Example 1:
105+
106+
Input: nums = [1,2,3,4]
107+
Output: [24,12,8,6]
108+
Example 2:
109+
110+
Input: nums = [-1,1,0,-3,3]
111+
Output: [0,0,9,0,0]
112+
113+
114+
Constraints:
115+
116+
2 <= nums.length <= 105
117+
-30 <= nums[i] <= 30
118+
The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.
119+
120+
121+
Follow up: Can you solve the problem in O(1) extra space complexity? (The output array does not count as extra space for space complexity analysis.)
122+
###
123+
124+
product_of_array_except_self = fn(nums: [int...]) -> [int...] {
125+
result: [int...] = []
126+
result.ensure_inner_capacity(nums.len())
127+
128+
left_prefixes: [int?...] = [nil, nums[0]]
129+
130+
# walk from left to right
131+
from 1 to nums.len() - 1, i {
132+
left_prefixes.push(left_prefixes[i] * nums[i])
133+
}
134+
135+
right_prefixes: [int?...] = [nil, nums[nums.len() - 1]]
136+
137+
# walk from right to left
138+
from 1 to nums.len() - 1, i {
139+
right_prefixes.push(right_prefixes[i] * nums[nums.len() - i - 1])
140+
}
141+
142+
# aggregate
143+
from 0 to nums.len(), i {
144+
left_product = (left_prefixes[i]) or 1
145+
right_product = (right_prefixes[nums.len() - i - 1]) or 1
146+
result.push(left_product * right_product)
147+
}
148+
149+
return result
150+
}
151+
152+
test_cases = map[[int...], [int...]] {
153+
[1,2,3,4]: [24,12,8,6],
154+
[-1,1,0,-3,3]: [0,0,9,0,0],
155+
[1, 2, 3, 4]: [24, 12, 8, 6],
156+
[2, 3, 4, 5]: [60, 40, 30, 24],
157+
[1, 1, 1, 1]: [1, 1, 1, 1],
158+
[10, 3, 5, 6, 2]: [180, 600, 360, 300, 900],
159+
[-1, 1, 0, -3, 3]: [0, 0, 9, 0, 0],
160+
[2, -2, 3, -3]: [18, -18, 12, -12],
161+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
162+
[-5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]: [-1, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5],
163+
}.pairs()
164+
165+
print "🔵 Starting testing suite"
166+
167+
from 0 to test_cases.len(), i {
168+
[input, expected] = test_cases[i]
169+
170+
output = product_of_array_except_self(input)
171+
172+
if output != expected {
173+
print "🛑 Error in test suite: expected " + expected.to_str() + ", found: " + output.to_str()
174+
assert false
175+
}
176+
177+
print " ☐ Passed test #" + i
178+
}
179+
180+
print "✅ Passed " + test_cases.len() + " test cases"
181+
"#,
182+
)
183+
.unwrap()
184+
}

compiler/src/tests/math.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ fn mod_equals() {
229229
}
230230

231231
#[test]
232-
fn bin_op_assign() {
232+
fn class_member_bin_op_assignment() {
233233
eval(
234234
r#"
235235
@@ -339,3 +339,36 @@ fn subtract_underflow() {
339339
)
340340
.unwrap();
341341
}
342+
343+
#[test]
344+
fn array_index_bin_op_assignment() {
345+
eval(
346+
r#"
347+
348+
positive_numbers: [int...] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
349+
350+
from 0 to positive_numbers.len(), i {
351+
positive_numbers[i] *= -1
352+
}
353+
354+
assert positive_numbers == [-1, -2, -3, -4, -5, -6, -7, -8, -9, -10]
355+
"#,
356+
)
357+
.unwrap();
358+
}
359+
360+
#[test]
361+
#[should_panic(expected = "invalid operation: int *= bool")]
362+
fn unsupported_array_index_bin_op_assignment() {
363+
eval(
364+
r#"
365+
366+
positive_numbers: [int...] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
367+
368+
from 0 to positive_numbers.len(), i {
369+
positive_numbers[i] *= true
370+
}
371+
"#,
372+
)
373+
.unwrap();
374+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
###
2+
Given an unsorted integer array nums. Return the smallest positive integer that is not present in nums.
3+
4+
You must implement an algorithm that runs in O(n) time and uses O(1) auxiliary space.
5+
6+
7+
8+
Example 1:
9+
10+
Input: nums = [1,2,0]
11+
Output: 3
12+
Explanation: The numbers in the range [1,2] are all in the array.
13+
Example 2:
14+
15+
Input: nums = [3,4,-1,1]
16+
Output: 2
17+
Explanation: 1 is in the array but 2 is missing.
18+
Example 3:
19+
20+
Input: nums = [7,8,9,11,12]
21+
Output: 1
22+
Explanation: The smallest positive integer 1 is missing.
23+
24+
25+
Constraints:
26+
27+
1 <= nums.length <= 105
28+
-231 <= nums[i] <= 231 - 1
29+
###
30+
31+
first_missing_positive = fn(nums: [int...]) -> int {
32+
from 0 to nums.len(), i {
33+
if nums[i] <= 0 {
34+
nums[i] = nums.len() + 1
35+
}
36+
}
37+
38+
from 0 to nums.len(), i {
39+
num_abs = (nums[i]).abs()
40+
41+
if num_abs - 1 < nums.len() && nums[num_abs - 1] > 0 {
42+
(nums[num_abs - 1]) *= -1
43+
}
44+
}
45+
46+
from 0 to nums.len(), i {
47+
if nums[i] > 0 {
48+
return i + 1
49+
}
50+
}
51+
52+
return nums.len() + 1
53+
}
54+
55+
test_cases = map[[int...], int] {
56+
[1,2,0]: 3,
57+
[3,4,-1,1]: 2,
58+
[7,8,9,11,12]: 1,
59+
[50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1]: 51,
60+
[1,2,6,3,5,4]: 7,
61+
}.pairs()
62+
63+
print "🔵 Starting testing suite"
64+
65+
from 0 to test_cases.len(), i {
66+
[input, expected] = test_cases[i]
67+
68+
output = first_missing_positive(input)
69+
70+
if output != expected {
71+
print "🛑 Error in test suite: expected " + expected.to_str() + ", found: " + output.to_str()
72+
assert false
73+
}
74+
75+
print " ☐ Passed test #" + i
76+
}
77+
78+
print "✅ Passed " + test_cases.len() + " test cases"

0 commit comments

Comments
 (0)