Just started learning Rust and here's a program that has caused me some agony to implement in Rust. This is very easy to implement in C++, but Rust's borrow checker is causing all sorts of trouble. My program tries to solve the following challenge:
You are given an integer array
nums
and an integerk
.In one operation, you can pick two numbers from the array whose sum equals
k
and remove them from the array.Return the maximum number of operations you can perform on the array.
The algorithm I'm using is the obvious one:
- Scan over the input making a hash map of the counts of each integer in the input.
- Loop over the integers and for each
n
check if the count ofn
andk - n
is more than 0 (more than 1 ifn
andk-n
are equal). - If yes, decrease counts of both integers and increment the result.
My implementation in Rust is the following, which seems quite ugly:
use std::collections::HashMap;
use std::collections::hash_map::Entry;
impl Solution {
pub fn max_operations(nums: Vec<i32>, k: i32) -> i32 {
let mut result = 0;
// Keep track of counts of each integer.
let mut counts = HashMap::<i32,i32>::new();
for n in nums.iter() {
let count = counts.entry(*n).or_insert(0);
*count += 1;
}
// Loop over each element and check if it has a matching pair to remove.
for n in nums.iter() {
if *n == k - *n {
if *counts.entry(*n).or_insert(0) < 2 {
continue;
}
result += 1;
*counts.entry(*n).or_insert(0) -= 2;
continue;
}
match counts.entry(*n) {
Entry::Occupied(o) => {
if *o.get() < 1 {
continue;
}
match counts.entry(k - *n) {
Entry::Occupied(o) => {
if *o.get() < 1 {
continue;
}
},
Entry::Vacant(_) => continue
}
},
Entry::Vacant(_) => continue
}
result += 1;
*counts.entry(*n).or_insert(0) -= 1;
*counts.entry(k - *n).or_insert(0) -= 1;
}
return result;
}
}
What I would like to do is something like the following instead of the match block and everything that comes after it:
if let counts.get(*n) > 0 && let counts.get(k - *n) > 0 {
*counts.entry(*n).or_insert(0) -= 1;
*counts.entry(k - *n).or_insert(0) -= 1;
}
This is not possible and it would also cause unnecessary zeroes to be inserted in the hashmap for elements not present.
Does Rust have any way of writing code like this in a more compact way?