1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#![cfg_attr(feature = "test", feature(test))]
#[cfg(feature = "nightly")]
#[cfg(test)] extern crate test;
const VOWELS: &'static str = "bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ";
const CONSONANTS: &'static str = "aeiouyAEIOUY";
fn stem(word: &str) -> (String, String) {
let start = word.chars()
.take_while(|c| VOWELS.contains(*c))
.collect::<String>();
let end = word.chars()
.skip(start.len())
.collect::<String>();
(start, end)
}
fn stem2(word: &str) -> (&str, &str) {
let pattern = |c: char| CONSONANTS.contains(c);
let index = word.find(pattern).unwrap_or(0);
(&word[0..index], &word[index..])
}
pub fn zummi_naive(phrase: &str) -> Option<String> {
let mut words = phrase.split_whitespace();
let (first, second) = (words.next(), words.next());
if let (Some(first), Some(second)) = (first, second) {
let (f, irst) = stem(first);
let (s, econd) = stem(second);
return Some(s + &irst + " " + &f + &econd);
}
None
}
pub fn zummi(phrase: &str) -> Option<String> {
let mut words = phrase.split_whitespace();
let (first, second) = (words.next(), words.next());
if let (Some(first), Some(second)) = (first, second) {
let (f, irst) = stem2(first);
let (s, econd) = stem2(second);
return Some(
String::with_capacity(f.len() + irst.len() + s.len() + econd.len()) +
&s + &irst + " " + &f + &econd
);
}
None
}
#[cfg(test)]
#[cfg(feature = "nightly")]
mod tests {
use super::*;
use test::black_box;
use test::Bencher;
#[bench]
fn zummi_bench(b: &mut Bencher) {
b.iter(|| {
let mix = zummi("stinkender fisch");
black_box(mix);
});
}
#[bench]
fn zummi_naiv_bench(b: &mut Bencher) {
b.iter(|| {
let mix = zummi_naiv("stinkender fisch");
black_box(mix);
});
}
}