1+ //! This module provides functionality to check if a given string is a pangram.
2+ //!
3+ //! A pangram is a sentence that contains every letter of the alphabet at least once.
4+ //! This module can distinguish between a non-pangram, a regular pangram, and a
5+ //! perfect pangram, where each letter appears exactly once.
6+
17use std:: collections:: HashSet ;
28
9+ /// Represents the status of a string in relation to the pangram classification.
310#[ derive( PartialEq , Debug ) ]
411pub enum PangramStatus {
512 NotPangram ,
613 Pangram ,
714 PerfectPangram ,
815}
916
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+ fn compute_letter_counts ( pangram_str : & str ) -> std:: collections:: HashMap < char , usize > {
18+ let mut letter_counts = std:: collections:: HashMap :: new ( ) ;
19+
20+ for ch in pangram_str
21+ . to_lowercase ( )
22+ . chars ( )
23+ . filter ( |c| c. is_ascii_alphabetic ( ) )
24+ {
25+ * letter_counts. entry ( ch) . or_insert ( 0 ) += 1 ;
26+ }
27+
28+ letter_counts
29+ }
30+
31+ /// Determines if the input string is a pangram, and classifies it as either a regular or perfect pangram.
1732///
18- /// ```
19- /// use the_algorithms_rust::string::is_pangram;
20- /// use std::collections::HashSet;
21- /// use the_algorithms_rust::string::PangramStatus;
33+ /// # Arguments
2234///
23- /// assert_eq!(
24- /// is_pangram("This is not a pangram"),
25- /// PangramStatus::NotPangram
26- /// );
35+ /// * `pangram_str` - A reference to the string slice to be checked for pangram status.
2736///
28- /// assert_eq!(
29- /// is_pangram("The quick brown fox jumps over the lazy dog"),
30- /// PangramStatus::Pangram
31- /// );
37+ /// # Returns
3238///
33- /// assert_eq!(
34- /// is_pangram("Mr. Jock, TV quiz PhD, bags few lynx"),
35- /// PangramStatus::PerfectPangram
36- /// );
37- /// ```
39+ /// A `PangramStatus` enum indicating whether the string is a pangram, and if so, whether it is a perfect pangram.
3840pub fn is_pangram ( pangram_str : & str ) -> PangramStatus {
39- let alphabet : HashSet < char > = "abcdefghijklmnopqrstuvwxyz" . chars ( ) . collect ( ) ;
41+ let letter_counts = compute_letter_counts ( pangram_str ) ;
4042
41- let letters_used: HashSet < char > = pangram_str
42- . to_lowercase ( )
43- . chars ( )
44- . filter ( |c| c. is_ascii_alphabetic ( ) )
45- . collect ( ) ;
43+ let alphabet: HashSet < char > = ( 'a' ..='z' ) . collect ( ) ;
44+ let used_letters: HashSet < _ > = letter_counts. keys ( ) . cloned ( ) . collect ( ) ;
4645
47- if letters_used != alphabet {
46+ if used_letters != alphabet {
4847 return PangramStatus :: NotPangram ;
49- } ;
48+ }
5049
51- if pangram_str . chars ( ) . filter ( |c| c . is_alphabetic ( ) ) . count ( ) == alphabet . len ( ) {
50+ if letter_counts . values ( ) . all ( | & count| count == 1 ) {
5251 PangramStatus :: PerfectPangram
5352 } else {
5453 PangramStatus :: Pangram
@@ -59,46 +58,35 @@ pub fn is_pangram(pangram_str: &str) -> PangramStatus {
5958mod tests {
6059 use super :: * ;
6160
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- ) ;
61+ macro_rules! pangram_tests {
62+ ( $( $name: ident: $tc: expr, ) * ) => {
63+ $(
64+ #[ test]
65+ fn $name( ) {
66+ let ( input, expected) = $tc;
67+ assert_eq!( is_pangram( input) , expected) ;
68+ }
69+ ) *
70+ } ;
9571 }
9672
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- ) ;
73+ pangram_tests ! {
74+ test_not_pangram_simple: ( "This is not a pangram" , PangramStatus :: NotPangram ) ,
75+ test_not_pangram_day: ( "today is a good day" , PangramStatus :: NotPangram ) ,
76+ test_not_pangram_almost: ( "this is almost a pangram but it does not have bcfghjkqwxy and the last letter" , PangramStatus :: NotPangram ) ,
77+ test_pangram_standard: ( "The quick brown fox jumps over the lazy dog" , PangramStatus :: Pangram ) ,
78+ test_pangram_boxer: ( "A mad boxer shot a quick, gloved jab to the jaw of his dizzy opponent" , PangramStatus :: Pangram ) ,
79+ test_pangram_discotheques: ( "Amazingly few discotheques provide jukeboxes" , PangramStatus :: Pangram ) ,
80+ test_pangram_zebras: ( "How vexingly quick daft zebras jump" , PangramStatus :: Pangram ) ,
81+ test_perfect_pangram_jock: ( "Mr. Jock, TV quiz PhD, bags few lynx" , PangramStatus :: PerfectPangram ) ,
82+ test_empty_string: ( "" , PangramStatus :: NotPangram ) ,
83+ test_repeated_letter: ( "aaaaa" , PangramStatus :: NotPangram ) ,
84+ test_non_alphabetic: ( "12345!@#$%" , PangramStatus :: NotPangram ) ,
85+ test_mixed_case_pangram: ( "ThE QuiCk BroWn FoX JumPs OveR tHe LaZy DoG" , PangramStatus :: Pangram ) ,
86+ test_perfect_pangram_with_symbols: ( "Mr. Jock, TV quiz PhD, bags few lynx!" , PangramStatus :: PerfectPangram ) ,
87+ test_long_non_pangram: ( & "a" . repeat( 1000 ) , PangramStatus :: NotPangram ) ,
88+ test_near_pangram_missing_one_letter: ( "The quick brown fox jumps over the lazy do" , PangramStatus :: NotPangram ) ,
89+ test_near_pangram_missing_two_letters: ( "The quick brwn f jumps ver the lazy dg" , PangramStatus :: NotPangram ) ,
90+ test_near_pangram_with_special_characters: ( "Th3 qu!ck brown f0x jumps 0v3r th3 l@zy d0g." , PangramStatus :: NotPangram ) ,
10391 }
10492}
0 commit comments