Решение на Search от Михаил Младенов

Обратно към всички решения

Към профила на Михаил Младенов

Резултати

  • 15 точки от тестове
  • 3 бонус точки
  • 18 точки общо
  • 5 успешни тест(а)
  • 0 неуспешни тест(а)

Код

pub struct WordIterator<'a> {
iter: ::std::str::CharIndices<'a>,
}
impl<'a> WordIterator<'a> {
pub fn new(text: &'a str) -> Self {
WordIterator { iter: text.char_indices() }
}
}
impl<'a> Iterator for WordIterator<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<Self::Item> {
let slice = self.iter.as_str();
let mut c = self.iter.next();
if c.is_none() {
return None;
}
let idx_offset = c.unwrap().0;
while c.is_some() && !c.unwrap().1.is_alphabetic() {
// Пропускаме всички небукви
c = self.iter.next();
}
if c.is_none() {
return None;
}
let start_idx = c.unwrap().0;
while c.is_some() && c.unwrap().1.is_alphabetic() {
c = self.iter.next();
}
if c.is_none() {
Some(slice.get((start_idx - idx_offset)..).unwrap())
} else {
Some(
slice
.get((start_idx - idx_offset)..(c.unwrap().0 - idx_offset))
.unwrap(),
)
}

Тук няма нужда да get-ваш, ако след това директно unwrap-ваш. По-лесно е да slice-неш директно:

if c.is_none() {
    Some(&slice[(start_idx - idx_offset)..])
} else {
    Some(&slice[(start_idx - idx_offset)..(c.unwrap().0 - idx_offset)])
}
}
}
pub fn extract_words(text: &str) -> Vec<String> {
WordIterator::new(text).map(String::from).collect()
}
use std::collections::HashSet;
use std::collections::HashMap;
pub struct TextIndex {
text: Vec<String>,
index: HashMap<String, Vec<usize>>,
}
impl TextIndex {
pub fn new() -> Self {
const init_cap: usize = 1 << 13;
TextIndex {
text: Vec::with_capacity(init_cap),
index: HashMap::with_capacity(init_cap),
}
}
pub fn push(&mut self, text: &str) {
let idx = self.text.len();
self.text.push(String::from(text));
for word in WordIterator::new(text) {
// Това не работи, защото мача взима мютъбъл реферънс към индекс и после не
// можем да инсъртнем :/ ...
/*
match self.index.get_mut(word) {
Some(v) => {
v.push(idx);
}
None => {
const init_cap: usize = 1 << 8;
let mut v = Vec::<usize>::with_capacity(init_cap);
v.push(idx);
self.index.insert(String::from(word), v);
}
}
*/

Благодаря за разяснението. Този метод не го бях видял. Точно това се питах, когато писах тази задача, дали има нещо, което изпускам или трябва да минавам през цялото това неудобство всеки път, когато правя подобна операция с хеш таблици.

// Ще трябва да направя следния грозен хак:
let mut inserted = false;
{
let indices = self.index.get_mut(word);
if indices.is_some() {
indices.unwrap().push(idx);
inserted = true;
}
}
if !inserted {
const init_cap: usize = 1 << 8;
let mut v = Vec::<usize>::with_capacity(init_cap);
v.push(idx);
self.index.insert(String::from(word), v);
}
}
}
pub fn search(&self, query: &str) -> HashSet<&str> {
let mut result = HashSet::<&str>::new();
for word in WordIterator::new(query) {
match self.index.get(word) {
Some(v) => {
for i in 0..v.len() {
result.insert(&self.text[v[i]]);
}
}
None => {}
}
}
result
}
}

Лог от изпълнението

Compiling solution v0.1.0 (file:///tmp/d20180105-6053-72o69k/solution)
warning: constant `init_cap` should have an upper case name such as `INIT_CAP`
  --> src/lib.rs:66:9
   |
66 |         const init_cap: usize = 1 << 13;
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(non_upper_case_globals)] on by default

warning: constant `init_cap` should have an upper case name such as `INIT_CAP`
   --> src/lib.rs:109:17
    |
109 |                 const init_cap: usize = 1 << 8;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: constant `init_cap` should have an upper case name such as `INIT_CAP`
  --> src/lib.rs:66:9
   |
66 |         const init_cap: usize = 1 << 13;
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(non_upper_case_globals)] on by default

warning: constant `init_cap` should have an upper case name such as `INIT_CAP`
   --> src/lib.rs:109:17
    |
109 |                 const init_cap: usize = 1 << 8;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    Finished dev [unoptimized + debuginfo] target(s) in 6.8 secs
     Running target/debug/deps/solution-3f98bfa5c86a5dd9

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-3d9e4ea2eafbbc82

running 5 tests
test solution_test::test_extract_words_basic ... ok
test solution_test::test_extract_words_extra ... ok
test solution_test::test_search_multiple_words ... ok
test solution_test::test_search_special_cases ... ok
test solution_test::test_search_word ... ok

test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

История (1 версия и 4 коментара)

Михаил качи първо решение на 22.12.2017 01:54 (преди над 7 години)

Добра работа! Оставил съм ти някакви коментари за това как би могъл да опростиш малко кода, но независимо от тях, си се справил със задачата, и с бонус условията. Получаваш 3 бонус точки, както сме обещали.