JA2 - Task 2 - Word Matching - нулев тест 3 грешен ли е?
Здравейте,
Мисля, че нулев тест 3 е грешен. При 50% - равно трябва да има 3 попадения, а не 2, както е написано. Процентите са от 1 до 100 включително и така ако задам 100% там ще имам 1 попадение. Сега съм с 90 точки в Judge. Ако дам строго по-голяма ме връща на 60 точки.
Има ли проблем или проблема е при мен.
Благодаря предварително.
Мерси, недогледал съм.
Ще използвам същата тема, защото въпросът ми е по същата задача.
Никъде в лекциите или в демотата нямаше информация как да разделяме думи от стринг, когато имаме различни препинателни знаци между тях. Дадохте пример с разделител ',' - getline(string, token, ','), но тук в задачката има и точки и запетаи и малко се затруднявам.
Звучи ми логично да мога да кажа:
Как да кажа на c++ "Разделяй стринговете от ей този стрийм, слагай ги ей тук, но когато срещнеш този и този символ, прескочи ги" ?
Здравей,
и мен ме интерсува,блъскам си главата,прерових нета,но нещо не успявам.
Поздрави
Здравейте,
Като цяло няма лесен вграден начин в C++ да се чете до различни разделители - просто стандартната библиотека не дава такава функционалност. Това не е проблем обаче, защото в програмирането, когато ни липсва един инструмент, си го създаваме.
Пробвайте да помислите ако трябва вие да напишете нещо, което прави такова разделение, как бихте го направили? string-ът е просто масив от символи. Да го разделим на думи е същото като да го разделим на "поредици от символи, които спазват определено условие". В едно от първите домашни имаше задача да четете поредица от числа и да изведете най-дългата поредица от еднакви числа. Сега е същото, само че не са числа, а са символи, и проверката ни не е дали са "еднакви" а дали са "различни от разделителите, които искам да ползвам".
Тоест алгоритъмът (функцията) ни ще приема string text, списък с разделители - примерно vector<char> separators - и ще връща (примерно) vector<string> с думите:
- правим си vector<string> words и един ostringstream currentWord в който ще си генерираме текущата дума
- пускаме един for (int i = 0; i < text.size(); i++)
---- ако текущият (i-ят) символ НЕ е разделител (т.е. НЕ можем да го намерим в separators), значи го добавяме към текущата дума: currentWord << text[i];
---- ако текущият (i-ят) символ Е разделител (т.е. го намираме в separators), значи текущата дума е приключила - добавяме я към списъка с думи и я зачистваме за да може да почнем да пълним следващата дума: words.push_back(currentWord.str()); currentWord = ostringstream() //(създаваме си направо нов ostringstream за да сме сигурни че е празен)
- накрая връщаме words от функцията
Вече имаме функция, която по един string връща всички думи в този string, определени от разделителите, които сме подали. Разбира се може да го подобрим този алгоритъм - примерно да му кажем да не връща празни думи (т.е. ако има два разделителя един до друг, между тях на практика се получава празна дума) и т.н. Тази функция можем да я ползваме във всякакви подобни ситуации. Разбира се, това не е единствения алгоритъм за постигане на това, не е дори единствения подход, но е сравнително прост и чист като решение.
Сега относно задачата - тази задача не изисква да разделята думите в текста. Може и така, разбира се, но има и друг вариант, които не отделя време за създаване на списък с думи. Този вариант е пак с цикъл да обхождате текста и да гледате дали символите, започващи от позицията, на която се намирате, съвпадат със символите от думата която търсите (по-точно дали определена бройка от тях съвпада, на базата на въведения процент) - ако да, значи сте намерили съвпадение, увеличавате някакъв брояч и продължавате от следващата позиция, ако не - пак продължавате, без да увеличавате брояча.
Отново, има и други решения на тази задача, но това е едно възможно което дори не ползва string функции, освен достъп до символ на определена позиция в string.
Поздрави,
Жоро
Доста се рових в нета и по метода на проба-грешка, го направих с RegEx, в две части. Защо като "чисти" точки, запетаи и другите, вкарва празни стрингове на тяхно място във вектора:
std::string s;
getline(std::cin, s);
std::regex re("([ .,;!?]|[ .,;!?]+)");
std::vector<std::string> vectorOfWords;
std::sregex_token_iterator it(s.begin(), s.end(), re, -1);
std::sregex_token_iterator reg_end;
for (; it != reg_end; ++it) {
vectorOfWords.push_back(it->str());
}
Кое е най-доброто решение за изчистване на тези празни стрингове, което да работи //какво ли не пробвах и накрая успях с remove_if и std::mem_fun_ref(&std::string::empty));
Но си нямам и представа защо и как го прави.
Аз го направих със replace_if да заменя всичко което не е буква със спейс и после го чета като стриим. Ама не се бях сетил въобще за варианта, които даде Жоро по-горе да не се разделя стринга а направо в него да се търси. Моето решение губи време първо да обходи веднъж стринга, да проверява какъв е символа и да заменя, втори път да го раздели във вектор на думи и трети път да обхожда вектора да търси думи съвпадащи с критериите. И така ми го оцени системата ама наистина всичко може да стане с едно обхождане.
@ Jovanna
Ако стринга е празен, просто не го добавяй във вектора.
Ето едно решение с strtok() (без кода за една от функциите)
Някакво решение? Че аз стигнах до решение, но не работи ако има в стринга спейсове :)
@kolioi, благодаря!
@ kolioi
Евала, мерси много за просвещаването! "Match" функцията (или по-точно изчисленията в нея) ги бях измислил, "input"-а и разделението на стринговете ми куцаше (нещо не се обичам аз много със стринговете хаха, сигурно защото и не знаех за съществуването на "strtok" понеже съм noob-че, а може би просто не съм имал късмет да попадна на него докато търсех нещо такова в Stack Overflow & co.). С помощта ти доизкусурих кода.
Имаш бира от мен!
Поздрави!
Лесна работа
Ето го и кода на липсващата функция
Весела Коледа!
Весела Коледа! Ето и моят вариант: