Hello there!
Spoilers ahead for the solutions of Advent of Code 2020 - Day 01 in Rust. The full solution is available here.
If you are unfamiliar, Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like. People use them as a speed contest, interview prep, company training, university coursework, practice problems, or to challenge each other.
The puzzle usually has a story, but we’d be looking at the actual problem we need to solve.
Part 1: Given an array of numbers, find two values that sum to 2020. Once you find the two values, multiply them. This might sound familiar to many, and if it does - yes, its the popular Two Sum problem for folks used to leetcode-ing.
The solution looks something like this:
/** The algorithm: * initialize a map * go through the array of the elements ie. entries, and calculate its complement. * insert (complement, index) into the map if it doesnt exist. * if it doest exist, yay! we've found the indices that sum to 2020. Get the values from entries at those indices and return. **/
let mut map: HashMap<i32, usize> = HashMap::new(); // `.iter()` returns an iterator, and `.enumerate` returns a tuple of (index, value) of every entry. for (index, entry) in entries.iter().enumerate() { let complement = TARGET_SUM - entry; // NOTE: `HashMap.contains_key` and `HashMap.get` take a reference and return a reference. if map.contains_key(&complement) { let chosen_one_index = map.get(&complement).unwrap(); let chosen_two_index = &index;
// we need to a deref here as `chosen_one_index` returns a pointer to a pointer. let chosen_one = entries.get(*chosen_one_index as usize).unwrap(); let chosen_two = entries.get(*chosen_two_index as usize).unwrap();
println!("2 entries that sum to 2020: {}, {}", chosen_one, chosen_two); println!("Product Of two entries: {}", chosen_one * chosen_two); } else { map.insert(*entry, index); } }
Part 1: Extended
Given an array of numbers, find three values that sum to 2020, and multiply them. The naive solution for this using a nested loop and then trying to find all possible triplets that sum to 2020. However, the complexity for something like that would be O(n^3)
and we probably don’t want that.
A better solution could be to sort the array, and then use a Two pointer approach with a sliding window approach. The complexity for this solution would be O(n log(n))
worst case, due to the sort.
entries.sort();
for (i, entry) in entries.iter().enumerate() { // initialize the `low` pointer to the start, `high` to the end of the array. // the window in the beginning, is the entire array let mut low = i + 1; let mut high = entries.len() - 1;
// bounds check while low < high { // calculate sum at the current index let current_sum = &entries[low] + &entries[high] + entry; // since there's only one such entry based on the question, we can break here. // otherwise we'd typically push these into a Vec<u8> | HashSet<u8> to deal with duplicates. if current_sum == TARGET_SUM { println!( "3 Entries that sum to 2020: {}, {}, {}", &entries[low], &entries[high], entry );
println!( "Product of 3 Entries: {}", &entries[low] * &entries[high] * entry );
break;
} else if current_sum < TARGET_SUM { // since the array is sorted, if the current sum is lesser we need to minimize / slide the window from the left. // so we increment the lower bound. low += 1; } else { // the current sum is greater, lets reduce the upper bound instead. high -= 1; } } }