Решение на Text Info от Радослав Върбанов

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

Към профила на Радослав Върбанов

Резултати

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

Код

pub struct TextInfo {
text: String,
}
impl TextInfo {
pub fn new(s: &str) -> Self {
TextInfo { text: String::from(s) }
}
pub fn char_count(&self) -> usize {
return self.text.chars().count();
}
pub fn alphabetic_count(&self) -> usize {
return self.text.chars().filter(
|&x| x.is_alphabetic()
).count();
}
pub fn latin_letter_count(&self) -> usize {
return self.text.chars().map(|x| self.latin_char(x)).filter(|&x| x)
.count();

Вместо .map(...).filter, в случая мисля, че директно можеш да ползваш filter. А ако latin_char не ти е дефинирано върху self, а в глобалния scope (забележи, че това е безопасно -- ако я дефинираш с fn, вместо с pub fn, тя ще бъде видима само в този модул), то ще можеш да напишеш това: self.text.chars().filter(latin_char).count().

}
pub fn cyrillic_letter_count(&self) -> usize {
return self.text.chars().map(|x| self.cyrillic_char(x)).filter(|&x| x)
.count();
}
pub fn word_count(&self) -> usize {
let words: Vec<&str> = self.text.split(
|c: char| !(self.latin_char(c) || self.cyrillic_char(c))
).collect();
return words.iter().filter(|x| x.len() > 0).count();

Не ти трябва да алокираш вектор тук. Мисля, че спокойно можеш вместо .collect(), да продължиш със .filter(...).count(). Това ти избягва алокирането на нова динамична памет за вектора, която ще се използва само за броене.

}
pub fn sentence_count(&self) -> usize {
let mut count: usize = 0;
let chunks: Vec<&str> = self.text.split(
|c: char| !self.punctuation(c)
).collect();
for i in 0..(chunks.len() - 1) {
if chunks[i].len() == 0 && chunks[i + 1].len() > 0 && self.punctuation(chunks[i + 1].chars().nth(0).unwrap()) {
count = count + 1;
}
}

Този код като че ли се получава малко сложничък. И аз пробвах в един момент с нещо такова, и си мисля, че е по-лесно просто да се направи императивно:

pub fn sentence_count(&self) -> usize {
    let mut count = 0;
    let mut in_sentence = false;

    for c in self.text.chars() {
        if !in_sentence && !is_sentence_terminator(c) {
            in_sentence = true;
        } else if in_sentence && is_sentence_terminator(c) {
            in_sentence = false;
            count += 1;
        }
    }
    count
}

Алтернативно, ето какво измислих като по-fancy решение:

pub fn sentence_count(&self) -> usize {
    self.text
        .split_terminator(is_sentence_terminator)
        .filter(|s| s.len() > 0)
        .count()
}

Нали, това в категория "да видиш някакви други интересни решения".

return count;
}
pub fn emotion(&self) -> String {
let mut wonder: usize = 0;
let mut shock: usize = 0;
let mut meh: usize = 0;
let chunks: Vec<&str> = self.text.split(
|c: char| !self.punctuation(c)
).collect();
for i in 0..(chunks.len() - 1) {
if chunks[i].len() == 0 && chunks[i + 1].len() > 0 && self.punctuation(chunks[i + 1].chars().nth(0).unwrap()) {
if chunks[i + 1].chars().nth(0) == Some('?') {
wonder = wonder + 1;
}
else if chunks[i + 1].chars().nth(0) == Some('!') {
shock = shock + 1;
}
else {
meh = meh + 1;
}
}
}
if wonder > shock && wonder > meh {
return String::from("🤔");
}
else if shock > wonder && shock > meh {
return String::from("😮");
}
else {
return String::from("😐");
}
}
fn punctuation(&self, c: char) -> bool {
return c == '.' || c == '?' || c == '!';
}
fn latin_char(&self, c: char) -> bool {
return match c {
'a'...'z' => true,
'A'...'Z' => true,
_ => false}
}
fn cyrillic_char(&self, c: char) -> bool {
return match c {
'а'...'я' => true,
'А'...'Я' => true,
_ => false}
}
}

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

Compiling solution v0.1.0 (file:///tmp/d20171026-5817-js3pqr/solution)
invalid expression
!4836 = !DIExpression(6, 34, 0, 6)
invalid expression
!4837 = !DIExpression(6, 34, 0, 6)
    Finished dev [unoptimized + debuginfo] target(s) in 3.78 secs
     Running target/debug/deps/solution-f5dd4e94aa395cae

running 0 tests

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

     Running target/debug/deps/solution_test-c3b431457e2a7a27

running 15 tests
test solution_test::test_alpha_count ... ok
test solution_test::test_alpha_count_2 ... ok
test solution_test::test_char_count ... ok
test solution_test::test_cyrillic_letter_count ... ok
test solution_test::test_emotions ... ok
test solution_test::test_emotions_repeated_punctuation ... ok
test solution_test::test_empty_string ... ok
test solution_test::test_latin_letter_count ... ok
test solution_test::test_sentence_count ... ok
test solution_test::test_sentence_count_2 ... ok
test solution_test::test_triple_dots_count ... ok
test solution_test::test_unicode_char_count ... ok
test solution_test::test_word_count ... ok
test solution_test::test_word_count_2 ... ok
test solution_test::test_word_count_3 ... ok

test result: ok. 15 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

История (2 версии и 3 коментара)

Радослав качи първо решение на 25.10.2017 14:25 (преди почти 8 години)

Радослав качи решение на 25.10.2017 22:20 (преди почти 8 години)

pub struct TextInfo {
text: String,
}
impl TextInfo {
pub fn new(s: &str) -> Self {
TextInfo { text: String::from(s) }
}
pub fn char_count(&self) -> usize {
return self.text.chars().count();
}
pub fn alphabetic_count(&self) -> usize {
return self.text.chars().filter(
|&x| x.is_alphabetic()
).count();
}
pub fn latin_letter_count(&self) -> usize {
return self.text.chars().map(|x| self.latin_char(x)).filter(|&x| x)
.count();

Вместо .map(...).filter, в случая мисля, че директно можеш да ползваш filter. А ако latin_char не ти е дефинирано върху self, а в глобалния scope (забележи, че това е безопасно -- ако я дефинираш с fn, вместо с pub fn, тя ще бъде видима само в този модул), то ще можеш да напишеш това: self.text.chars().filter(latin_char).count().

}
pub fn cyrillic_letter_count(&self) -> usize {
return self.text.chars().map(|x| self.cyrillic_char(x)).filter(|&x| x)
.count();
}
pub fn word_count(&self) -> usize {
let words: Vec<&str> = self.text.split(
|c: char| !(self.latin_char(c) || self.cyrillic_char(c))
).collect();
return words.iter().filter(|x| x.len() > 0).count();

Не ти трябва да алокираш вектор тук. Мисля, че спокойно можеш вместо .collect(), да продължиш със .filter(...).count(). Това ти избягва алокирането на нова динамична памет за вектора, която ще се използва само за броене.

}
pub fn sentence_count(&self) -> usize {
- let punctuation: Vec<&str> = self.text.split(
+ let mut count: usize = 0;
+
+ let chunks: Vec<&str> = self.text.split(
|c: char| !self.punctuation(c)
).collect();
- let endings_count: usize = punctuation.iter().filter(|x| x.len() > 0).count();
-
- if punctuation.len() == endings_count {
- return 0;
+ for i in 0..(chunks.len() - 1) {
+ if chunks[i].len() == 0 && chunks[i + 1].len() > 0 && self.punctuation(chunks[i + 1].chars().nth(0).unwrap()) {
+ count = count + 1;
+ }
}

Този код като че ли се получава малко сложничък. И аз пробвах в един момент с нещо такова, и си мисля, че е по-лесно просто да се направи императивно:

pub fn sentence_count(&self) -> usize {
    let mut count = 0;
    let mut in_sentence = false;

    for c in self.text.chars() {
        if !in_sentence && !is_sentence_terminator(c) {
            in_sentence = true;
        } else if in_sentence && is_sentence_terminator(c) {
            in_sentence = false;
            count += 1;
        }
    }
    count
}

Алтернативно, ето какво измислих като по-fancy решение:

pub fn sentence_count(&self) -> usize {
    self.text
        .split_terminator(is_sentence_terminator)
        .filter(|s| s.len() > 0)
        .count()
}

Нали, това в категория "да видиш някакви други интересни решения".

- return endings_count;
+ return count;
}
pub fn emotion(&self) -> String {
- let punctuation: Vec<&str> = self.text.split(
+ let mut wonder: usize = 0;
+ let mut shock: usize = 0;
+ let mut meh: usize = 0;
+
+ let chunks: Vec<&str> = self.text.split(
|c: char| !self.punctuation(c)
).collect();
- let endings_count: usize = punctuation.iter().filter(|x| x.len() > 0).count();
-
- if punctuation.len() == endings_count {
- return String::from("😐");
+ for i in 0..(chunks.len() - 1) {
+ if chunks[i].len() == 0 && chunks[i + 1].len() > 0 && self.punctuation(chunks[i + 1].chars().nth(0).unwrap()) {
+ if chunks[i + 1].chars().nth(0) == Some('?') {
+ wonder = wonder + 1;
+ }
+ else if chunks[i + 1].chars().nth(0) == Some('!') {
+ shock = shock + 1;
+ }
+ else {
+ meh = meh + 1;
+ }
+ }
}
- let wonder: usize = punctuation.iter().filter(|str| str.chars().nth(0) == Some('?')).count();
- let shock: usize = punctuation.iter().filter(|str| str.chars().nth(0) == Some('!')).count();
- let meh: usize = punctuation.iter().filter(|str| str.chars().nth(0) == Some('.')).count();
-
if wonder > shock && wonder > meh {
return String::from("🤔");
}
else if shock > wonder && shock > meh {
return String::from("😮");
}
else {
return String::from("😐");
}
}
fn punctuation(&self, c: char) -> bool {
return c == '.' || c == '?' || c == '!';
}
fn latin_char(&self, c: char) -> bool {
return match c {
'a'...'z' => true,
'A'...'Z' => true,
_ => false}
}
fn cyrillic_char(&self, c: char) -> bool {
return match c {
'а'...'я' => true,
'А'...'Я' => true,
_ => false}
}
-}
+}