Софтуерно Инженерство
Loading...
BobyTopalova avatar BobyTopalova 25 Точки

Task 4 Visitors от 09.01.2018 г.

Ето, моето решение за него judge ми дава 20/100 точки доста грешни тестове.https://pastebin.com/ZJ5qGhd5

Може ли някой (например:  МартинБГ   :) или Kolioi ,че само вие пишете във форума  ), да ми обясни как да ползвам count от #include<algorithm>, за да заместя  функцията, която аз съм написала. На мястото, на което искам да го ползвам има закоментиран count.

Може ли да ми кажете, къде греша.

вход:

entry 1A John 15
entry 1B Tony 16
entry 1A John 15
entry 1C John 86
name John
name Jebediah
entry 1A John 15
entry 1B Tony 16
entry 1A John 15
entry 1E Jebediah 87
entry 1D Mark 16
age 15 87
end

Тагове:
0
C++ Programming 09/01/2019 20:25:05
MartinBG avatar MartinBG 1139 Точки
Best Answer

std::count може да бъде използван за колекции с типове, които са директно сравними - напр. прости типове или класове, които имат дефиниран == оператор.

За всички останали е по-удобно да се използва std::count_if, който приема predicate като трети параметър, по който се сравняват елементите на колекцията.

Примерен код за сравняване по име с използване на lambda функция:

vector<Visitors>infoVisit;
.....
long long int mycount = count_if(infoVisit.begin(),infoVisit.end(),[&searchName](Visitors const& v){return v.name == searchName;});
cout<< "by name " << searchName << ": " << mycount << endl;

 

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

1
BobyTopalova avatar BobyTopalova 25 Точки

Да искам още да помисля!

0
BobyTopalova avatar BobyTopalova 25 Точки

Ето, аз добре си помислих, но сега вместо 20/100 имам 0/100 точки.Смених вектора с лист, а другите два временни вектора с опашка. Само,че като сравнявам за името и различните години нещо не правя, както трябва и вместо 2 отговора е 4. Сравнявам първия с последния и после трия първия в списъка. Може ли съвет? Ето го решението ми.

Да питам и struct има ли също конструктор и деструктор, аз и класа смених със struct?

0
MartinBG avatar MartinBG 1139 Точки

Единствената разлика между class и struct в C++, е че класът по подразбиране е с private достъп, а struct - с public.

Следните два записа са еквивалентни по своето значчение:

class A {
// private: - this is the default access specifier for classes
public: // but it can be changed freely
  int age;
  A(int age): age(age) {}
}

struct B {
// public: - this is default access specifier for structs
  int age;
  B(int age): age(age) {}
}

 

printCountNameVisitors и printCountAgeVisitors в новото ти решение получават infoVisit (колекцията с посещенията) по референция и трият елементите от нея. Това не е правилно, защото при една и съща команда (напр. name John) изпълнена последователно два или повече пъти, ще получим различен резултат.

 

 

Няколко думи за избора на структури. По-важните неща, които се вземат предвид:

  • добавяне на нови елементи - колко честа операция се очаква да бъде и има ли значение къде в колекцията ще бъдат вмъкнати
  • има ли повтарящи се елементи
  • извличане/триене на елементи - от края, началото или от произволни места
  • търсене - колко често се налга и по какъв критерий
  • достъп до елементите - трябва ли да е произволен (напр. по индекс/ключ) или не
  • подреденост - необходима ли е и каква да бъде: според въвеждането или според някакъв критерий
  • обем на очакваните данни - при малко елементи на практика всяка структура би свършила работа
  • обем памет, която може да използваме за съхраняване на данните

 

Не винаги може да се удовлетворят всички условия само с една колекция и често се налага да се търси баланс между използвана памет, бързодействие и - не на последно място - сложност на кода.

За постигане на оптимални резултати може да се наложи комбинирането на няколко структури, напр:

- list/vector - за запазване на последователността на въвеждане

- unordered_set/unordered_map - за уникални елементи и/или за бърза проверка дали даден елемент съществува

- set/map - за сортиране на уникални елементи по даден критерий, както и за бързо извличане на последователни елементи, които попадат в дадени граници

multiset/multimap - като горните, но позволяват и повтарящи се елементи

- stack - ако искаме да достъпваме елементите в обратен ред (достъп до последния въведен елемент)

- queue - ако искаме да достъпваме елементите според реда на въвеждането им (достъп до най-старият елемент в колекцията)

priority_queue - ако искаме достъп до елемента с най-висок приоритет по даден критерий

 

В контекста на задачата, имаме следните операции:

  1. Добавяне на елементи - може да има повтарящи се, но нас ни интересуват само уникалните (по ID)
  2. Не се налага триене
  3. Извеждане на резултата - не ни е необходима подреденост (извеждаме само число, а не самите елементи)
  4. Търсене по критерий name - трябва да изведем броя уникални потребители с това име 
  5. Търсене по критерий min. age - max. age - трябва да изведем броя уникални потребители в този възрастов диапазон

 

Какви структури, според теб, най-много биха подхождали за тези операции?

0
BobyTopalova avatar BobyTopalova 25 Точки

Търсене по критерий name - трябва да изведем броя уникални потребители с това име и различни години.

Според, което си обяснил (това ще си го запиша), трябва да се използва unordered_set , но това нямам представа как да го

напиша като код, особено в клас.

0
MartinBG avatar MartinBG 1139 Точки

Търсенето по name не се интересува от годините, защото уникалността на потребителите се гарантира от id-то им.

 

Ще ти подскажа структурите, които аз съм използвал - виж дали ще се ориентираш коя за какво е, а малко по-късно ще ти постна и решението ми:

std::unordered_set<std::string>
std::unordered_map<std::string, size_t>
std::map<size_t, size_t>
0
BobyTopalova avatar BobyTopalova 25 Точки

Сетих се set за id, unordered_map <string, int> за имената и броя им и съответно map<int, int> за годините и броя им.

0
MartinBG avatar MartinBG 1139 Точки

Да, точно така! smiley

  std::unordered_set<std::string> ids;
  std::unordered_map<std::string, size_t> nameCount; // name -> count of users with the name
  std::map<size_t, size_t> ageCount; // age -> count of users of that age

 

0
MartinBG avatar MartinBG 1139 Точки

Набързо това са проблемите, които забелязвам:

 

  • Винаги добавяш новите елементи към name и age колекциите, без да проверяваш в id дали вече не е добавен този потребител.
  • Не използваш name и age като броячи (сетваш стойностите на 1, вместо да увеличаваш стойността при добавяне на нов запис)
  • Основният цикъл за четене от конзолата е ненужно сложен - while с вложени още 2 while цикъла. Може да се направи само с един while (докато не се въведе "end") и if-else-... конструкция в него, която да обработва входните данни
  • name и age колекциите не се използват ефективно за извличане на данните - обхождат се целите и се броят съвпаденията, което на практика обезсмисля използването на по-сложните структури

 

Искаш ли да опиташ да ги оправиш, или направо да ти покажа решението?

0
10/01/2019 21:54:23
MartinBG avatar MartinBG 1139 Точки

Щеше да е провал, ако не беше стигнала дотук. Сигурен съм, че сега знаеш много повече за структурите, отколкото преди да я почнеш. :)

Имай предвид, че тази е от задачите на Жорката, а нивото на курса, който той води е по-високо, от това, което ви преподават в текущата инстанция, т.е. нормално е тази задача да ти е по-трудна от тези, които са ви давали.

 

Това е моето решение на задачата, а това са две решения от автора на задачата: first and optimized

 

Авторът е решил да използва Visitor клас, докато моето решение се фокусира директно върху проблемите, които трябва да се решат - броене на потребителите по критерий и бързо извеждане на резултата.

0
MartinBG avatar MartinBG 1139 Точки

Не си ми загубила времето - приятно ми е, когато мога да помогна на колега, но съм изненадан, че се колебаеш дали да продължиш. Както писах и по-горе, последните седмици решаваш задачи, които са над нивото на курса, който караш. Нормално е да са ти по-трудни, но пък задачите, които ви дават за домашно и най-вероятно ще имате на изпита ще ти бъдат по-леки. smiley

0
BobyTopalova avatar BobyTopalova 25 Точки

unordered_set/unordered_map , но може и без клас.

0
BobyTopalova avatar BobyTopalova 25 Точки

Ето това.

успях да направя, продполагам че map<size_t,size_t> го ползваш , counter

Mоята задача пак не е вярна. Уви.

0
BobyTopalova avatar BobyTopalova 25 Точки

Не ми пращай още решението.

0
BobyTopalova avatar BobyTopalova 25 Точки

Предавам се

 

 

0
13/01/2019 18:24:00
BobyTopalova avatar BobyTopalova 25 Точки

Вече, н

0
13/01/2019 18:23:41
BobyTopalova avatar BobyTopalova 25 Точки

Благодаря и извинявай, че ти изгубих толкова време!

0
13/01/2019 18:23:16
BobyTopalova avatar BobyTopalova 25 Точки

Разгледах, решенията и твоето ми се струва най - разбираемо, поне за мен. Ти още при въвеждането проверяваш за id, веднага преброяваш посетителите  с уникално i

1
13/01/2019 18:23:04