Sorting array and saving the old index in C++ - c++

I am doing online challenge which has to do the following.
There is a contest going in a village. So in the first line input two numbers N (which is how many people will join the contest) and K (how many of them can go to stage 2).
After that, we input N times the votes for each candidate in both stages.
Example input:
5 3
9 2
3 10
5 6
8 4
6 5
As you can see, we input N=5, K=3, which means 5 candidates, so 5 additional lines and 3 of them which go to stage 2.
After we sort the array the candidates with most votes are the ones with 6, 8 and 9. So they're going to stage 2. The winner is the one who has most votes in the stage 2 of them. In this case, 6 has 5 votes which is the most (8 has 4 and 9 has 2) and therefore we output the index of the 6 which is 5.
What I got so far:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int arr[50],nizabackup[50],n,k,niza2[50],saveindex[50],indexp=0;
cin >> n >> k;
for(int i=0;i<n;i++)
{
cin >> arr[i] >> niza2[i];
nizabackup[i] = arr[i];
}
sort(arr,arr+n);
for(int j=n;j>=k;j--)
{
for(int k=0;k<n;k++)
{
if(arr[j]==nizabackup[k])
{
saveindex[0]=k;
indexp++;
}
}
}
sort(saveindex,saveindex+indexp);
cout << saveindex[indexp];
return 0;
}
I need a hint what to do and also additional question -- why my debugger doesn't read the second for loop?

OK, alternative implementation. There's more set-up, but read main first and see how much simpler the actual logic is.
#include <vector>
#include <iostream>
#include <algorithm>
struct Contestant {
int index;
int firstVote;
int secondVote;
Contestant(int i, int v1, int v2) : index(i), firstVote(v1), secondVote(v2)
{}
};
// return true if l should come before r in sorted result
bool byFirstVote(Contestant const &l, Contestant const &r) {
return l.firstVote > r.firstVote; // sort by first vote
}
bool bySecondVote(Contestant const &l, Contestant const &r) {
return l.secondVote > r.secondVote; // sort by second vote
}
int main()
{
int n, k;
std::cin >> n >> k;
// populate a single vector of {index, firstVote, secondVote}
std::vector<Contestant> contestants;
for(int i=0; i<n; i++) {
int v1, v2;
std::cin >> v1 >> v2;
contestants.push_back(Contestant(i+1, v1, v2));
}
// sort all by firstVote, then sort first k by secondVote
std::sort(contestants.begin(), contestants.end(), byFirstVote);
std::sort(contestants.begin(), contestants.begin()+k, bySecondVote);
std::cout << contestants.front().index << std::endl;
}
I'm storing the index (starting from 1, not zero, as per your example), and both votes, all together in a single structure.
Then, I just change which field I sort on.

Related

What's wrong in my approach in a problem of game of death in a circle?

#include<bits/stdc++.h>
#include<vector>
#include<algorithm>
using namespace std;
void safe(int n,int k,int a[])
{
vector<int>s(a+0,a+n);
vector<int>b(a+0,a+n);
while(s.size()>1)
{
int r;
r=s.size();
int count=1;
while(count<=r)
{
b[count%r]=0;
count=count+k;
}
b.erase(remove(b.begin(),b.end(),0),b.end());
s=b;
}
for(int x:s)
{
cout<<x<<"\n";
}
}
int main()
{
int t;
cin>>t;
for(int i=0;i<t;i++)
{
int n,k;
cin>>n>>k;
int *a=new int[n];
for(int j=1;j<=n;j++)
{
a[j-1]=j;
}
if(n>2)
{
safe(n,k,a);
}
else if(n==2)
{
cout<<a[1]<<"\n";
}
else
cout<<a[0]<<"\n";
}
}
Input:
4
4 2
5 2
2 1
50 10
Output:
1
3
2
19 --> it should be 36
If you don't know this problem
Description of question:
There are n people standing in a circle (numbered clockwise 1 to n) waiting to be executed. The counting begins at point 1 in the circle and proceeds around the circle in a fixed direction (clockwise). In each step, a certain number of people are skipped and the next person is executed. The elimination proceeds around the circle (which is becoming smaller and smaller as the executed people are removed), until only the last person remains, who is given freedom.
Given the total number of persons n and a number k which indicates that k-1 persons are skipped and kth person is killed in circle. The task is to choose the place in the initial circle so that you are the last one remaining and so survive.
Consider if n = 5 and k = 2, then the safe position is 3.
Firstly, the person at position 2 is killed, then person at position 4 is killed, then person at position 1 is killed. Finally, the person at position 5 is killed. So the person at position 3 survives.
Here is a possible solution, hopefully the comments make it clear. There's no need to allocate an int[] and copy it into the vector, you can init the vector directly with iota. Likewise you can remove elements as you go, rather than zeroing and removing as a later step.
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
void safe(int n, int k) {
vector<int> s(n);
// Init the vector 1..n
iota(s.begin(), s.end(), 1);
int i = 0;
// While more than one survive...
while (s.size() > 1) {
// Skip forward (k-1)
i = (i + k - 1) % s.size();
// Kill the next one
s.erase(s.begin() + i);
}
for (int x : s) {
cout << x << "\n";
}
}
int main() {
int t;
cin >> t;
for (int i = 0; i < t; i++) {
int n, k;
cin >> n >> k;
if (n > 2) {
safe(n, k);
} else if (n == 2) {
cout << 2 << "\n";
} else
cout << 1 << "\n";
}
}

Minimum number of points such that each line segment contains a point

I'm tackling with a problem where I have to find the minimum number as well as the points such that all the given line segments would have atleast one point in their span.
Input is of the format - number of line segments followed by start,finish of each.
Output required is of the form - number of points along with its value
My approach: I am sorting the line segments in ascending order of finish values, iterating over them, adding them to the output list: and then comparing line segment start points with that end point. If the given start point is <=, we remove that start,end pair.
My code:
#include <algorithm>
#include <iostream>
#include <climits>
#include <vector>
using std::vector;
struct Segment {
int start, end;
};
struct less_than_key
{
inline bool operator() (const Segment& struct1, const Segment& struct2)
{
return (struct1.end < struct2.end);
}
};
vector<int> optimal_points(vector<Segment> &segments) {
vector<int> points;
sort(segments.begin(),segments.end(),less_than_key());
vector<Segment> ss = segments;
vector<int> output;
int p=0;
int t=0;
while(segments.size()!=0)
{
int m = segments[p].end;
int q=0;
output.push_back(m);
while(t==0)
{
if(q>=segments.size())
{
t=t+1;
continue;
}
if(segments[q].start<=m)
{
segments.erase(segments.begin()+q);
q=q-1;
}
q=q+1;
}
}
return output;
}
int main() {
int n;
std::cin >> n;
vector<Segment> segments(n);
for (size_t i = 0; i < segments.size(); ++i) {
std::cin >> segments[i].start >> segments[i].end;
}
vector<int> points = optimal_points(segments);
std::cout << points.size() << "\n";
for (size_t i = 0; i < points.size(); ++i) {
std::cout << points[i] << " ";
}
}
This code is working for very particular inputs and resulting in infinite loops in some. The logic should work perfectly on paper but my code is bugging out somewhere.
Running data -
Input -
3
1 3
2 5
3 6
Output -
1
3
Works correctly as the point 3 will result in each segment having a point.

Am I misunderstood? The answer that appears to be distorted about DFS

The answer are wrong Am I misunderstood? in DFS
Could someone please advice where the mistake has been done at my end?
I have checked that there is no bug in the program but the answer is wrong.
this for my test case
6
10
4 3
3 1
3 4
5 2
5 6
6 5
1 2
1 3
2 1
2 5
1
this is my input.
result is 1 2 5 6 3 4.
#include <bits/stdc++.h>
using namespace std;
const int N = 10000;
vector<bool> vis(N, -1);
vector<int> adj[N]; /// keep adj list
bool visited[N];
int dis[N] = {0};
void DFS(int start){
cout << start << " ";
vis[start] = true;
for(int i=0;i<adj[start].size() ; i++){
if(vis[i] == -1){
DFS(i);
}
}
}
int main() {
int edge, node;
cin >> node;
cin >> edge;
for (int i = 0; i < edge; i++){
int first,second;
cin >> first;
cin >> second;
adj[first].push_back(second);
adj[second].push_back(first);
}
int start_node;
cin >> start_node;
DFS(start_node);
return 0;
}
In order for if(vis[i] == -1) to work you need to initialize all the values in your vector to -1 before starting the algorithm.
Also, I would advise you to use vector<bool> instead.
Your for loop is not good. it should go
for (const auto elem : adj[start])
{
if(!vis[elem])
{
DFS(elem);
}
}
That is, you need to iterate over adj ELEMENTS, not over number of elements.
Other way to iterate over elements would be to change your if statement to be
if(!vis[adj[start][i]])
but that leaves you with other possible errors, so stick to the one above.
Also, you have many other errors, such as node variable not being used and you have duplicate edges, but all of those are fixable with some practice.
Happy learning!

Finding 3 or more duplicates in array

I need write a program which checks if there are 3 or more matching numbers in an array. My code works fine until there is an array like "2 2 3 3 5 5 4 4 1 1", then it approves that there are 3 or more duplicates in the array which is not true. Maybe someone knows a simple solution which would help me? Or do I need to overwrite my code?
Here is my code:
#include <iostream>
using namespace std;
void funk(int n, int a[], int &kiek);
int main()
{
int n, a[101],kiek=0;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
funk(n, a, kiek);
if (kiek > 2) {
cout << "TAIP";
}
else
cout << "NE";
}
void funk(int n, int a[], int &kiek)//funkcijos kūnas
{
int j;
for (int i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
if (a[i] == a[j])
kiek++;
cout << kiek;
}
}
}
This is the input:
10
2 2 3 3 5 5 4 4 1 1
This is the output I need to get:
NE
The problem that your code has is:
You are comparing any 2 numbers and never reset the counter. So if there is an 1 1, you are increasing the counter. If there is then an 2 2 you are also increasing the counter. And for the final 3 3 you also increase the same counter. Then it is 3. Although there are only 2 same values. This can never work. What you could do is
Read all values
Count the frequency of EACH different value
Check if the frequency of the values
If any of the counts is greater than 2, then show corresponding message
Show count of each value
I will show you the "more-modern" C++ approach and will use C++ algorithms for the below example solution.
First we will get the number of values to work with from the user. We will store the values in a std::vector. And, we use std::copy_n to copy the values from std::cin to our std::vector. For that we will use the std::istream_iterator that will iterate over the elements given by the user. So, we use a simple one-liner to read all values from the user.
Next is the frequency counting. For this we have a standard solution in C++. You will find it in dozens of places in the net. We will use a std::map. The key is the integer that we read into the vector and the value is the counter. With the std::map's index operator [] we add a value to the map, if it is not yet existing. With the ++ we simply do the counting, whether the value was already in the std::map or has just been added. Also this is a very simple one-liner.
Then, we check, if any of the counts is greater than 2. For this we will use the STL algorithm std::any:of with a very simple lambda. With that, we can create your desired result.
Last, but not least, we show all values and their count, if the count is greater than 2. This we do with an ultra simple range based for loop. We extract the values out of the counter-std::map using structered bindings.
Please see:
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <iterator>
int main() {
// Give instructions
std::cout << "How many values do you want do read? Please specify: ";
// Read the number of values to enter
size_t numberOfValues{ 0U }; std::cin >> numberOfValues;
// Read the given number of values from std::cin
std::vector <int> values(numberOfValues);
std::copy_n(std::istream_iterator<int>(std::cin), numberOfValues, values.begin());
// Count each value
std::map<int, size_t> counter{};
std::for_each(values.begin(), values.end(), [&counter](const int& i) { counter[i]++; });
// Check, if any count is bigger than 2
if (std::any_of(counter.begin(), counter.end(), [](const std::pair<int, size_t> & c) { return c.second > 2; }))
std::cout << "TAIP\n";
else
std::cout << "NE\n";
// Look, if there is any number with a count bigger than 2 and show the result
for (const auto& [value, count] : counter)
if (count > 2) std::cout << value << " --> " << count << "\n";
return 0;
}
I hope this gives you an idea on how this could be done . . .

Party Invitation

The problem that I am working on right now is here, but I am of course not looking for the complete answer to this homework problem. All I am asking for is the steps in the final parts of the question. This is what I have so far:
int main()
{
cout << "Please enter the number of guests attending your party: ";
int k;
cin >> k;
cout << "Please enter the number of rounds of removal you'd like to perform: ";
int m;
cin >> m;
for (int i = 1; i <= m; i++) {
cout << "Please enter the multiple at which you'd like the removal to be at for round " << i << ": ";
int r;
cin >> r;
if (k % r == 0) {
k - r;
}
cout << k << endl;
}
system("pause");
}
This is all so confusing to me, and I truly have no idea where to turn to get answers. It seems like I'd need an array to solve this, but arrays in C++ cannot be variable, and the array length would be k, a variable input. Any help would be very appreciated.
I've read that question. you need a dynamic list like Linked list because you need to put and remove different items from different index so using arrays will be difficult.
Try to use std::vector or std::list, you can add or remove any any of list
#include <list>
std::list<int> mylist;
How can you add and remove values from list, check this link http://en.cppreference.com/w/cpp/container/list
For using your own Linklist, check this link How could i create a list in c++?
According to your question an std::vector will be the best choice because it is a combination of an array & linked list in raw terms or we can simply say it's a dynamic array.
However as you mentioned n your comment that you haven't been taught anything other than basic arrays & want a solution within whatever you have learnt, then you have to take an array. Now the problem is that arrays are static & you cannot delete elements from it. So all you can do is to keep a counter that will take care of the number of elements in it.
// array insert and delete
#include <iostream>
using namespace std;
void see_array (int a[], int f, int b)
{
for (int i=f; i<b; ++i)
cout << a[i] << ' ';
cout << '\n';
}
int get_pos (int a[], int f, int b, int num)
{
for (int i=f; i<b; ++i)
{
if (a[i] == num)
return i;
}
return -1; // if search is unsuccessful
}
int main()
{
int a[] = {1,2,3,4,5,6,7,8,9,10};
int front = 0, back = 10; // as we have 10 elements
// delete last element
--back;
see_array(a, front, back);
// delete first element
++front;
see_array(a, front, back);
// delete element from middle say 6
int pos = get_pos(a, front, back, 6);
if (pos != -1)
{
for (int i = pos; i<back; ++i) // shift elements towards left
{
a[i] = a[i+1];
}
--back; // decrease size of the array
see_array(a, front, back);
}
return 0;
}
/* Output :-
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9
2 3 4 5 7 8 9
*/
I hope the above program is of some help to you !!! Good luck !!!