Решение на 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)}
}
}
#[inline(always)]

Бих ти препоръчал компилатора да решава, какво да бъде inline-нато. В повечто слуачаи той преценява по-добре, а във всички останали бих прпоръчал добре да измериш "импакта" на инлайнването.

fn is_latin_letter(c : char) -> bool
{
c >= '\u{0041}' && c <= '\u{005A}'
||
c >= '\u{0061}' && c <= '\u{007A}'
}
#[inline(always)]
fn is_cyrillic_letter(c :char) -> bool
{
c >= '\u{0410}' && c <= '\u{044F}'
&&
c != '\u{0428}' && c != '\u{042D}'
&&
c != '\u{044B}' && c != '\u{044D}'
}
impl TextInfo
{
pub fn char_count(&self) -> usize
{
self.text.chars().count()
}
pub fn alphabetic_count(&self) -> usize
{
let mut count : usize = 0;
for i in self.text.chars()
{
if is_latin_letter(i) || is_cyrillic_letter(i)
{
count += 1;
}
}
count
}
pub fn latin_letter_count(&self) -> usize
{
let mut count : usize = 0;
for i in self.text.chars()
{
if is_latin_letter(i)
{
count += 1;
}
}
count
}
pub fn cyrillic_letter_count(&self) -> usize
{
let mut count : usize = 0;
for i in self.text.chars()
{
if is_cyrillic_letter(i)
{
count += 1;
}
}
count
}
pub fn word_count(&self) -> usize
{
let mut count : usize = 0;
// We can use finite transducer here
enum State
{
Start,
Letter,
NonLetter,
}
let mut state = State::Start;
for i in self.text.chars()
{
let is_letter = is_latin_letter(i) || is_cyrillic_letter(i);
match state
{
State::Start =>
{
if is_letter
{
state = State::Letter;
}
else
{
state = State::NonLetter;
}
}
State::Letter =>
{
if !is_letter
{
state = State::NonLetter;
count += 1;
}
}
State::NonLetter =>
{
if is_letter
{
state = State::Letter;
}
}
}
}
count
}
}
struct SentenceStats
{
open_mouths : usize,
thinking_faces : usize,
neutral_faces : usize,
}
const OPEN_MOUTH : char = '\u{1F62E}';
const NEUTRAL_FACE : char = '\u{1F610}';
const THINKING_FACE : char = '\u{1F914}';

Тук би могъл спокойно да направиш константите от тип &str, с двойни кавички. Така няма да се наложи долу да им викаш .to_string().

(То условието можеше да се напише и да връща char, ама това е друга тема ;))

impl TextInfo
{
fn gather_sentence_stats(&self) -> SentenceStats
{
let mut stats = SentenceStats
{
open_mouths: 0,
thinking_faces: 0,
neutral_faces: 0
};
// We can use finite transducer again
enum State
{
Start,
NonPunctuation,
Punctuation,
}
let mut state = State::Start;
for i in self.text.chars()
{
match state
{
State::Start =>
{
if i == '!' || i == '.' || i == '?'
{
state = State::Punctuation
}
else
{
state = State::NonPunctuation;
}
}
State::Punctuation =>
{
if !(i == '!' || i == '.' || i == '?')
{
state = State::NonPunctuation;
}
}
State::NonPunctuation =>
{
if i == '!'
{
stats.open_mouths += 1;
state = State::Punctuation;
}
if i == '.'
{
stats.neutral_faces += 1;
state = State::Punctuation;
}
if i == '?'
{
stats.thinking_faces +=1;
state = State::Punctuation;
}
}
}
}
stats
}
pub fn sentence_count(&self) -> usize
{
let stats = Self::gather_sentence_stats(&self);
stats.open_mouths + stats.thinking_faces + stats.neutral_faces
}
pub fn emotion(&self) -> String
{
let stats = Self::gather_sentence_stats(&self);
if stats.open_mouths > std::cmp::max(stats.thinking_faces, stats.neutral_faces)
{
String::from(OPEN_MOUTH.to_string())
}
else if stats.thinking_faces > std::cmp::max(stats.open_mouths, stats.neutral_faces)
{
String::from(THINKING_FACE.to_string())
}
else
{
String::from(NEUTRAL_FACE.to_string())
}
}
}

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

Compiling solution v0.1.0 (file:///tmp/d20171026-5817-16d5gpi/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 4.0 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 коментара)

Михаил качи първо решение на 19.10.2017 20:14 (преди почти 8 години)

Михаил качи решение на 19.10.2017 20:14 (преди почти 8 години)

pub struct TextInfo
{
text : String
}
impl TextInfo
{
pub fn new(s: &str) -> Self
{
TextInfo{text : String::from(s)}
}
}
#[inline(always)]

Бих ти препоръчал компилатора да решава, какво да бъде inline-нато. В повечто слуачаи той преценява по-добре, а във всички останали бих прпоръчал добре да измериш "импакта" на инлайнването.

fn is_latin_letter(c : char) -> bool
{
c >= '\u{0041}' && c <= '\u{005A}'
||
c >= '\u{0061}' && c <= '\u{007A}'
}
#[inline(always)]
fn is_cyrillic_letter(c :char) -> bool
{
c >= '\u{0410}' && c <= '\u{044F}'
&&
c != '\u{0428}' && c != '\u{042D}'
&&
c != '\u{044B}' && c != '\u{044D}'
}
impl TextInfo
{
pub fn char_count(&self) -> usize
{
self.text.chars().count()
}
pub fn alphabetic_count(&self) -> usize
{
let mut count : usize = 0;
for i in self.text.chars()
{
if is_latin_letter(i) || is_cyrillic_letter(i)
{
count += 1;
}
}
count
}
pub fn latin_letter_count(&self) -> usize
{
let mut count : usize = 0;
for i in self.text.chars()
{
if is_latin_letter(i)
{
count += 1;
}
}
count
}
pub fn cyrillic_letter_count(&self) -> usize
{
let mut count : usize = 0;
for i in self.text.chars()
{
if is_cyrillic_letter(i)
{
count += 1;
}
}
count
}
pub fn word_count(&self) -> usize
{
let mut count : usize = 0;
// We can use finite transducer here
enum State
{
Start,
Letter,
NonLetter,
}
let mut state = State::Start;
for i in self.text.chars()
{
let is_letter = is_latin_letter(i) || is_cyrillic_letter(i);
match state
{
State::Start =>
{
if is_letter
{
state = State::Letter;
}
else
{
state = State::NonLetter;
}
}
State::Letter =>
{
if !is_letter
{
state = State::NonLetter;
count += 1;
}
}
State::NonLetter =>
{
if is_letter
{
state = State::Letter;
}
}
}
}
count
}
}
struct SentenceStats
{
open_mouths : usize,
thinking_faces : usize,
neutral_faces : usize,
}
const OPEN_MOUTH : char = '\u{1F62E}';
const NEUTRAL_FACE : char = '\u{1F610}';
const THINKING_FACE : char = '\u{1F914}';

Тук би могъл спокойно да направиш константите от тип &str, с двойни кавички. Така няма да се наложи долу да им викаш .to_string().

(То условието можеше да се напише и да връща char, ама това е друга тема ;))

impl TextInfo
{
fn gather_sentence_stats(&self) -> SentenceStats
{
let mut stats = SentenceStats
{
open_mouths: 0,
thinking_faces: 0,
neutral_faces: 0
};
// We can use finite transducer again
enum State
{
Start,
NonPunctuation,
Punctuation,
}
let mut state = State::Start;
for i in self.text.chars()
{
match state
{
State::Start =>
{
if i == '!' || i == '.' || i == '?'
{
state = State::Punctuation
}
else
{
state = State::NonPunctuation;
}
}
State::Punctuation =>
{
if !(i == '!' || i == '.' || i == '?')
{
state = State::NonPunctuation;
}
}
State::NonPunctuation =>
{
if i == '!'
{
stats.open_mouths += 1;
state = State::Punctuation;
}
if i == '.'
{
stats.neutral_faces += 1;
state = State::Punctuation;
}
if i == '?'
{
stats.thinking_faces +=1;
state = State::Punctuation;
}
}
}
}
stats
}
pub fn sentence_count(&self) -> usize
{
let stats = Self::gather_sentence_stats(&self);
stats.open_mouths + stats.thinking_faces + stats.neutral_faces
}
pub fn emotion(&self) -> String
{
let stats = Self::gather_sentence_stats(&self);
if stats.open_mouths > std::cmp::max(stats.thinking_faces, stats.neutral_faces)
{
String::from(OPEN_MOUTH.to_string())
}
else if stats.thinking_faces > std::cmp::max(stats.open_mouths, stats.neutral_faces)
{
String::from(THINKING_FACE.to_string())
}
else
{
String::from(NEUTRAL_FACE.to_string())
}
}
}
-
-

Добра работа, стабилно решение :). Едно нещо, което трябва да отбележа, е че стилово е доста различно от обикновено-използвания стандарт -- отваряща скоба на същия ред, липса на интервал преди :. Ако си инсталираш програмата rustfmt и я пуснеш върху кода си, тя ще го форматира в "предпочитания" стил.

Няма да ти правя проблем за това -- ако предпочиташ така да пишеш кода си, fair enough. Но ще виждаш доста код в различен от твоя стил, и дори и само заради това бих те посъветвал да опиташ препоръчания такъв -- открил съм, че човек може спокойно да свикне с различен coding style, стига само да опита за достатъчно дълго време :). Ти си знаеш, обаче.