Greedy algorithm error using c++ sets - c++

I've created a greedy algorithm to solve a problem (homework assignment) and since I'm learning c++ I would like to achieve the same thing but using sets.
Basically we submit the homework to an online platform, this platform as some test cases that we don't know of, and we get a score based on that. If we pass all test cases we have 100%;
The problem is like this.
We have an actor that wants to schedule appointments with the fans that answered an online questionnaire about him. Now he wants to choose the fan's that maximizes the sum of points in the questionnaire and respecting the fan's availability. He can see only one fan a day.
We have an input like this:
6
1 1 5
2 2 4
3 1 2
4 3 1
5 1 6
6 2 2
Where the first line is the number of fans and following, in each line, we have the fan id, the fan available days and the fan points achieved in the online questionnaire. I must print the ids of the fans that the actor will see and the sum of combined points of the fans. So for the above input I have the following output:
2
4
5
11
Note that if two fans have the same points, the fan prefered should be the one with the lower ID.
I've started by sorting the fans by the points of the questionnaire (decreasing order) and then by the lower id.
When reading the input, I'm adding the number of days to a set.
My idea was like this:
When iterating over the data, I check if the fan in study days available is in the set. If it is, add this fan and remove the days from the set. If the fan days is not in the set, then get the upper_bound and decrease the iterator to set the fan on the first day lower that the initial day. The algorithm stops wen the set is empty or I iterate all over the fans.
Here is my greedy function:
void greedy() {
fan_id.insert(questionnaire_result[0][0]);
days_available.erase(questionnaire_result[0][1]);
total_questionaire_sum += questionnaire_result[0][2];
int i;
for (i = 1; i < number_of_fans; i++) {
if (days_available.empty()) {
break;
} else if (days_available.count(questionnaire_result[i][1])) {
fan_id.insert(questionnaire_result[i][0]);
days_available.erase(questionnaire_result[i][1]);
total_questionaire_sum += questionnaire_result[i][2];
} else {
it = days_available.upper_bound(questionnaire_result[i][1]);
if (it == days_available.begin()) {
if (*it < questionnaire_result[i][1]) {
fan_id.insert(questionnaire_result[i][0]);
days_available.erase(*it);
total_questionaire_sum += questionnaire_result[i][2];
}
} else if (it == days_available.end()) {
it--;
if (*it < questionnaire_result[i][1]) {
fan_id.insert(questionnaire_result[i][0]);
days_available.erase(*it);
total_questionaire_sum += questionnaire_result[i][2];
}
} else {
it--;
if (*it < questionnaire_result[i][1]) {
fan_id.insert(questionnaire_result[i][0]);
days_available.erase(*it);
total_questionaire_sum += questionnaire_result[i][2];
}
}
}
}
}
I believe my problem is in this line:
it = days_available.upper_bound(questionnaire_result[i][1]);
I've tested many possibilities and this is working in all my test cases. Unfortunately, we don't have the test cases of the platform.
Does someone see an situation that my code fails? With this I'm getting 90% of the score.
EDIT:
As Edward pointed me out, I've managed to solve the problem like this:
When reading the input added this line of code:
max_days = max_days | questionnaire_result[i][1];
And then did this:
for (int j = 1; j < max_days + 1; j++) {
days_available.insert(j);
}
Problem solved

This input file will cause the program to generate an incorrect result:
2
1 2 6
2 2 5
Both fans are available either day, so it's clear that both fans could be visited and the total output score should be 11. Your algorithm, however, only chooses the first one and outputs a score of 6.

Related

How to find number of subarrays whose product is divisible by 4 in linear time

I tried but I am not able to correctly implement it.
This is the code I wrote which is wrong as I am not counting some of the subarrays.
Is it possible to write an algorithm which runs is O(n)
int even=0 , count =0 ;
for( int i=0 ; i<n ; ++i ) {
if(arr[i]%4==0) {
count = count + n - i ;
if(even==1) {
count = count + n - i ;
--even;
}
}
else if(a[i]%2==0) {
++even;
if(even==2) {
count = count + n - i ;
--even;
}
}
}
Sample I/O - if arr[] = {1,4,9} then answer should be 4 as {1,4} , {1,4,9} , {4,9} , {4} have their products divisible by 4 .
This is codechef online currently going April challenge related query.as per online contest rules abd regulations. don't spoil the contest... You can check it out after april 13 3 :00 pm.
please refrain from answering the questions
its related to an ongoing problem in a constest
I hope u guys understand.
here's the contest and problem link
https://www.codechef.com/APRIL20B/problems/SQRDSUB
Please abide by it as a token of appreciation for those who do solve it on there own
EDIT: NOW SINCE THE CONTEST IS OVER I AM PROVIDING AN ANSWER ON APRIL 14 2020
NOTE: The code is written in python3
def ALL_SUBS_PRO_DIV_BY_4(arr, n):
even_ind = [i for i,it in enumerate(arr) if it%2==0]
TOTAL_COUNT = 0
last = -1
while even_ind:
ind = even_ind.pop(0)
if arr[ind]%4==0:
TOTAL_COUNT += (ind-last) * (n-ind)
last = ind
else:
if even_ind:
ind2 = even_ind[0]
TOTAL_COUNT += (ind - last)*(n-ind2)
else:
return TOTAL_COUNT
last = ind
return ans
I know a lot of you guys may need an explanation but i guess u can simply run the code and print the values to see what is happening
In any case if someone needs an explanation please leave a comment below. I might upload a google doc explaining the algo
I am not sure if this can be solved in linear time complexity.
However, the below link has a few approaches to this problem.
I hope it helps.
https://www.geeksforgeeks.org/count-sub-arrays-whose-product-is-divisible-by-k/

need help for codejam question "PARENTING PARTNERSHIP"

This question was asked on 4th april in google codejam : https://codingcompetitions.withgoogle.com/codejam/round/000000000019fd27/000000000020bdf9.
The description of question is :
Cameron and Jamie's kid is almost 3 years old! However, even though the child is more independent now, scheduling kid activities and domestic necessities is still a challenge for the couple.
Cameron and Jamie have a list of N activities to take care of during the day. Each activity happens during a specified interval during the day. They need to assign each activity to one of them, so that neither of them is responsible for two activities that overlap. An activity that ends at time t is not considered to overlap with another activity that starts at time t.
For example, suppose that Jamie and Cameron need to cover 3 activities: one running from 18:00 to 20:00, another from 19:00 to 21:00 and another from 22:00 to 23:00. One possibility would be for Jamie to cover the activity running from 19:00 to 21:00, with Cameron covering the other two. Another valid schedule would be for Cameron to cover the activity from 18:00 to 20:00 and Jamie to cover the other two. Notice that the first two activities overlap in the time between 19:00 and 20:00, so it is impossible to assign both of those activities to the same partner.
Given the starting and ending times of each activity, find any schedule that does not require the same person to cover overlapping activities, or say that it is impossible.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts with a line containing a single integer N, the number of activities to assign. Then, N more lines follow. The i-th of these lines (counting starting from 1) contains two integers Si and Ei. The i-th activity starts exactly Si minutes after midnight and ends exactly Ei minutes after midnight.
Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is IMPOSSIBLE if there is no valid schedule according to the above rules, or a string of exactly N characters otherwise. The i-th character in y must be C if the i-th activity is assigned to Cameron in your proposed schedule, and J if it is assigned to Jamie.
If there are multiple solutions, you may output any one of them.
Input :
4
3
360 480
420 540
600 660
3
0 1440
1 3
2 4
5
99 150
1 100
100 301
2 5
150 250
2
0 720
720 1440
Output :
Case #1: CJC
Case #2: IMPOSSIBLE
Case #3: JCCJJ
Case #4: CC
My approach :
sort the task values on basis of starting or ending time and check whether it can be assigned to C or J. If all the task can be assigned then all good otherwise impossible.
I tried sorting on basis of both start time and end time but for both the cases got WA.
if someone can point out what i'm missing in implementation that qoulfd be very helpful.
My code:
#include<bits/stdc++.h>
using namespace std;
typedef struct task
{
int start_time;
int finish_time;
task()
{
this->start_time=0;
this->finish_time=0;
}
task(int start_time, int finish_time)
{
this->start_time=start_time;
this->finish_time=finish_time;
}
bool operator<(const task t)
{
return this->start_time<t.start_time;
}
}task;
int main()
{
int t;
cin>>t;
int a=1;
while(t--)
{
int n,st,ft;
cin>>n;
char res[1005];
int index = 0;
vector<task> task_list;
for(int i=0;i<n;i++)
{
cin>>st>>ft;
task t1(st,ft);
task_list.push_back(t1);
}
sort(task_list.begin(),task_list.end());
task j_task, c_task;
for(int i=0;i<n;i++)
{
if(task_list[i].start_time>=j_task.finish_time)
{
j_task = task_list[i];
res[index++] = 'J';
}
else if(task_list[i].start_time>=c_task.finish_time)
{
c_task = task_list[i];
res[index++] = 'C';
}
else
{
index = 0;
break;
}
}
if(index!=0)
{
res[index] = '\0';
cout<<"Case #"<<a++<<": "<<res<<endl;
}
else
{
cout<<"Case #"<<a++<<": "<<"IMPOSSIBLE"<<endl;
}
}
return 0;
}
You are asked to assign 'C' or 'J' to the original order of the tasks given in the input. So before sorting, you should save the index of the tasks and once sorted, assign 'C' or 'J' to those saved indices.

Multiply numbers which are divisible by 3 and less than 10 with a while loop in c++?

In C++, I should write a program where the app detects which numbers are divisible by 3 from 1 till 10 and then multiply all of them and print the result. That means that I should multiply 3,6,9 and print only the result, which is 162, but I should do it by using a "While" loop, not just multiplying the 3 numbers with each other. How should I write the code of this? I attached my attempt to code the problem below. Thanks
#include <iostream>
using namespace std;
int main() {
int x, r;
int l;
x = 1;
r = 0;
while (x < 10 && x%3==0) {
r = (3 * x) + 3;
cout << r;
}
cin >> l;
}
Firstly your checking the condition x%3 == 0 brings you out of your while - loop right in the first iteration where x is 1. You need to check the condition inside the loop.
Since you wish to store your answer in variable r you must initialize it to 1 since the product of anything with 0 would give you 0.
Another important thing is you need to increment the value of x at each iteration i.e. to check if each number in the range of 1 to 10 is divisible by 3 or not .
int main()
{
int x, r;
int l;
x = 1;
r = 1;
while (x < 10)
{
if(x%3 == 0)
r = r*x ;
x = x + 1; //incrementing the value of x
}
cout<<r;
}
Lastly I have no idea why you have written the last cin>>l statement . Omit it if not required.
Ok so here are a few hints that hopefully help you solving this:
Your approach with two variables (x and r) outside the loop is a good starting point for this.
Like I wrote in the comments you should use *= instead of your formula (I still don't understand how it is related to the problem)
Don't check if x is dividable by 3 inside the while-check because it would lead to an too early breaking of the loop
You can delete your l variable because it has no affect at the moment ;)
Your output should also happen outside the loop, else it is done everytime the loop runs (in your case this would be 10 times)
I hope I can help ;)
EDIT: Forget about No.4. I didn't saw your comment about the non-closing console.
int main()
{
int result = 1; // "result" is better than "r"
for (int x=1; x < 10; ++x)
{
if (x%3 == 0)
result = result * x;
}
cout << result;
}
or the loop in short with some additional knowledge:
for (int x=3; x < 10; x += 3) // i know that 3 is dividable
result *= x;
or, as it is c++, and for learning purposes, you could do:
vector<int> values; // a container holding integers that will get the multiples of 3
for (int x=1; x < 10; ++x) // as usual
if ( ! x%3 ) // same as x%3 == 0
values.push_back(x); // put the newly found number in the container
// now use a function that multiplies all numbers of the container (1 is start value)
result = std::accumulate(values.begin(), values.end(), 1, multiplies<int>());
// so much fun, also get the sum (0 is the start value, no function needed as add is standard)
int sum = std::accumulate(values.begin(), values.end(), 0);
It's important to remember the difference between = and ==. = sets something to a value while == compares something to a value. You're on the right track with incrementing x and using x as a condition to check your range of numbers. When writing code I usually try and write a "pseudocode" in English to organize my steps and get my logic down. It's also wise to consider using variables that tell you what they are as opposed to just random letters. Imagine if you were coding a game and you just had letters as variables; it would be impossible to remember what is what. When you are first learning to code this really helps a lot. So with that in mind:
/*
- While x is less than 10
- check value to see if it's mod 3
- if it's mod 3 add it to a sum
- if not's mod 3 bump a counter
- After my condition is met
- print to screen pause screen
*/
Now if we flesh out that pseudocode a little more we'll get a skeletal structure.
int main()
{
int x=1//value we'll use as a counter
int sum=0//value we'll use as a sum to print out at the end
while(x<10)//condition we'll check against
{
if (x mod 3 is zero)
{
sum=x*1;
increment x
}
else
{
increment x
}
}
//screen output the sum the sum
//system pause or cin.get() use whatever your teacher gave you.
I've given you a lot to work with here you should be able to figure out what you need from this. Computer Science and programming is hard and will require a lot of work. It's important to develop good coding habits and form now as it will help you in the future. Coding is a skill like welding; the more you do it the better you'll get. I often refer to it as the "Blue Collar Science" because it's really a skillset and not just raw knowledge. It's not like studying history or Biology (minus Biology labs) because those require you to learn things and loosely apply them whereas programming requires you to actually build something. It's like welding or plumbing in my opinion.
Additionally when you come to sites like these try and read up how things should be posted and try and seek the "logic" behind the answer and come up with it on your own as opposed to asking for the answer. People will be more inclined to help you if they think you're working for something instead of asking for a handout (not saying you are, just some advice). Additionally take the attitude these guys give you with a grain of salt, Computer Scientists aren't known to be the worlds most personable people. =) Good luck.

forming a recursion function C++ programming

A student can do the things bellow:
a. Do his homework in 2 days
b. Write a poem in 2 days
c. Go on a trip for 2 days
d. Study for exams for 1 day
e. Play pc games for 1 day
A schedule of n days can be completed by any combination of the activities above. For example 3 possible schedules for 7 days are:
homework, poem, homework, play
poem, study, play, homework, study
trip, trip, trip, study
Find a recursive function T(n) that represents the number of all possible schedules for n days.
I have 2 questions...
firstly i had to write a c++ program for this..
#include<iostream>
using namespace std;
int Count(int n)
{
if (n < 1) return 0;
if (n == 2 || n == 1) return 1;
return (3*(Count(n-2))) + (2*(Count(n-1)));
}
int main()
{
cout<<Count(2);
}
For input 2 it's giving answer 1.. shouldn't it be 7? homework ; poem ; trip ; exams,pcgame ; pcgame,exams; pcgame,pcgame; exams,exams
Secondly, suppose i consider pcgame, trip and trip,pcgame as the same combinations. How do i formulate an recursive solution for that?
When n = 2 the following if condition find a true paths,
if (n == 2 || n == 1) return 1;
^^^^^
Hence it returns 1 and terminates the recursion.

A program that takes in a matrix and outputs the fastest path to the "exit" and the number it takes to get there

So I'm having a lot of trouble understanding c++ again I've taken my programming class twice and failed. I need help. I'm not interested in programming anymore because it's obviously not for me. I just need to pass. Here's the problem:
The goal of this assignment is to practice recursive algorithms by writing a program that takes in a matrix representing the number of guards in each room of the castle and outputs the fastest path to the princess and the number of guards you will have to fight.
You're moving through a map(array) that looks like:
5 5
6 2 3 44 15
1 7 2 9 10
11 1 5 14 12
5 17 2 1 20
21 7 33 4 25
Where the first to numbers are the size of your array and you can only move right and down.
So an output would be:
50 > > v v v > v >
We're given a skeleton which we have to fill in but I don't know what some of it does and it might be too long to copy and paste here, I'm new to the community.
How would you tackle this assignment
Using recursion you try to simplify the problem. So take a step right, compute the score for this step and add it to the rest of the solution by calling the same function on a smaller matrix (leaving out the left column). Then take a step down and do the same with the smaller matrix leaving out the top row. Then choose the solution with the lowest score.
This is just a dynamic programming problem.
I don't know how to pass a 2-d array as a function parameter.
Someone correct me please(How to pass 'matrix' array and 'result' array as function parameters). Rest all part is fine
Algorithm is simple. Just start from the last position and come backwards.
where result[i][j] = min(result[i+1][j],result[i][j+1])
void function(int a,int b,int** matrix,int** result){
if(result[a+1][b] == -1 && result[a][b+1] == -1){
result[a][b] = min(function(a+1,b,matrix,result),function(a,b+1,matrix,result));
}
else if(result[a+1][b] == -1 && result[a][b+1] != -1){
result[a][b] = min(function(a+1,b,matrix,result),result[a][b+1]);
}
else if(result[a+1][b] != -1 && result[a][b+1] == -1){
result[a][b] = min(result[a+1][b],function(a,b+1,matrix,result));
}
return;
}
int main(){
int p,q;
cin>>p>>q;
int matrix[p][q];
for(int i=0;i<p;i++){
for(int j=0;j<q;j++){
cin>>matrix[i][j];
}
}
int result[p][q];
for(int i=0;i<p;i++){
for(int j=0;j<q;j++){
result[i][j] = -1;
}
}
result[p-1][q-1] = matrix[p-1][q-1];
for(int i=q-2;i>=0;i++){
result[p-1][i] = matrix[p-1][i] + result[p-1][i+1];
}
for(int i=p-2;i>=0;i++){
result[i][q-1] = matrix[i][q-1] + result[i+1][q-1];
}
function(0,0,matrix,result);
cout<<results[0][0]<<endl;
}