Skip to content

Commit 17d5dad

Browse files
Adin3vil02
andauthored
Pangram and Lipogram checker (rust-lang#660)
--------- Co-authored-by: Piotr Idzik <[email protected]>
1 parent 338c386 commit 17d5dad

File tree

4 files changed

+204
-0
lines changed

4 files changed

+204
-0
lines changed

DIRECTORY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,10 @@
302302
* [Jaro Winkler Distance](https://github.com/TheAlgorithms/Rust/blob/master/src/string/jaro_winkler_distance.rs)
303303
* [Knuth Morris Pratt](https://github.com/TheAlgorithms/Rust/blob/master/src/string/knuth_morris_pratt.rs)
304304
* [Levenshtein Distance](https://github.com/TheAlgorithms/Rust/blob/master/src/string/levenshtein_distance.rs)
305+
* [Lipogram](https://github.com/TheAlgorithms/Rust/blob/master/src/string/lipogram.rs)
305306
* [Manacher](https://github.com/TheAlgorithms/Rust/blob/master/src/string/manacher.rs)
306307
* [Palindrome](https://github.com/TheAlgorithms/Rust/blob/master/src/string/palindrome.rs)
308+
* [Pangram](https://github.com/TheAlgorithms/Rust/blob/master/src/string/pangram.rs)
307309
* [Rabin Karp](https://github.com/TheAlgorithms/Rust/blob/master/src/string/rabin_karp.rs)
308310
* [Reverse](https://github.com/TheAlgorithms/Rust/blob/master/src/string/reverse.rs)
309311
* [Run Length Encoding](https://github.com/TheAlgorithms/Rust/blob/master/src/string/run_length_encoding.rs)

src/string/lipogram.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use std::collections::HashSet;
2+
3+
/// Function that returns the letters that are missing from the input slice
4+
/// and are present in the English alphabet
5+
///
6+
/// ## Arguments
7+
///
8+
/// * `in_str` - the slice that will be checked for missing characters
9+
///
10+
fn compute_missing(in_str: &str) -> HashSet<char> {
11+
let alphabet: HashSet<char> = "abcdefghijklmnopqrstuvwxyz".chars().collect();
12+
13+
let letters_used: HashSet<char> = in_str
14+
.to_lowercase()
15+
.chars()
16+
.filter(|c| c.is_ascii_alphabetic())
17+
.collect();
18+
19+
alphabet.difference(&letters_used).cloned().collect()
20+
}
21+
22+
/// Function that checks if the slice is a lipogram with specific missing letters.
23+
/// Lipogram - sentence in which a particular letter or group of letters is avoided
24+
///
25+
/// ## Arguments
26+
///
27+
/// * `lipogram_str` - the slice that will be checked if is a lipogram with specific missing letters
28+
/// * `missing_chars` - the characters that has to be missing
29+
///
30+
/// ## Examples
31+
///
32+
/// ```
33+
/// use the_algorithms_rust::string::is_lipogram;
34+
/// use std::collections::HashSet;
35+
///
36+
/// assert!(
37+
/// !is_lipogram("The quick brown fox jumps over the lazy dog",
38+
/// &HashSet::from(['x'])
39+
/// ));
40+
///
41+
/// assert!(
42+
/// is_lipogram("The brown cat jumped over the lazy dog with a brick",
43+
/// &HashSet::from(['f', 'q', 's', 'x'])
44+
/// ));
45+
///
46+
/// assert!(
47+
/// !is_lipogram("The quick brown fox jumped over the lazy dog",
48+
/// &HashSet::from(['x'])
49+
/// ));
50+
/// ```
51+
pub fn is_lipogram(lipogram_str: &str, missing_chars: &HashSet<char>) -> bool {
52+
if !missing_chars.iter().all(|&c| c.is_lowercase()) {
53+
panic!("missing_chars should be all lowercase.")
54+
}
55+
56+
missing_chars == &compute_missing(lipogram_str)
57+
}
58+
59+
#[cfg(test)]
60+
mod tests {
61+
use super::*;
62+
macro_rules! test_lipogram {
63+
($($name:ident: $inputs:expr,)*) => {
64+
$(
65+
#[test]
66+
fn $name() {
67+
let (in_str, missing_chars, other_chars) = $inputs;
68+
assert_ne!(missing_chars, other_chars);
69+
assert_eq!(compute_missing(in_str), missing_chars);
70+
assert!(is_lipogram(in_str, &missing_chars));
71+
assert!(!is_lipogram(in_str, &other_chars));
72+
}
73+
)*
74+
}
75+
}
76+
77+
test_lipogram! {
78+
lipogram1: ("The quick brown fox jumps over the lazy dog", HashSet::from([]), HashSet::from(['a', 'b'])),
79+
lipogram2: ("Jackdaws love my big sphinx of quartz", HashSet::from([]), HashSet::from(['x'])),
80+
lipogram3: ("abcdefghijklmnopqrstuvwxyz", HashSet::from([]), HashSet::from(['x', 'y', 'z'])),
81+
lipogram4: ("Five quacking zephyrs jolt my wax bed", HashSet::from([]), HashSet::from(['a'])),
82+
lipogram5: ("The quick brown fox jumped over the lazy dog", HashSet::from(['s']), HashSet::from([])),
83+
lipogram6: ("abcdefghijklmnopqrstuvwxy", HashSet::from(['z']), HashSet::from(['y', 'z'])),
84+
lipogram7: ("The brown fox jumped over the lazy dog with a brick", HashSet::from(['q', 's']), HashSet::from(['b'])),
85+
lipogram8: ("ABCdefghijklmnopqrstuvwx", HashSet::from(['y', 'z']), HashSet::from(['a', 'b'])),
86+
}
87+
88+
#[test]
89+
#[should_panic]
90+
fn test_is_lipogram_panics_when_missing_chars_are_upper_case() {
91+
is_lipogram("abcdefghijklmnopqrstuvwx", &HashSet::from(['y', 'Z']));
92+
}
93+
}

src/string/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ mod hamming_distance;
88
mod jaro_winkler_distance;
99
mod knuth_morris_pratt;
1010
mod levenshtein_distance;
11+
mod lipogram;
1112
mod manacher;
1213
mod palindrome;
14+
mod pangram;
1315
mod rabin_karp;
1416
mod reverse;
1517
mod run_length_encoding;
@@ -30,8 +32,11 @@ pub use self::hamming_distance::hamming_distance;
3032
pub use self::jaro_winkler_distance::jaro_winkler_distance;
3133
pub use self::knuth_morris_pratt::knuth_morris_pratt;
3234
pub use self::levenshtein_distance::levenshtein_distance;
35+
pub use self::lipogram::is_lipogram;
3336
pub use self::manacher::manacher;
3437
pub use self::palindrome::is_palindrome;
38+
pub use self::pangram::is_pangram;
39+
pub use self::pangram::PangramStatus;
3540
pub use self::rabin_karp::rabin_karp;
3641
pub use self::reverse::reverse;
3742
pub use self::run_length_encoding::{run_length_decoding, run_length_encoding};

src/string/pangram.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
use std::collections::HashSet;
2+
3+
#[derive(PartialEq, Debug)]
4+
pub enum PangramStatus {
5+
NotPangram,
6+
Pangram,
7+
PerfectPangram,
8+
}
9+
10+
/// Function that checks if the slice is a pangram
11+
///
12+
/// ## Arguments
13+
///
14+
/// * `pangram_str` - the slice that will be checked if is a pangram
15+
///
16+
/// ## Examples
17+
///
18+
/// ```
19+
/// use the_algorithms_rust::string::is_pangram;
20+
/// use std::collections::HashSet;
21+
/// use the_algorithms_rust::string::PangramStatus;
22+
///
23+
/// assert_eq!(
24+
/// is_pangram("This is not a pangram"),
25+
/// PangramStatus::NotPangram
26+
/// );
27+
///
28+
/// assert_eq!(
29+
/// is_pangram("The quick brown fox jumps over the lazy dog"),
30+
/// PangramStatus::Pangram
31+
/// );
32+
///
33+
/// assert_eq!(
34+
/// is_pangram("Mr. Jock, TV quiz PhD, bags few lynx"),
35+
/// PangramStatus::PerfectPangram
36+
/// );
37+
/// ```
38+
pub fn is_pangram(pangram_str: &str) -> PangramStatus {
39+
let alphabet: HashSet<char> = "abcdefghijklmnopqrstuvwxyz".chars().collect();
40+
41+
let letters_used: HashSet<char> = pangram_str
42+
.to_lowercase()
43+
.chars()
44+
.filter(|c| c.is_ascii_alphabetic())
45+
.collect();
46+
47+
if letters_used != alphabet {
48+
return PangramStatus::NotPangram;
49+
};
50+
51+
if pangram_str.chars().filter(|c| c.is_alphabetic()).count() == alphabet.len() {
52+
PangramStatus::PerfectPangram
53+
} else {
54+
PangramStatus::Pangram
55+
}
56+
}
57+
58+
#[cfg(test)]
59+
mod tests {
60+
use super::*;
61+
62+
#[test]
63+
fn test_not_pangram() {
64+
assert_eq!(
65+
is_pangram("This is not a pangram"),
66+
PangramStatus::NotPangram
67+
);
68+
assert_eq!(is_pangram("today is a good day"), PangramStatus::NotPangram);
69+
assert_eq!(
70+
is_pangram(
71+
"this is almost a pangram but it does not have bcfghjkqwxy and the last letter"
72+
),
73+
PangramStatus::NotPangram
74+
);
75+
}
76+
77+
#[test]
78+
fn test_pangram() {
79+
assert_eq!(
80+
is_pangram("The quick brown fox jumps over the lazy dog"),
81+
PangramStatus::Pangram
82+
);
83+
assert_eq!(
84+
is_pangram("A mad boxer shot a quick, gloved jab to the jaw of his dizzy opponent"),
85+
PangramStatus::Pangram
86+
);
87+
assert_eq!(
88+
is_pangram("Amazingly few discotheques provide jukeboxes"),
89+
PangramStatus::Pangram
90+
);
91+
assert_eq!(
92+
is_pangram("How vexingly quick daft zebras jump"),
93+
PangramStatus::Pangram
94+
);
95+
}
96+
97+
#[test]
98+
fn test_perfect_pangram() {
99+
assert_eq!(
100+
is_pangram("Mr. Jock, TV quiz PhD, bags few lynx"),
101+
PangramStatus::PerfectPangram
102+
);
103+
}
104+
}

0 commit comments

Comments
 (0)