How to delete element to compare in two-dimensional structure - c++

I was given an assignment in which the head of a top-secret organization, collecting statistics on retired agents
There are several secret agencies that employ spies. The time has come for the agencies to retire their employees
The given task:
The organization itself consists of 2 structures.
Agency which includes string-title, int-min_mission, int-agent_count and Spy* agents
Spy with the values name, string-speciality, int-completed_missions and bool-is_private.
I would like to point out that spies have only 3 specialty categories ("Diplomacy", "SpecOps", "DarkMistery")
Job Purpose: It is necessary to find an agency in which the maximum number of agents have been released.
In order to send them to resign the agency must check a few punuts, after surpassing which, its release from the position is accepted.
These rules are as follows:
His number of missions completed must exceed the minimum that his agency has set. If it is less, the agent cannot release him.
If the agent's speciality is "SpecOps", his minimum number of missions is 2 less than the others.
If an agent's speciality is "DarkMistery", his minimum number of missions is twice that of the others.
If the agent is Private, (that is, if the logical type is_private is == 1), then the agent will never be released
The input to test:
3
"For Angency - 1'st is Agency's name, 2'nd is min_number limit and 3'rd is number of agents" //
"For spies - 1'st is name, 2'nd is his\her speciality and 3'rd is completed missions"
BloodDragonfly 5 6
Jagternaut Diplomacy 7 0
Ditablo DarkMistery 6 0
Sartuman Diplomacy 3 1
Coltosus SpecOps 1 0
Samtanta DarkMistery 11 0
Tantos SpecOps 4 1
GoldenNose 6 4
Smith SpecOps 8 1
Smity DarkMistery 11 0
Smitens Diplomacy 5 0
Smaut DarkMistery 16 0
Lucaduca 10 5
Mario SpecOps 4 0
Puerrio Diplomacy 9 0
Luchio Diplomacy 11 1
Julietio Diplomacy 14 1
Bob DarkMistery 35 1
The value that should be displayed on the monitor OR Output:
Lucaduca
In short, I wrote a command that sorts out which agents can be released.
But I have forgotten how to remove the agents in the array that did pass the check, so that the size of the array changes.
(ignore the variable -> sum)
Here is my code.
#include "iostream"
#include "string"
using namespace std;
struct Spy { //The Spy structure
string name;
string speciality;
int missions;
bool is_private;
};
struct Agency { //The agency structure
string title;
int min_missions;
int agentCount;
Spy* agnt;
};
istream& operator >> (istream& is, Spy& sp) { //The operator to enter the values of spy
is >> sp.name >> sp.speciality >> sp.missions >> sp.is_private;
return is;
}
istream& operator >> (istream& is, Agency& agc) {//To enter the values of Agency
is >> agc.title >> agc.min_missions >> agc.agentCount;
return is;
}
int main() {
int N; cout << "Enter the number of agencies: \n";
cin >> N; //
Agency* agc = new Agency[N];
for (int i = 0; i < N; ++i) { //Creating a loop for the Agency struct, which would store the values of an individual agency
cin >> agc[i];
agc[i].agnt = new Spy[agc[i].agentCount];
for (int j = 0; j < agc[i].agentCount; ++j) { //This is for the struct Spy that will be stored inside the agentCount
cin >> agc[i].agnt[j];
}
}
for (int i = 0; i < N; ++i) {
int sum = 0;
int count = 0;
for (int j = 0; j < agc[i].agentCount; ++j) {
if (agc[i].agnt[j].is_private) { //Сonditional operator to check whether the agent is private or not
continue;
}
else {
if (agc[i].agnt[j].speciality == "DarkMistery") {//To check the speciality of agent
count = (agc[i].min_missions * 2);//If a spy's specialization is DarkMistery,
// he will get double the minimum number of missions than others
}
else if (agc[i].agnt[j].speciality == "SpecOps") {//If a spy's specialization is SpecOps,
count = (agc[i].min_missions - 2); //he/she will get 2 fewer mission than the others
}
else { //f a spy's specialization belongs to the third category
//Nothing will change for him/her
count = agc[i].min_missions;
}
if (agc[i].agnt[j].missions > count) {
sum++;
} else {
continue;
}
}
}
}
}
I tried to identify, through sum, the agency with the maximum number of non-exempt agents. But it will update every time it passes through the next agency.
I tried to use the delete command to delete the spy value, but I don't know how to use it on two-dimensional structures
I expect to see a change in the array agc[i].agentCount
so that it changes its size is dynamic if it is appropriate for this code of course.

If you only want to keep track of the number of agents an agency should release, you are almost done:
You could use a map from agency names to number of agents to be released.
Then, in your last two nested loops:
Before the inner loop, you reset a counter of agents to be released.
With each iteration of that inner loop, you update that counter.
After the inner loop, you insert a new element in the map, namely the name of the agency and the number of agents to be released.
The code below does that, although I'm afraid to say that the output is different than the expected (BloodDragonfly instead of Lucaduca). That may have to do with the input data or with the algorithm to decide if an agent has to be released.
[Demo]
using map_of_agents_to_be_released_per_agency_t = std::unordered_map<std::string, int>;
map_of_agents_to_be_released_per_agency_t agents_to_be_released{};
for (int i = 0; i < no_of_agencies; ++i) {
auto& agency{ agencies[i] };
int no_of_agents_to_be_released = 0;
for (int j = 0; j < agency.agent_count; ++j) {
auto& agent{ agency.agents[j] };
if (not agent.is_private) {
if (agent.speciality == "DarkMistery") {
if (agent.missions > agency.min_missions * 2) {
no_of_agents_to_be_released++;
}
} else if (agent.speciality == "SpecOps") {
if (agent.missions > agency.min_missions - 2) {
no_of_agents_to_be_released++;
}
} else if (agent.speciality == "Diplomacy") {
if (agent.missions > agency.min_missions) {
no_of_agents_to_be_released++;
}
}
}
}
agents_to_be_released.insert({agency.title, no_of_agents_to_be_released});
}
fmt::print("Agents to be released: {}\n", agents_to_be_released);
fmt::print("Agency with more agents to be released: {}\n",
std::ranges::max_element(
agents_to_be_released,
std::less<>{},
&map_of_agents_to_be_released_per_agency_t::value_type::second
)->first);
// Outputs:
//
// Agents to be released: {"Lucaduca": 0, "GoldenNose": 1, "BloodDragonfly": 2}
// Agency with more agents to be released: BloodDragonfly

Related

Finding the minimum value

I can't begin to understand how to approach this problem. Can someone help me to just point me in the direction as to how I can approach it?
N tasks are given and there are M workers that are available. Each worker can takes different times to complete each task. The time taken by each worker for every task is given. At any time only one task can be worked on by only one worker. But the condition is once a worker has stopped working, he can't work on any task again. I want to find out what is the minimum time required to finish all the tasks. Here's an example-
M = 3
N = 4 {T1, T2,T3,T4}
No of days required by each worker (Wi) for each task (Ti) -
There are many ways to finish the task, some of them are -
All the tasks are done by the W1 ===> total time taken = 1+2+2+3 = 8
All the tasks are done by the W2 ===> total time taken = 3+1+3+2 = 9
All the tasks are done by the W3 ===> total time taken = 1+1+6+6 = 14
T1,T2,T3 done by W1 and T4 done by W2 ===> total time taken = 1+2+2+2 = 7
T1,T2 done by W1 and T3,T4 done by W3 ===> total time taken = 1+2+6+6 = 15
T1,T2 done by W3, T3 done by W1 and T4 done by W2 ===> total time taken = 1+1+2+2 = 6
There are more possible ways but the one that gives the smallest time taken is the 6th one (also shown in the picture below).
I was just able to understand how to do it when the number of workers are only 2. I did it this way -
#include<iostream>
using namespace std;
int N=4,M=2;
int main()
{
int i,j,min=INT_MAX;
int sum,sum1;
int w0[N] = {1,2,2,3};
int w1[N] = {3,1,3,2};
for(i=0;i<N;i++)
{
sum=0;
sum1=0;
for(j=0;j<i;j++)
{
sum+=w0[j];
sum1+=w1[j];
}
for(j=N-1;j>=i;j--)
{
sum+=w1[j];
sum1+=w0[j];
}
if(sum<sum1)
{
if(min>sum)
min = sum;
}
else
{
if(min>sum1)
min = sum1;
}
}
cout<<min;
return 0;
}
I tried to explain it using another table below -
But this way I can only find min value for 2 workers. I need help to to understand the approach for more than 2 workers.
Can there also be a DP solution possible for this?
The best way I can think to solve this is using recursion. I would implement this by having a list of unusable workers and a running sum passed to each call, and a global variable of minimum value.
This would also work best if you had a matrix of values. So like matrix[0] = {1, 2, 3}; matrix[1] = {3, 4, 5}. I haven't hardcoded a matrix in a while so please forgive me if the syntax is a little off.
So, using global variables for the matrix this would look something like
int matrix[m][n];
int runningMinimum = INT_MAX; //set the runningMinimum to max so any value compared will be lower
void minimum(int i, vector<int> bannedWorkers, int currentWorker, int sum){
//test the end condition here
if (i == n-1){//last column
if (sum < runningMinimum){runningMinimum = sum;}
return; //we want to return at the end, whether it's found the new lowest value or not
//if we're not at the end, we need to move one step to the right for all possible workers
for (int j = 0; j < m; j++){//For each worker
//check to see if the worker is no longer allowed to work
bool isBanned = false
for (int k = 0; k < bannedWorkers.size(); k++){
if (bannedWorkers[k] == j) isBanned = true;
}
if(!isBanned){
if (j == currentWorker){
minimum(i+1, bannedWorkers, currentWorker, sum+matrix[j][i])
}else{
vector<int> newBannedWorkers = bannedWorkers; //Make sure to copy to a new vector
newBannedWorkers.push_back(currentWorker);
minimum(i+1, newBannedWorkers, j, sum + matrix[j][i])
}
}
}
return; //after we've checked every option we want to end that call
}
This is a rough, untested idea but it should give you a solid start. Hope it helps!
Probably not the best approach if the number of workers is large, but easy to understand and implement I think. I would:
get a list all the possible combination with repetition of W, for example using the algorithm in https://www.geeksforgeeks.org/combinations-with-repetitions/ . This would give you things like [[W1,W3,W2,W3,W1],[W3,W5,W5,W4,W5]...
Discard combinations where workers are not continuous (loop through the lists counting the times each worker appears in total and the times it appears continuously, if its different then discard the list)
Use the filtered list of lists to check times using the table and keep the minimum one
A possible way to discard lists could be
bool isValid=true;
for (int kk = 0; kk < workerOrder.Length; kk++)
{
int state=0;
for (int mm = 0; mm < workerOrder.Length; mm++)
{
if (workerOrder[mm] == kk && state == 0) { state = 1; } //it has appeard
if (workerOrder[mm] != kk && state == 1 ) { state = 2; } //it is not contious
if (workerOrder[mm] == kk && state == 2) { isValid = false; break; } //it appeard again
}
if (isValid==false){break;}
}

Algorithm correctness for Bank Kattis problem

This is the problem I am referring to. In quick summary:
Input: An integer time T; the time in minutes in which a bank closes and a set of pairs c and t that denotes the amount of cash (integer) this person carries and the time in minutes from now after which person leaves if not served. It takes one minute to serve a person and you must begin serving a person at time t at the latest.
Output: Maximum amount of money that can be collected within closing time.
My approach was this: place all the people in a map that maps money to time. I sort this map by money. I then make a queue-like structure where I take the person with the most money and place him/her as far back as possible. If the spot is occupied, then I move forward until I find a spot. If I can't then I just don't add the person.
Below is my helper function to determine whether or not I can insert a person.
// returns index where we can insert, otherwise -1
int canInsert(bool* queue, int timeToInsert) {
if (!queue[timeToInsert]) {
return timeToInsert;
} else {
int index = timeToInsert-1;
while (index >= 0) {
if (!queue[index]) {
return index;
} else {
index--;
}
}
return -1;
}
}
Here is the main driver function:
// moneyToTime is a map that maps a person's money to the time value
int Bank(int T, map<int, int> moneyToTime) {
int answer = 0;
bool queue[47] = {0};
for (map<int,int>::reverse_iterator i = moneyToTime.rbegin(); i != moneyToTime.rend(); i++) {
if (T > 0) {
// try to insert. If we can, then add to sum. Otherwise, don't.
int potentialIndex = canInsert(queue, i->second);
if (potentialIndex != -1) {
queue[potentialIndex] = 1;
answer += i->first;
T--;
}
} else {
break;
}
}
return answer;
}
Logically, this makes sense to me and it is passing almost all the test cases. There are a couple that are failing; I can not see what they are. The test case errors are in fact indicating wrong answer, as opposed to bad runtime errors. Can someone help me see the fallacy in my approach?
You don't show how you build the moneyToTime but anyway it looks like map<int, int> is a wrong type for that. Imagine you have many people with the same amount of money and different timings. How would you represent then in your moneyToTime?
If my theory is correct, an example like this should break your solution:
3 3
2000 2
2000 1
500 2
Obviously the best sum is 4000 = 2000 + 2000. I suspect you get only 2500.
I think the best sum for the TC is 4500,
3 3
2000 2
2000 1
500 2
{money, time}
{2000,0} | {2000,1} | {500,2}

Boolean variable is automatically changing its value

This problem is from SPOJ. I was required to find whether the graph is Bi-partite or not. I'm using BFS to find it.
The problem here is in a while loop under the section //PROBLEM COMING HERE (please see the code under to find this statement.)
Problem description:
I want to toggle between 0 and 1. So I have chosen a bool value called flag and initialised it with 0. Now, per iteration I want to toggle it's value. So I have used flag = !flag. However, for some unknown reasons the flag value automatically toggles after the first iteration before executing the statement flag = ! flag.
So, because of this lot of problems are coming.
//BUG LIFE
#include <cstdio>
#include <vector>
#include <queue>
#define DEFAULT 2
using namespace std;
int main()
{
int t,n,e;
bool eflag;
//freopen("input.txt", "r", stdin);
//Taking the Testcase
scanf("%d",&t);
//Iterating each Testcase
for(int itr=1; itr<=t; itr++)
{
//n is the number of nodes in the graph and e is the no of edges.
scanf("%d %d",&n,&e);
//eflag is exit flag in short. this is used to early exit to save time if we already found out that the given graph isn't bi-partite.
//Assuming the graph is bi-partite hence eflag = false meaning no exit is required yet.
eflag = false;
//Graph data structure vector 2D Array
vector < vector < int > > graph(n+1);
//Taking edges as input and adding in the graph
for(int i = 1; i <=e; i++)
{
int v1,v2;
scanf("%d %d",&v1,&v2);
graph[v1].push_back(v2);
graph[v2].push_back(v1);
}
//Check the graph is bi-partite or not
//vis is an array which will hold whether a node has been explored or not. label is an array which segregates all the nodes in two groups 0 or 1.
bool vis[n+1]; int label[n+1];
//Initialising vis and label.
for(int i=1; i<=n; i++)
{
vis[i] = 0;
//DEFALUT VALUE IS 2. This is to tell that label of the node i hasn't been given yet or in otherwords, it's not be put in a group yet.
label[i] = DEFAULT;
}
//Taking nodes one by one and doing a BFS on it.
//LOGIC Here is: Take a node assign it a label 0 and add all the children of it in the queue and give them label 1. Now explore all children and give their children label 0. So like this, we alternate between labels.
//Now if we see that a node already has a label apart from 2 and a children is trying to label it with something different label it will mean that specific node is involved in both the groups. Hence we will set the eflag as true.
for(int i=1; i<=n && !eflag; i++)
{
if(!graph[i].empty() && !vis[i])
{
//Initialising the queue and adding the first node which has children.
queue <int> q;
q.push(i); bool flag;
//PROBLEM COMING HERE
//Assigning the label for this node as 0. meaning group 0
label[i] = 0; flag = false;
//BFS Starts
while(!q.empty() && !eflag)
{
int x = q.front(); q.pop();
printf("%d **\n",flag);
//The children of this node needs to have different label than parent. Hence flag = !flag
flag = !flag;
printf("%d %d\n",x,flag);
if(vis[x]) continue;
vis[x] = 1;
//Exploring the children and assigning them labels
for(vector <int>::iterator it = graph[x].begin(); it != graph[x].end(); it++)
{
//If the children doesn't have a default label and the label which it has is different than the one the parent is trying to put then it means that this child belongs to both the groups 0 and 1. So exit.
if(label[*it] != DEFAULT && label[*it] != flag)
{
printf("%d %d %d %d\n",x,*it,label[*it],flag);
eflag = true;
break;
}
else
{
label[*it] = flag;
}
}
printf("asd %d **\n",flag);
}
//PROBLEM ENDS HERE
}
}
if(eflag == false)
printf("Scenario #%d:\nNo suspicious bugs found!\n",itr);
else
printf("Scenario #%d:\nSuspicious bugs found!\n",itr);
}
return 0;
}
OUTPUT:
0 **
1 1
asd 1 **
0 **
2 1
2 1 0 1
asd 1 **
Scenario #1:
Suspicious bugs found!
Sample Input:
1
3 3
1 2
2 3
1 3
Your assumption in the comment:
After it prints asd 1** it should print again 1 ** because flag = ! flag hasn't been executed yet. However it shows 0 **
Is wrong. (Not the assumption that flag = ! flag hasn't been executed, that's correct.)
In the following snippet, I've cut most of the irrelevant code away (you're welcome). Let's name some of your loops:
for(int i=1; i<=n && !eflag; i++) // outer loop
{
// ..
queue <int> q;
q.push(i); bool flag;
label[i] = 0; flag = false; // (1)
while(!q.empty() && !eflag) // inner loop
{
int x = q.front(); q.pop();
printf("%d **\n",flag); // (2)
flag = !flag;
printf("%d %d\n",x,flag);
// ...
printf("asd %d **\n",flag); // (3)
}
// ...
}
You only ever push exactly one element into q. That's at the top of outer loop. You always pop it at the top of inner loop. Inner loops condition is true only if the queue is not empty. Therefore the inner loop always runs at most once per outer loop. Because the inner loop is never repeated more than once, you always jump to the beginning of the outer loop after printing asd 1** at the end of inner loop (3). At the top of outer loop (1), you assign flag = false. Therefore, regardless of the value of flag when it's printed at (3), it's value will always be false at (2).
As you can see, the variable isn't changing "automatically" or because of "unknown reasons". It's changing because you assign it at (1).

Efficient way to retrieve count of number of times a flag set since last n seconds

I need to track how many times a flag is enabled in last n seconds. Below is the example code I can come up with.StateHandler maintains the value of the flag in active array for last n(360 here) seconds. In my case update function is called from outside every second. So when I need to know how many times it set since last 360 seconds I call getEnabledInLast360Seconds. Is it possible to do it more efficiently like not using an array size of n for booleans ?
#include <map>
#include <iostream>
class StateHandler
{
bool active[360];
int index;
public:
StateHandler() :
index(0),
active()
{
}
void update(bool value)
{
if (index >= 360)
{
index = 0;
}
active[index % 360] = value;
index++;
}
int getEnabledInLast360Seconds()
{
int value = 0;
for (int i = 0; i < 360; i++)
{
if (active[i])
{
value++;
}
}
return value;
}
};
int main()
{
StateHandler handler;
handler.update(true);
handler.update(true);
handler.update(true);
std::cout << handler.getEnabledInLast360Seconds();
}
Yes. Use the fact that numberOfOccurrences(0,360) and numberOfOccurrences(1,361) have 359 common terms. So remember the sum, calculate the common term, and calculate the new sum.
void update(bool value)
{
if (index >= 360)
{
index = 0;
}
// invariant: count reflects t-360...t-1
if (active[index]) count--;
// invariant: count reflects t-359...t-1
active[index] = value;
if (value) count++;
// invariant: count reflects t-359...t
index++;
}
(Note that the if block resetting index removes the need for the modulo operator % so I removed that)
Another approach would be to use subset sums:
subsum[0] = count(0...19)
subsum[1] = count(20...39)
subsum[17] = count(340...359)
Now you only have to add 18 numbers each time, and you can entirely replace a subsum every 20 seconds.
Instead of fixing the buffer, you can simply use std::set<timestamp> (Or perhaps std::queue). Every time you check, pop off the elements older than 360s and count the remaining ones.
If you check scarcely but update often, you might want to add the "popping" to the update itself, to prevent the set from growing too big.

C++ simple array element comparison

Okay I don't know if this is even a valid question but I'm posting here because I don't know where else to turn with this. I just started studying programming this half year at a university and we just had the final exam, which I failed. Basically, there were 4 questions, and while the second one looked easy it was actually tricky and I just can't figure out how it should have been done.
Basically the problem is: There is a bank, and when people log in to do business, you need to write a program that records the time they logged in (0-24h), the minutes (0-59), the type of transaction they choose (1 for logging in with a bank card, -1 for logging out with the same bank card, 2 for money input into the account, -2 for withdrawal) and finally either their bank acc number (if they pressed 1 or -1 previously), or the amount they are withdrawing or putting in (if they chose 2 or -2).
Basically here is how we had to do it:
int n; //size of the array or number of ppl who transacted that day
cin >> n;
int bank[n][4];
for (int i=0; i<n; ++i)
{
cin >> bank[n][0];
cin >> bank[n][1];
cin >> bank[n][2];
cin >> bank[n][3];
}
This fills up all the info and then,
basically a sample input looked like this for 4 customers during the day:
11 40 1 458965
12 20 2 6000
15 40 -1 458965
16 25 -2 18000
Here is the part I could not solve:
Our test asked us: How many people were logged in from 12 o clock to 13:00 oclock?
At first I did
int count=0;
for (int i=0; i<n; ++i)
{
if (bank[i][0]==12)
{
count=count+1;
}
}
cout << count;
The problem with this, is that it does not account for people who log in before 12 with a 1 in the third column, but log out at later than 1 oclock with a -1. Which means they were still logged in from 12 to 1pm.
so then I did
int count=0;
for (int i=0; i<n; ++i)
{
if (bank[i][0]==12)
{
count=count+1;
}
if (bank[i][2]==-1)
{
count=count+1;
}
}
cout << count;
but then I realized that this would count some logins twice, because if they logged in at 12 with a 1 for example, then logged out at 3 o clock with a -1 it would count that one person twice.
It also asked us what is the longest period that any person was logged in, assuming the bank kicks everyone off at 24:00. I honestly am not even sure how to even begin that one.
EDIT: SORRY i edited a bunch of stuff to make it clearer and correct code. I'm not too good at this yet forgive my mistakes
I didn’t know how the bank system works. So I made a minimal example for you.
I also didn't know if you used classes before, so I wrote it without.
I cleaned your code a bit:
//Use these enums
enum action { action_login = 1, action_logout = -1, action_input = 2, action_output = -2 };
enum information {information_time_h, information_time_m, information_action, information_bankNumber};
//Place this in the function you have
int peapelToInput = 0; //size of the array or number of ppl who transacted that day
cin >> peapelToInput;
for (int i=0; i<peapelToInput; ++i)
{
//Maby add error handeling? When some one inputs a 'a', it won't do what you want.
cin bank[i][information_time_h];
cin bank[i][information_time_m];
cin bank[i][information_action];
cin bank[i][information_bankNumber];
}
As you can see, I made the code cleaner by adding enums. This makes developing a lot easier.
The login code:
int count=0;
int bankSize = bank.size(); //I guess it's a vector?
for (int i=0; i < bankSize; ++i)
{
if (bank[i][information_time_h] == 12 && bank[i][information_action] == action_login)
count++;
}
cout << "logins at 12:00 - 12:59:" << count << endl;
You can do 2 checks in 1 if, I increment count when they were logedin from 12:00 - 12:59. Do you need exclude people that were loggedout?
The longest time code:
//A function to search when he is logedout
int findLogoutIndex(int start, int accountNumber, XXX bank)
{
int bankSize = bank.size();
for (int i=start; i < bankSize; ++i)
if( bank[i][information_action] == action_logout && bank[i][information_bankNumber] == accountNumber)
return i;
return -1; //Handle this error
}
//And how it workes
int logenst = 0;
int indexLongest = 0;
int bankSize = bank.size(); //I guess it's a vector?
for (int i=0; i < bankSize; ++i)
{
if( bank[i][information_action] != action_login )
continue;
int logoutIndex = findLogoutIndex(i,bank[i][information_bankNumber],bank);
//check if logoutIndex is not -1, or handle the error on an other way.
int loginTimeHour = bank[logoutIndex][information_time_h] - bank[i][information_time_h];
int loginTimeMinute = bank[logoutIndex][information_time_m] - bank[i][information_time_m];
int loginTime = (loginTimeHour * 100) + loginTimeMinute;
if( logenst < loginTime)
{
logenst = loginTime;
indexLongest = i;
}
}
cout << "longest is: H:" << bank[indexLongest][information_time_h] << " M: " << bank[indexLongest][information_time_m] << endl;
You don't need to keep the time format, this way makes comparing a lot easier. Just save the longest login time and the index number of it. That way you can easily access all the data you want.
I didn't take the time to write "good code". But you asked how it can be done, I guess this is good enough to understand it?
I didn't test the code and wrote it in Notepad. So I don't know if it will compile.
The first thing that you need to know is what the questions are actually asking. In the first case, How many people were logged in from 12 o clock to 1 oclock? can mean multiple things. It could mean how many people were logged in during the whole period or how many people were logged in at any given time between those two hours. The difference is whether someone that logs in at 12:15 and logs out at 12:30 is counted or not. The second question is calculating the longest period someone was logged in, and that can be done at the same time.
One possible approach would be managing a lookup table from user id to login times. You read the input linearly, whenever someone logs in you add an entry (acct, time) into the table. When they log out you lookup the account number and calculate the difference of times. If the difference is greater than the maximum you store the new maximum.
For the first question, at 12 you can create a set of the people that was logged in from that lookup table. Whenever someone logs out between that time and 1 you find whether the person was in the set and you remove it if so. When you find the first operation after 1, the set contains the account numbers of all the people that was logged in for the whole period from 12 to 1.
If the question was getting all people that was logged at any time in the period, instead of removing from the set those users that log out before 1, you need to include new users that log in inside the period. At the end of the period the set contains all users that were logged in at any time within the period.
You only need to perform a single pass over the input data which means that you don't even need to store all of the transactions in memory, only the map/set required above. The overall cost of the operation is O(n log n) on the number of operations. (Disclaimer: I haven't done the math, this is a hunch :))
Haven't tested this. Nevertheless, the process followed should be correct.
I'm sure this can still be optimized in terms of execution speed.
Also, I assume by time 12 you mean 12:00 and by time 1 you mean 13:00.
int main()
{
int answer = 0;
// For each transaction
for ( int i = 0; i < count; i++ ) {
// If logged in before 12:00
// bank[i][2] > 0 tells you user logged in.
if ( bank[i][0] < 12 && bank[i][2] > 0 ) {
// Loop through each following transaction.
for ( int j = i + 1; j < count; j++ ) {
// If logged out after 13:00
if ( bank[j][0] > 13 && bank[j][2] < 0 ) {
// Now to check if it was the same user who logged in earlier - how?:
// Only way to differentiate is by comparing the transaction amounts and types.
if ( (bank[i][3] == bank[j][3]) && (bank[i][2] == -1*bank[j][2]) ) { // log-in code = -1 * log-out code.
answer++; // Number of transactions that spanned from before 12:00 till after 13:00.
// Remember, a single person can't have multiple log-ins at the same time. ( assumption )
}
}
}
}
}
}