Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f9f6eb1

Browse files
committed
cleanup using iterator magic
1 parent dafd95b commit f9f6eb1

File tree

2 files changed

+53
-60
lines changed

2 files changed

+53
-60
lines changed

‎src/misc.rs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,15 @@ impl PiecewiseLinearFn {
7070

7171
fn update_envelope(&mut self) {
7272
self.recent_lines.extend(self.sorted_lines.drain(..));
73-
self.recent_lines.sort_unstable_by(asserting_cmp);
73+
self.recent_lines.sort_unstable_by(asserting_cmp);// TODO: switch to O(n) merge
7474
self.intersections.clear();
7575

7676
for (new_m, new_b) in self.recent_lines.drain(..).rev() {
7777
while let Some(&(last_m, last_b)) = self.sorted_lines.last() {
7878
// If slopes are equal, get rid of the old line as its intercept is higher
7979
if (new_m - last_m).abs() > 1e-9 {
8080
let intr = (new_b - last_b) / (last_m - new_m);
81-
if self.intersections.last().map(|&x| x < intr).unwrap_or(true) {
81+
if self.intersections.last() < Some(&intr) {
8282
self.intersections.push(intr);
8383
break;
8484
}
@@ -92,9 +92,9 @@ impl PiecewiseLinearFn {
9292

9393
fn eval_helper(&self, x: f64) -> f64 {
9494
let idx = slice_lower_bound(&self.intersections, &x);
95-
std::iter::once(self.sorted_lines.get(idx))
96-
.flatten()
97-
.chain(self.recent_lines.iter())
95+
self.recent_lines
96+
.iter()
97+
.chain(self.sorted_lines.get(idx))
9898
.map(|&(m, b)| m * x + b)
9999
.min_by(asserting_cmp)
100100
.unwrap_or(1e18)

‎src/string_proc.rs‎

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,12 @@ impl<'a, C: Eq> Matcher<'a, C> {
6161
///
6262
/// ```
6363
/// use contest_algorithms::string_proc::Matcher;
64-
/// let utf8_string = "hello";
65-
///
66-
/// let match_from_byte_literal = Matcher::new(b"hello");
67-
///
68-
/// let match_from_bytes = Matcher::new(utf8_string.as_bytes());
69-
///
64+
/// let byte_string: &[u8] = b"hello";
65+
/// let utf8_string: &str = "hello";
7066
/// let vec_char: Vec<char> = utf8_string.chars().collect();
67+
///
68+
/// let match_from_byte_literal = Matcher::new(byte_string);
69+
/// let match_from_utf8 = Matcher::new(utf8_string.as_bytes());
7170
/// let match_from_chars = Matcher::new(&vec_char);
7271
///
7372
/// let vec_int = vec![4, -3, 1];
@@ -93,24 +92,24 @@ impl<'a, C: Eq> Matcher<'a, C> {
9392
Self { pattern, fail }
9493
}
9594

96-
/// KMP algorithm, sets match_lens[i] = length of longest prefix of pattern
95+
/// KMP algorithm, sets @return[i] = length of longest prefix of pattern
9796
/// matching a suffix of text[0..=i].
98-
pub fn kmp_match(&self, text: &[C]) -> Vec<usize> {
99-
let mut match_lens = Vec::with_capacity(text.len());
97+
pub fn kmp_match(&self, text: impl IntoIterator<Item = C>) -> Vec<usize> {
10098
let mut len = 0;
101-
for ch in text {
102-
if len == self.pattern.len() {
103-
len = self.fail[len - 1];
104-
}
105-
while len > 0 && self.pattern[len] != *ch {
106-
len = self.fail[len - 1];
107-
}
108-
if self.pattern[len] == *ch {
109-
len += 1;
110-
}
111-
match_lens.push(len);
112-
}
113-
match_lens
99+
text.into_iter()
100+
.map(|ch| {
101+
if len == self.pattern.len() {
102+
len = self.fail[len - 1];
103+
}
104+
while len > 0 && self.pattern[len] != ch {
105+
len = self.fail[len - 1];
106+
}
107+
if self.pattern[len] == ch {
108+
len += 1;
109+
}
110+
len
111+
})
112+
.collect()
114113
}
115114
}
116115

@@ -141,7 +140,7 @@ impl<C: std::hash::Hash + Eq> MultiMatcher<C> {
141140

142141
/// Precomputes the automaton that allows linear-time string matching.
143142
/// If there are duplicate patterns, all but one copy will be ignored.
144-
pub fn new(patterns: Vec<impl IntoIterator<Item = C>>) -> Self {
143+
pub fn new(patterns: implIntoIterator<Item = impl IntoIterator<Item = C>>) -> Self {
145144
let mut trie = Trie::default();
146145
let pat_nodes: Vec<usize> = patterns.into_iter().map(|pat| trie.insert(pat)).collect();
147146

@@ -171,16 +170,16 @@ impl<C: std::hash::Hash + Eq> MultiMatcher<C> {
171170
}
172171
}
173172

174-
/// Aho-Corasick algorithm, sets match_nodes[i] = node corresponding to
173+
/// Aho-Corasick algorithm, sets @return[i] = node corresponding to
175174
/// longest prefix of some pattern matching a suffix of text[0..=i].
176-
pub fn ac_match(&self, text: &[C]) -> Vec<usize> {
177-
let mut match_nodes = Vec::with_capacity(text.len());
175+
pub fn ac_match(&self, text: impl IntoIterator<Item = C>) -> Vec<usize> {
178176
let mut node = 0;
179-
for ch in text {
180-
node = Self::next(&self.trie, &self.fail, node, &ch);
181-
match_nodes.push(node);
182-
}
183-
match_nodes
177+
text.into_iter()
178+
.map(|ch| {
179+
node = Self::next(&self.trie, &self.fail, node, &ch);
180+
node
181+
})
182+
.collect()
184183
}
185184

186185
/// For each non-empty match, returns where in the text it ends, and the index
@@ -235,9 +234,9 @@ impl SuffixArray {
235234
}
236235

237236
/// Suffix array construction in O(n log n) time.
238-
pub fn new(text: &[u8]) -> Self {
239-
let n = text.len();
240-
let init_rank = text.iter().map(|&ch| ch asusize).collect::<Vec<_>>();
237+
pub fn new(text: implIntoIterator<Item = u8>) -> Self {
238+
let init_rank = text.into_iter().map(|ch| ch asusize).collect::<Vec<_>>();
239+
let n = init_rank.len();
241240
let mut sfx = Self::counting_sort(0..n, &init_rank, 256);
242241
let mut rank = vec![init_rank];
243242
// Invariant at the start of every loop iteration:
@@ -291,7 +290,7 @@ impl SuffixArray {
291290
/// # Panics
292291
///
293292
/// Panics if text is empty.
294-
pub fn palindromes<T:Eq>(text: &[T]) -> Vec<usize> {
293+
pub fn palindromes(text: &[implEq]) -> Vec<usize> {
295294
let mut pal = Vec::with_capacity(2 * text.len() - 1);
296295
pal.push(1);
297296
while pal.len() < pal.capacity() {
@@ -339,27 +338,21 @@ mod test {
339338

340339
#[test]
341340
fn test_kmp_matching() {
342-
let text = b"banana";
343-
let pattern = b"ana";
341+
let pattern = "ana";
342+
let text = "banana";
344343

345-
let matches = Matcher::new(pattern).kmp_match(text);
344+
let matches = Matcher::new(pattern.as_bytes()).kmp_match(text.bytes());
346345

347346
assert_eq!(matches, vec![0, 1, 2, 3, 2, 3]);
348347
}
349348

350349
#[test]
351350
fn test_ac_matching() {
352-
let text = b"banana bans, apple benefits.";
353-
let dict = vec![
354-
"banana".bytes(),
355-
"benefit".bytes(),
356-
"banapple".bytes(),
357-
"ban".bytes(),
358-
"fit".bytes(),
359-
];
360-
361-
let matcher = MultiMatcher::new(dict);
362-
let match_nodes = matcher.ac_match(text);
351+
let dict = vec!["banana", "benefit", "banapple", "ban", "fit"];
352+
let text = "banana bans, apple benefits.";
353+
354+
let matcher = MultiMatcher::new(dict.iter().map(|s| s.bytes()));
355+
let match_nodes = matcher.ac_match(text.bytes());
363356
let end_pos_and_id = matcher.get_end_pos_and_pat_id(&match_nodes);
364357

365358
assert_eq!(
@@ -370,11 +363,11 @@ mod test {
370363

371364
#[test]
372365
fn test_suffix_array() {
373-
let text1 = b"bobocel";
374-
let text2 = b"banana";
366+
let text1 = "bobocel";
367+
let text2 = "banana";
375368

376-
let sfx1 = SuffixArray::new(text1);
377-
let sfx2 = SuffixArray::new(text2);
369+
let sfx1 = SuffixArray::new(text1.bytes());
370+
let sfx2 = SuffixArray::new(text2.bytes());
378371

379372
assert_eq!(sfx1.sfx, vec![0, 2, 4, 5, 6, 1, 3]);
380373
assert_eq!(sfx2.sfx, vec![5, 3, 1, 0, 4, 2]);
@@ -393,9 +386,9 @@ mod test {
393386

394387
#[test]
395388
fn test_palindrome() {
396-
let text = b"banana";
389+
let text = "banana";
397390

398-
let pal_len = palindromes(text);
391+
let pal_len = palindromes(text.as_bytes());
399392

400393
assert_eq!(pal_len, vec![1, 0, 1, 0, 3, 0, 5, 0, 3, 0, 1]);
401394
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /