#![allow(unused)]
fn main() {
use std::collections::HashSet;
#[derive(Debug, Default)]
pub struct Difference<'a, 'b> {
first_only: Vec<&'a str>,
second_only: Vec<&'b str>,
}
pub fn words(sentence: &str) -> HashSet<&str> {
sentence
.split(' ')
.filter(|word| !word.is_empty()) // this makes sure we don't have empty words
.collect()
}
pub fn find_difference<'a, 'b>(sentence1: &'a str, sentence2: &'b str) -> Difference<'a, 'b> {
// lifetime annotations here are not required, added for clarity
let sentence_1_words: HashSet<&'a str> = words(sentence1);
let sentence_2_words: HashSet<&'b str> = words(sentence2);
let mut diff = Difference::default();
for word in &sentence_1_words {
if !sentence_2_words.contains(word) {
diff.first_only.push(word)
}
}
for word in &sentence_2_words {
if !sentence_1_words.contains(word) {
diff.second_only.push(word)
}
}
// sorting simplifies the equality assertions below
diff.first_only.sort();
diff.second_only.sort();
diff
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_completely_disjoint_sentences() {
let sentence1 = "apple banana cherry";
let sentence2 = "dog elephant fox";
let result = find_difference(sentence1, sentence2);
assert_eq!(result.first_only, vec!["apple", "banana", "cherry"]);
assert_eq!(result.second_only, vec!["dog", "elephant", "fox"]);
}
#[test]
fn test_identical_sentences() {
let sentence1 = "apple banana cherry";
let sentence2 = "apple banana cherry";
let result = find_difference(sentence1, sentence2);
assert!(result.first_only.is_empty());
assert!(result.second_only.is_empty());
}
#[test]
fn test_some_common_words() {
let sentence1 = "apple banana cherry";
let sentence2 = "banana cherry dog";
let result = find_difference(sentence1, sentence2);
assert_eq!(result.first_only, vec!["apple"]);
assert_eq!(result.second_only, vec!["dog"]);
}
#[test]
fn test_empty_sentences() {
let sentence1 = "";
let sentence2 = "";
let result = find_difference(sentence1, sentence2);
assert!(result.first_only.is_empty());
assert!(result.second_only.is_empty());
}
#[test]
fn test_one_empty_sentence() {
let sentence1 = "apple banana cherry";
let sentence2 = "";
let result = find_difference(sentence1, sentence2);
assert_eq!(result.first_only, vec!["apple", "banana", "cherry"]);
assert!(result.second_only.is_empty());
}
#[test]
fn test_drop_first_sentence_before_second() {
let sentence1 = String::from("A long sentence that takes up a lot of memory. We want to drop it as soon as possible.");
let sentence2 =
String::from("A short sentence, we are ok with keeping around for a while.");
let Difference {
first_only,
second_only,
} = find_difference(&sentence1, &sentence2);
#[rustfmt::skip]
assert_eq!(
first_only,
vec! ["We", "as", "drop", "it", "long", "lot", "memory.", "of", "possible.", "sentence", "soon", "takes", "that", "to", "up", "want"],
);
drop(sentence1);
#[rustfmt::skip]
assert_eq!(
second_only,
vec! ["are", "around", "for", "keeping", "ok", "sentence,", "short", "we", "while.", "with"],
);
}
}
}