Advertisement
Guest User

Untitled

a guest
May 23rd, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.52 KB | None | 0 0
  1. //
  2. // Created by Saxion on 10/12/2018.
  3. //
  4.  
  5. #ifndef ALGOS_ALGOS_H
  6. #define ALGOS_ALGOS_H
  7.  
  8. #include <algorithm>
  9. #include <numeric>
  10. #include <random>
  11. #include <vector>
  12. #include "task.h"
  13.  
  14. namespace saxion {
  15. struct algos {
  16.  
  17.  
  18. // 1 point
  19. template<typename _Iter>
  20. auto has_all_tasks_assigned(_Iter begin, _Iter end) const noexcept {
  21. // todo DONE
  22. return std::all_of(begin,end,[](const task& t){
  23. return t.assignees.size();
  24. });
  25. // returns true if all the tasks in collection have a person assigned to them
  26. }
  27.  
  28. // 1 point
  29. template <typename _Iter>
  30. bool has_task_with_deadline_afer(_Iter begin, _Iter end, const task::time_type& deadline) const noexcept{
  31. // todo DONE
  32. return std::any_of(begin,end,[deadline](const task& t){
  33. return t.deadline > deadline;
  34. });
  35. }
  36.  
  37. // 3 points
  38. template <typename _Iter>
  39. auto remove_asignee_from_all(_Iter begin, _Iter end, const std::string& person) const noexcept{
  40. // todo DONE
  41. return std::for_each(begin,end,[person](task& t){
  42. bool found = (std::find(t.assignees.begin(), t.assignees.end(), person) != t.assignees.end());
  43. if (found){
  44. t.assignees.erase(person);
  45. }
  46. });
  47. // transforms the tasks (in-place) by removing <person> from the assignees in all the tasks
  48. }
  49.  
  50. // 1 point
  51. template <typename _Iter>
  52. auto extend_deadlines(_Iter begin, _Iter end, int priority, const task::time_difference_type& extension) const noexcept{
  53. // todo DONE
  54. return std::for_each(begin,end,[priority,extension](task& t){
  55. if (t.priority == priority){
  56. t.deadline += extension;
  57. }
  58. });
  59. // transforms the tasks with priority <prio> (in-place) by extending their deadlines with <extension>
  60. }
  61.  
  62. // 1 point
  63. template <typename _Iter>
  64. auto count_tasks_with_deadlines_before(_Iter begin, _Iter end, const task::time_type& deadline) const noexcept{
  65. // todo DONE
  66. return std::count_if(begin, end, [deadline](const task& t){
  67. return t.deadline < deadline;
  68. // returns the count of tasks with a deadline before <deadline>
  69. });
  70. }
  71.  
  72.  
  73. // 2 points
  74. template <typename _Iter>
  75. auto add_assignee_to_task(_Iter begin, _Iter end, int id, std::string person) const noexcept{
  76. // todo DONE
  77. return std::any_of(begin, end, [id, person] (task& t)
  78. {
  79. if(t.id == id && !(t.assignees.find(person) != t.assignees.end() ))
  80. {
  81. t.assignees.insert(person);
  82. return true;
  83. }
  84. return false;
  85. }
  86.  
  87. );
  88. // adds <person> to assignees of the task with id <id>
  89. // returns false if such a task doesn't exist or if it already has <person> assigned to it
  90. // otherwise returns true
  91. }
  92.  
  93. // 1 point
  94. template <typename _Iter>
  95. std::vector<task> get_tasks_with_priority(_Iter begin, _Iter end, int priority) const noexcept{
  96. // todo DONE
  97. std::vector<task> vec1;
  98. std::for_each(begin,end,[priority,&vec1](task& t){
  99. if (t.priority == priority){
  100. vec1.push_back(t);
  101. }
  102. });
  103. // returns a vector with copies of tasks with priority <priority>
  104. return vec1;
  105. }
  106.  
  107. // 2 points move_if ;)
  108. template <typename _Iter, typename _OutIter>
  109. _Iter extract_tasks_with_deadline_before(_Iter begin, _Iter end, _OutIter out, const task::time_type& deadline) const noexcept{
  110. // todo DONE
  111. //(void)begin; (void)end; (void)out; (void)deadline;
  112.  
  113. std::copy_if(begin, end, out, [deadline](task& t){
  114. return t.deadline < deadline;
  115. });
  116. return std::remove_if(begin, end, [deadline](task& t){
  117. return t.deadline < deadline;
  118. });
  119.  
  120. // moves the tasks with deadlines before <deadline> to the container "pointed by" the <out> iterator (see test code for what it is)
  121. // the tasks that are on or after the <deadline> should stay in the *beginning* of the original container
  122. // the returned iterator should point to the 'new end' of the range in the original container
  123.  
  124. /* Simplified example:
  125. * given an input container with integers: [6, 3, 7, 4, 5, 1]
  126. * move the numbers before number {5} to another container and return the new 'end' iterator to the original container.
  127. *
  128. * After moving numbers 'before {5}' the output container will have elements: [3, 4, 1],
  129. * while the original container will look like this: [6, 7, 5, _, _, _]
  130. * Notice that there are three empty slots at the end of the container and all the number >= 5 have been moved to the beginning.
  131. * The function should return the iterator to the 'new end' of the original container, which is the first empty slot.
  132. */
  133. //return end;
  134. }
  135.  
  136. using id_prio = std::tuple<int, int>;
  137.  
  138. // 2 points
  139. template<typename _Iter>
  140. std::vector<id_prio> list_sorted_by_prio(_Iter begin, _Iter end) const noexcept {
  141. std::vector<task> tmp;
  142. std::vector<id_prio> sortedVector;
  143. std::copy(begin, end,std::back_inserter(tmp)); //make a local copy
  144.  
  145. std::sort(tmp.begin(), tmp.end(), [] (task a,task b) { //sort the items
  146. if(a.priority == b.priority){
  147. return a.id < b.id;
  148. } else{
  149. return a.priority < b.priority;
  150. }
  151. });
  152.  
  153. for (auto a : tmp){
  154. sortedVector.push_back(std::make_tuple(a.id,a.priority));
  155. }
  156.  
  157. // returns a vector of pairs <id, priority> of all the tasks. The returned vector must be sorted by priority.
  158. // If two tasks have the same priority, they are sorted by id (lower id comes first)
  159. //return std::vector<id_prio>();
  160. return sortedVector;
  161. }
  162.  
  163. // 1 point
  164. template <typename _Cont>
  165. auto remove_all_finished(_Cont &container) const noexcept {
  166. // todo DONE
  167. //(void) container;
  168. std::vector<task> tmp;
  169. std::vector<task> foo;
  170. std::copy_if(container.begin(),container.end(),std::back_inserter(foo),[](task& t){
  171. auto now = task::clock_type::now();
  172. return (now.time_since_epoch() <= t.deadline.time_since_epoch());
  173. }
  174. );
  175. std::copy(foo.begin(),foo.end(),container.begin());
  176. container.resize(foo.size());
  177. return container;
  178. // removes all the tasks with deadline before or on the time point now() obtained from the system_clock
  179. // notice that this function takes the whole container as an argument, that's because it's impossible to remove elements using just the iterators.
  180. }
  181.  
  182.  
  183. // 1 point
  184. template <typename _Iter>
  185. task& get_nth_to_complete(_Iter begin, _Iter end, int n) const noexcept{
  186. // todo DONE
  187. std::sort(begin, end,[](task& t, task& r){
  188. if(t.deadline == r.deadline) {
  189. return t.priority < r.priority;
  190. } else return t.deadline < r.deadline;
  191. });
  192. // returns a reference to the n-th task to be completed in order of deadlines.
  193. // deadline ties are resolved by comparing priorities (lower priorities come first)
  194. return *(begin + n);
  195. }
  196.  
  197. // 1 point
  198. template <typename _Iter>
  199. std::vector<task> get_first_n_to_complete(_Iter begin, _Iter end, int n) const noexcept{
  200. // todo DONE
  201. //(void)begin; (void)end; (void)n;
  202. std::vector <task> vec1;
  203.  
  204. std::sort(begin, end,[](task& t, task& r){
  205. if(t.deadline == r.deadline) {
  206. return t.priority < r.priority;
  207. } else return t.deadline < r.deadline;
  208. });
  209. std::copy_n(begin,n,std::back_inserter(vec1));
  210.  
  211. // returns a vector with copies of first n tasks to complete by deadline (ties resolved with priority).
  212. // The tasks in this vector must me sorted by deadline (ties resolved with priority)
  213. return vec1;
  214. }
  215.  
  216. // 3 points
  217. template <typename _Iter, typename _OIter>
  218. void cost_burndown(_Iter begin, _Iter end, _OIter obegin) const noexcept {
  219. // todo DONE
  220. using time_type = std::chrono::time_point<std::chrono::system_clock>;
  221. std::map<time_type, double> deadlines;
  222. double cumulative(0.0);
  223.  
  224. std::for_each(begin, end, [&deadlines](const task& task1)
  225. {
  226. deadlines[task1.deadline] += task1.cost;
  227. });
  228.  
  229. std::transform(deadlines.begin(), deadlines.end(), obegin,[&cumulative](std::pair<time_type, double> deadline)
  230. {
  231. cumulative = cumulative + deadline.second;
  232. return cumulative;
  233. });
  234. // you can assume that _OIter is a std::back_insert_iterator to a container of double
  235.  
  236. // calculates the cost burndown of the tasks and writes the output to the output iterator <obegin>
  237. // the cost burndown is defined as cumulative sum of the tasks' costs sorted by deadlines
  238. // tasks with the same deadline contribute one data point (sum of their costs) to the burndown
  239.  
  240. /* Simplified example
  241. * Assume that we have a container with 5 tasks, where each task has a deadline and a cost associated with it:
  242. * [ {4, 43.0}, {2, 11.0}, {3, 7.0}, {1, 23.0}, {3, 19.0} ], here the first number in a pair is the deadline and the second the cost
  243. * The first task to complete is the 4th task (deadline 1) with associated cost of 23.0
  244. * The 2nd task to complete is the 2nd task (deadline 2) with associated cost of 11.0
  245. * The 3rd tasks to complete are the 3rd and the 5th tasks (deadline 3) with associated costs of 7.0 + 19.0 = 26.0
  246. * The 4th and last task to complete is the 1st task (deadline 4) with associated cost of 43.0
  247. *
  248. * Therefore the cost burndown (cumulative cost) is: [23.0, 34.0, 60.0, 103.0].
  249. * Those numbers in this order must be outputted to the obegin iterator.
  250. */
  251. }
  252.  
  253.  
  254. // 1 point
  255. template <typename _Iter>
  256. std::pair<task, task> cheapest_and_most_expensive(_Iter begin, _Iter end) const noexcept{
  257. // todo DONE
  258. //(void)begin; (void)end;
  259. task max;
  260. task min;
  261.  
  262. max.cost = 0;
  263. min.cost = INT_MAX;
  264. std::for_each(begin,end,[&min, &max](task& t){
  265. if (t.cost < min.cost){
  266. min = t;
  267. }
  268. if (t.cost > max.cost){
  269. max = t;
  270. }
  271. });
  272. return {min, max};
  273. // returns a pair consisting of the least and the most expensive tasks in the collection
  274. //return {task(), task()};
  275. }
  276.  
  277. // 1 point
  278. template <typename _Iter>
  279. auto total_cost(_Iter begin, _Iter end) const noexcept{
  280. // todo DONE
  281. return std::accumulate(begin, end, 0.0, [](double accumulator, task& t) {
  282. return accumulator + t.cost;
  283. });
  284. // returns the total cost of all the tasks in the collection
  285. }
  286.  
  287. // 2 points
  288. template <typename _Iter>
  289. double total_cost_of(_Iter begin, _Iter end, const std::string& assignee) const noexcept{
  290. // todo DONE
  291. return std::accumulate(begin, end, 0.0, [assignee](double accumulator, task& t)
  292. {
  293. bool found = (std::find(t.assignees.begin(), t.assignees.end(), assignee) != t.assignees.end());
  294. if(found) {
  295. return accumulator + t.cost;
  296. } else {
  297. return accumulator;
  298. }
  299. });
  300. // returns the cost of all the tasks that have <assignee> assigned to them
  301. }
  302.  
  303. // 1 point
  304. template <typename _Iter>
  305. _Iter separate_by_deadline(_Iter begin, _Iter end, const task::time_type& deadline) const noexcept {
  306. // todo DONE
  307.  
  308. auto place = std::count_if(begin, end, [deadline, begin, end](task& t){
  309. std::sort(begin, end,[](task& t, task& r){
  310. return t.deadline < r.deadline;
  311. });
  312. return t.deadline < deadline;
  313. });
  314. // reorders the tasks in such a way that all tasks with deadlines before <deadline> precede the tasks with deadline on or after <deadline>
  315. // returns the iterator to the last task in the first group (with deadlines before <deadline>)
  316. return (begin+(place-1));
  317. }
  318.  
  319. // 3 points
  320. template <typename _Iter>
  321. double estimate_workload(_Iter begin, _Iter end, const std::string& person) const {
  322. // todo DONE
  323. //(void)begin; (void)end; (void)person;
  324. std::vector<task> sample;
  325. std::sample(begin, end, std::back_inserter(sample), std::distance(begin, end) / 2, std::mt19937{std::random_device{}()});
  326. return std::count_if(sample.begin(), sample.end(), [person](const task &task1) {
  327. return task1.assignees.find(person) != task1.assignees.end();
  328. }) / sample.size();
  329. // estimates the workload of a <person>
  330. // the estimation is done as follows:
  331. // - out of all the tasks, half of them (n_s) are chosen at random (sampled)
  332. // - for the selected tasks a check is done, whether the <person> belongs to the task's assignees
  333. // based on the number of tasks that checked positive (count) and the total number of sampled tasks (n_s) the estimated workload is calculated as:
  334. // count / n_s
  335.  
  336. /* Simplified example:
  337. * There are 8 tasks and "zack" is assigned to tasks [2, 3, 6].
  338. * We can construct a truth table of all tasks like this: [0, 0, 1, 1, 0, 0, 1, 0]
  339. * The true workload of "zack" is 3/8=0.375
  340. *
  341. * Let's say for the estimate we sampled tasks: 0, 2, 4, 6. For those sampled tasks "zack" is assigned 2 two times,
  342. * consequently the estimated workload is 2/4 = 0.5
  343. *
  344. * Let's now say that we randomly sampled tasks 1, 4, 6, 7. For those tasks "zack" appears only once,
  345. * therefore the estimated workload is 1/4 = 0.25
  346. *
  347. * Notice that for our example it is possible to estimate a workload between 0.00 & 0.75
  348. */
  349.  
  350. //return -1.0;
  351. }
  352.  
  353.  
  354. // 2 points
  355. struct averageaccumulator_t {
  356. double sum;
  357. size_t n;
  358.  
  359. double GetAverage() const { return (sum) / n; }
  360. };
  361. template <typename _Iter>
  362. auto average_cost_of_prio(_Iter begin, _Iter end, int priority) const noexcept {
  363. // todo DONE
  364.  
  365. auto func_acc_avg = [priority](averageaccumulator_t averageaccumulator, task &t) {
  366. if (t.priority == priority) {
  367. return averageaccumulator_t({averageaccumulator.sum + t.cost, averageaccumulator.n + 1});
  368. } else {
  369. return averageaccumulator_t({averageaccumulator.sum + 0.0, averageaccumulator.n + 0});
  370. }
  371. };
  372. averageaccumulator_t accumulated = std::accumulate(begin, end, averageaccumulator_t({0.0, 0}), func_acc_avg);
  373. // calculates and returns the average cost of tasks with priority <priority>
  374. return accumulated.GetAverage();
  375. }
  376. };
  377. }
  378.  
  379.  
  380. #endif //ALGOS_ALGOS_H
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement