Skip to content

Instantly share code, notes, and snippets.

@cite-reader
Created September 30, 2015 17:57
Show Gist options
  • Save cite-reader/ec327575318e8c67f6cf to your computer and use it in GitHub Desktop.
Save cite-reader/ec327575318e8c67f6cf to your computer and use it in GitHub Desktop.
Cracking the Coding Interview exercise: baby names
use std::collections::HashMap;
pub fn aggregate_baby_names<'a>(name_frequencies: &[(&'a str, usize)],
name_mappings: &[(&'a str, &'a str)])
-> Vec<(&'a str, usize)>
{
let mut disambiguation = HashMap::with_capacity(name_mappings.len());
let mut coalesced_index = 0;
let mut canonical_names = Vec::with_capacity(name_frequencies.len());
for &(syn1, syn2) in name_mappings {
// Finesse around the borrow checker with a wee command interpreter
match match (disambiguation.get(syn1), disambiguation.get(syn2)) {
(None, None) => Action::InsertBoth,
(Some(&i), None) => Action::InsertRight(i),
(None, Some(&i)) => Action::InsertLeft(i),
(Some(_), Some(_)) => Action::DoNothing
} {
Action::InsertBoth => {
disambiguation.insert(syn1, coalesced_index);
disambiguation.insert(syn2, coalesced_index);
canonical_names.push(syn1);
coalesced_index += 1;
},
Action::InsertLeft(i) => { disambiguation.insert(syn1, i); },
Action::InsertRight(i) => { disambiguation.insert(syn2, i); },
Action::DoNothing => ()
}
}
let mut name_counts = vec![0; name_frequencies.len()];
for &(name, frequency) in name_frequencies {
let index = *disambiguation.entry(name).or_insert_with(|| {
let i = coalesced_index;
canonical_names.push(name);
coalesced_index += 1;
i
});
name_counts[index] += frequency;
}
canonical_names.iter()
.map(|&name| (name, name_counts[*disambiguation.get(name).unwrap()]))
.collect()
}
// Commands for the borrowchecker-finessing interpreter. This could be more
// general, I don't care.
enum Action {
InsertBoth,
InsertLeft(usize),
InsertRight(usize),
DoNothing
}
// Doesn't actually pass because I selected a different canonical name than the
// textbook, and I'm too lazy to make a non-brittle test. Also it's one AM crap
#[test]
fn the_example() {
let aggregated = aggregate_baby_names(
&vec![("John", 15), ("Jon", 12), ("Chris", 13), ("Kris", 4),
("Christopher", 19)],
&vec![("Jon", "John"), ("John", "Johnny"), ("Chris", "Kris"),
("Chris", "Christopher")]);
assert_eq!(aggregated, vec![("John", 27), ("Kris", 36)]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment