keeping track of vector pair indices upon sorting - c++

Similar things have been asked before but I am having trouble applying the concept. I would like to to keep track of the indices of the pairs in my vector of pairs then, once sorted, std::cout the input order.
e.g.
cin >> 5 6 1 5 1 2 1 2 3 5
cout << 1 2 1 2 1 5 3 5 5 6
cout >> 3 4 2 5 1 //and this is where I am having trouble.
I was thinking of converting to triples, where one of the elements is the index but I couldn't get that to conform to my needs.
Any help would be appreciated. Thank you.
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
using namespace std;
bool compare(const pair<int,int>&A, const pair<int,int>&B);
int main()
{
vector<pair<int,int>> v;
pair<int,int> tok;
while(cin >> tok.first>>tok.second){v.push_back(tok);}
sort(v.begin(),v.end(), compare);
for(int i = (signed int)v.size()-1; i >= 0 ; i--)
{
cout << v.at(i).first << " ";
cout << v.at(i).second << " ";
}
cout << endl;
return 0;
}
bool compare(const pair<int,int>&A, const pair<int,int>&B)
{
return A.first > B.first;
}

Here's one way to do it. Long time since I did someone's homework for them ;-)
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
const string input_data = "5 6 1 5 1 2 1 2 3 5";
typedef pair<int, int> integer_pair;
typedef pair<int, integer_pair> integer_pair_with_input_order;
bool less_by_integer_pair(const integer_pair_with_input_order& l,
const integer_pair_with_input_order& r)
{
return l.second < r.second;
}
int main()
{
// note - I did this to avoid having to type numbers in.
std::istringstream simulate_cin(input_data);
vector<integer_pair_with_input_order> v;
integer_pair tok;
int input_order = 0;
while(simulate_cin >> tok.first >> tok.second) {
v.push_back(make_pair(++input_order, tok));
}
sort(v.begin(),v.end(), less_by_integer_pair);
for (int i = 0 ; i < v.size() ; ++i)
{
const integer_pair_with_input_order& elem = v[i];
cout << "input order : " << elem.first
<< " { " << elem.second.first
<< ", " << elem.second.second << " }\n";
}
return 0;
}

Related

Cannot sort vector<pair<int, int>>

I tried to sort a vector<pair<int, int>> by using STL sort with my own boolean function.
#include <bits/stdc++.h>
using namespace std;
bool comp(pair<int, int> u1, pair<int, int> u2){
if(u1.first != u2.first) return u1.first < u2.first;
return u2.second > u2.second;
}
int main(void){
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int univs, day, pay, max_income = 0, spent = 0;
vector<pair<int, int>> day_pay;
cin >> univs;
for(int u = 0; u < univs; u++){
cin >> pay >> day;
day_pay.push_back(make_pair(day, pay));
}
for(int i = 0; i < univs; i++) cout << day_pay[i].first << " " << day_pay[i].second << endl;
cout << endl;
sort(day_pay.begin(), day_pay.end(), comp);
for(int i = 0; i < univs; i++) cout << day_pay[i].first << " " << day_pay[i].second << endl;
for(int u = 0; u < univs; u++){
if(day_pay[u].first <= spent) continue;
max_income += day_pay[u].second;
spent++;
}
cout << max_income;
}
this is test case:
4
50 2
10 1
20 2
30 1
I want to sort this case as
30 1
10 1
50 2
20 2
What should I do for solving this problem?
The line
return u2.second > u2.second;
is suspicious. You most likely mean
return u1.second > u2.second;
Look at your comp function. The line after the if:
return u2.second > u2.second;
shuldn't that be:
return u1.second > u2.second
The actual fault was well pointed by Caleth in their answer. But I think that this much code is sufficient for sorting. You may modify it according to your question.
#include <iostream>
#include <utility>
#include <vector>
int main() {
std::size_t n;
std::cin >> n;
std::vector<std::pair<int, int>> v(n);
for (auto &&i : v) std::cin >> i.first >> i.second;
std::sort(v.begin(), v.end(),
[](std::pair<int, int> &a, std::pair<int, int> &b) {
return a.second != b.second ? a.second < b.second
: a.first > b.first;
});
for (auto &&i : v) std::cout << i.first << ' ' << i.second << '\n';
}
If you're using C++ 14 or higher, you can directly use auto in lambda params.
Sample Run:
Sample Input:
4
50 2
10 1
20 2
30 1
Corresponding Output:
30 1
10 1
50 2
20 2

Character Counter in C++?

I'm trying to find a way to display all the characters in a string and the number of times they occur.
This is what I have so far:
//Any unused includes are part of the default code
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cmath>
#include <string>
using namespace std;
int main()
{
string st = "";
cout << "Input a sentence: " << endl;
getline(cin, st);
int index = 0;
int index2 = 0;
int counters[26] = {0};
for(int i = 0; i < st.length(); i++)
{
int counter = 0;
index = st.find(st[i],0);
for(int j = 0; j < st.length(); j++)
{
index2 = st.find(st[j]);
if(index == index2)
{
counter++;
}
}
cout << st[i] << ": " << counter << endl;
}
//cout << st[i] <<": " << counters[st[i] - 'a'] << endl;
return 0;
}
and I return this:
Input a sentence:
hello
h: 1
e: 1
l: 2
l: 2
o: 1
so I kind of have something but I can't figure out how to make the letters not repeat more than once. I know that I need to store them in an array but it's out of my ken.
You were very close, nice try! I liked the approach with the counters array, where every cell would represent the frequency of a letter in the given string.
So, just go and update this array, as this answer implies How to get character's position in alphabet in C language?, without the plus one they mention there, since you want the index of the letter in your array. In other words, for 'a', you need 0, 'b', you need 1 and so on.
Then, in the printing phase, just use the above link's suggestion in the reverse way. When you print the i-th non-zero element of counters, print the i-th element of the element, which will reveal the letter in question.
Putting all together, you get:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cmath>
#include <string>
using namespace std;
int main()
{
string st = "";
cout << "Input a sentence: " << endl;
getline(cin, st);
int index = 0;
int index2 = 0;
int counters[26] = {0};
for(size_t i = 0; i < st.length(); i++)
{
int counter = 0;
index = st.find(st[i],0);
for(size_t j = 0; j < st.length(); j++)
{
index2 = st.find(st[j]);
if(index == index2)
{
counter++;
}
}
counters[st[i] - 'a'] = counter; // update 'counters' array
}
for(int i = 0; i < 26; ++i)
if(counters[i] != 0) // print non-zero counters
cout << (char)(i + 'a') << ": " << counters[i] << endl;
return 0;
}
Output:
e: 1
h: 1
l: 2
o: 1
I would do something like this:
#include <iostream>
#include <map>
#include <string>
int main()
{
std::string st;
std::cout << "Input a sentence: " << std::endl;
std::getline(std::cin, st);
std::map<char, int> m;
for (const char c : st)
++m[c];
for (const std::pair<char, int>& me : m)
std::cout << me.first << ": " << me.second << std::endl;
}
lechuga2000 beat me to the post, but this is my suggestion:
#include <iostream>
#include <map>
#include <string>
int main()
{
std::string input_sentence = "Now is the time for all good men to come to the aid of the party.";
/*
std::cout << "Input a sentence: " << std::endl;
std::getline(std::cin, input_sentence);
*/
std::map<char, int> character_counts;
for (const auto character : input_sentence)
++character_counts[character];
for (const auto counted_character : character_counts)
std::cout << counted_character.first << ": " << counted_character.second << '\n';
return 0;
}
And here is the output:
: 15
.: 1
N: 1
a: 3
c: 1
d: 2
e: 6
f: 2
g: 1
h: 3
i: 3
l: 2
m: 3
n: 1
o: 8
p: 1
r: 2
s: 1
t: 7
w: 1
y: 1

pointers with numbers in backwards [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I need to receive an undetermined number of integer numbers in between (0-9). With this numbers, print them forwards and backwards, and then erase the numbers at the corners.
Example:
3 5 1 9 4 6 2 4 4 2 6 4 9 1 5 3
5 1 9 4 6 2 4 4 2 6 4 9 1 5
1 9 4 6 2 4 4 2 6 4 9 1
9 4 6 2 4 4 2 6 4 9
4 6 2 4 4 2 6 4
6 2 4 4 2 6
2 4 4 2
4 4
And here is the code I have so far:
#include <iostream>
using namespace std;
int a;
int p;
int set;
void numberss()
{
for set[](int a=0; a<p; a++)
}
int main()
{
cin >> p;
cin >> a;
const int SIZE = p;
int set[] = {a};
int *numPtr;
numPtr = set;
for (int index = 0; index < SIZE; index++)
{
cout << *numPtr << " ";
numPtr++;
}
for (int index = 0; index < SIZE; index++)
{
numPtr--;
cout << *numPtr << " ";
}
return 0;
}
If we ignore errors, you can read the numbers in one at a time, and form a string for the first line of output. Forming the string will involve appending a reversed copy to the original. Once the string is formed, you can output that string for the first line. Then replace the first number with a space character, and shrink the string from the back by two characters. Keep doing that until you are done.
This works because the numbers are all single digit.
int main (void)
{
int N;
std::string nums;
std::cin >> N;
for (int i = 0, x; i < N; ++i) {
std::cin >> x;
nums += std::to_string(x) + ' ';
}
nums.append(nums.rbegin() + 1, nums.rend());
for (int i = 0; i < N; ++i) {
std::cout << nums << '\n';
nums[2*i] = ' ';
nums.resize(nums.size()-2);
}
}
DEMO
Your code doesn't work because you are not reading all of the numbers from the user's input, you are only reading the count and the 1st number. Also, you are not looping enough times to output the numbers in a triangular fashion, you are only outputting the 1st line of the triangle.
Try this instead:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int p;
vector<int> set;
cin >> p;
set.resize(p);
for (int i = 0; i < p; ++i)
cin >> set[i];
for (int index = 0; index < p; index++)
{
int *numPtr = &set[index];
for (int i = 0; i < index; ++i)
cout << " ";
for (int i = index; i < p; ++i)
cout << *numPtr++ << " ";
for (int i = index; i < p; i++)
cout << *--numPtr << " ";
cout << endl;
}
return 0;
}
Live Demo
That being said, here is an alternative approach that is more C++-ish and less C-ish, by using iterators instead of pointers, and using STL algorithms. Also, you should always validate user input before using it:
#include <iostream>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <limits>
#include <iterator>
#include <cstdint>
using uint16vec = std::vector<uint16_t>; // there is no operator>> for uint8_t...
int main()
{
size_t count = 0;
std::cin >> count;
uint16vec set;
set.reserve(count);
for (size_t i = 0; i < count; ++i)
{
uint16vec::value_type num;
while (!((std::cin >> num) && (num <= 9)))
{
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
std::cout << "Enter a valid number 0..9!" << std::endl;
}
set.push_back(num);
}
auto begin = set.begin(), end = set.end();
auto rbegin = set.rbegin(), rend = set.rend();
auto out = std::ostream_iterator<uint16vec::value_type>(std::cout, " ");
std::cout << std::setfill(' ');
for (size_t i = 0; i < count; ++i)
{
std::cout << std::setw((i*2)+1);
std::copy(begin++, end, out);
std::copy(rbegin, rend--, out);
std::cout << std::endl;
}
return 0;
}
Live Demo
Give this a shot, mate. I've commented it so you can follow along. It allows for characters other than numbers because that seemingly wasn't a requirement of your assignment, so it's on you to sort and filter those out. It prints as intended, so here's hoping that this is what you're looking for to start off with your search for the right answer.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void pop_front(vector<char>& _vector)
{
_vector.front() = move(_vector.back());
_vector.pop_back();
}
int main()
{
vector<char> characterList;
string consoleInput;
cin >> consoleInput;
//Initialize by pushing everyting from the console into our vector.
for (char c : consoleInput)
{
characterList.push_back(c);
}
//After adding from the console, now we'll do it in reverse.
for (int i = consoleInput.length() - 1; i > -1; i--)
{
characterList.push_back(consoleInput[i]);
}
//Print where we are currently up to for display purposes.
for (char c : characterList)
{
cout << c;
}
// Newline.
cout << "\n";
//Now let's start to chop it down. It'll take the same iterations as the console input, because we're doubling down.
for (int i = 0; i < consoleInput.length() - 1; i++)
{
characterList.erase(characterList.begin());
characterList.pop_back();
for (char c : characterList)
{
cout << c;
}
cout << "\n";
}
return 0;
}

Printing vector in reverse order using range-based for loop

I have this code that convert a decimal number into a binary one:
#include <iostream>
#include <windows.h>
#include <vector>
#include <algorithm>
using namespace std;
void space(){ cout << endl << endl << endl; }
int main(int argc, char const *argv[]){
system("color 1F");
unsigned long int n, copy_n;
vector<int> v;
cout << "# Decimal: "; cin >> n; cout << endl; copy_n = n;
while (n != 0){
if (n % 2 == 0){ v.push_back(0); }else{ v.push_back(1); }
n = int(n / 2);}
cout << endl << "# Binary: ";
reverse(v.begin(), v.end());
for (size_t i = 0; i < v.size(); i++){cout << v.at(i);}
space(); system("Pause"); return 0;
}
... and this ...
#include <iostream>
#include <windows.h>
using namespace std;
void space(){ cout << endl << endl << endl; }
int main(int argc, char const *argv[]){
system("color 1F");
unsigned long int n, copy_n, nr = 0 ;
cout << "# Decimal: "; cin >> n; copy_n = n; cout << endl;
while (copy_n != 0){ nr++; copy_n = int(copy_n / 2); }
int* v = new int[nr];
for (int i = 0; i < nr; i++){if (n % 2 == 0){ v[i] = 0; }else{ v[i] = 1; }n = int(n / 2);}
cout << endl << "# Binary: ";
for (int i = nr-1; i >= 0;i--){cout << v[i] << "";}
space(); system("Pause"); return 0;}
... and this ...
#include <iostream>
#include <windows.h>
#include <bitset>
using namespace std;
void space(){ cout << endl << endl << endl; }
int main(int argc, char const *argv[]){
system("color 1F");
unsigned int n;
cout << "# Decimal: "; cin >> n; cout << endl;
bitset<16>binary(n);
cout << endl << "# Binary: " << binary << endl;
space(); system("Pause"); return 0;
}
But my question is:
How can I use reverse() function from algorithm and print the vector with range-based for loop
Ex: Decimal = 2
with
reverse(v.begin(), v.end());
for (size_t i = 0; i < v.size(); i++){cout << v.at(i);}
program prints 10
with
reverse(v.begin(), v.end());
for(auto i : v){cout<<v.at(i);}
program pritns 01
Why? And how can I fix this?
This for statement
reverse(v.begin(), v.end());
for(auto i : v){cout<<v.at(i);}
is simply wrong.
The valid code will look like
reverse(v.begin(), v.end());
for(auto i : v){ cout << i;}
Also if you are paid for the number of symbols entered in the source code then this statement
if (n % 2 == 0){ v.push_back(0); }else{ v.push_back(1); }
looks very good because it contains many symbols. Otherwise it would be better to write
v.push_back( n % 2 );
Also in one of your programs you allocate dynamically an array
int* v = new int[nr];
but not free it. In this case it would be better to use smart pointer std::unique_ptr.
You could also try to write a recursive function. For example
#include <iostream>
#include <vector>
std::vector<unsigned int> & dec_to_bin( std::vector<unsigned int> &v,
unsigned int x )
{
const unsigned int Base = 2;
static size_t n;
unsigned int digit = x % Base;
++n;
if ( x /= Base )
{
dec_to_bin( v, x );
}
else
{
v.reserve( n );
n = 0;
}
v.push_back( digit );
return v;
}
int main()
{
while ( true )
{
std::cout << "Enter a non-negative number (0-exit): ";
unsigned int x = 0;
std::cin >> x;
if ( !x ) break;
std::vector<unsigned int> v;
dec_to_bin( v, x );
for ( auto digit : v ) std::cout << digit;
std::cout << std::endl;
}
return 0;
}
If to enter sequentially
15
7
3
1
0
then the program output will be
Enter a non-negative number (0-exit): 15
1111
Enter a non-negative number (0-exit): 7
111
Enter a non-negative number (0-exit): 3
11
Enter a non-negative number (0-exit): 1
1
Enter a non-negative number (0-exit): 0

c++ code producing different outputs through Visual Studio c++ and Gcc

I have the following C++ Program:
//============================================================================
// Name :
// Author : Bryce Sandlund
// Version :
// Copyright :
// Description : Code skeleton
//============================================================================
#include <iostream>
#include <iomanip>
#include <set>
#include <vector>
#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdlib>
#include <sstream>
#include <list>
#include <map>
#include <fstream>
#include <string>
#include <time.h>
#include <queue>
#include <tuple>
#include <functional>
#include <unordered_set>
#include <unordered_map>
#define INF 1000000000
#define all(c) (c).begin(),(c).end()
#define tr(c,i) for(typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define EP .00001
using namespace std;
typedef pair<int, int> ii;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<vi> vvi;
typedef vector<vb> vvb;
typedef vector<ii> vii;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef long long LL;
vvi adjList;
unordered_map<string, int> targs;
int add(string &s)
{
if (targs.count(s))
return targs[s];
targs[s] = targs.size();
adjList.push_back(vi());
return targs.size()-1;
}
void connect(int si, int ti)
{
if (si == ti)
return;
for (int i = 0; i < adjList[si].size(); ++i)
{
if (adjList[si][i] == ti)
return;
}
adjList[si].push_back(ti);
}
vi bfs(int s)
{
queue<ii> q;
q.push(ii(s, -1));
vi dist(adjList.size(), INF);
while (!q.empty())
{
int top = q.front().first;
int hops = q.front().second;
q.pop();
if (dist[top] != INF)
continue;
dist[top] = hops;
for (int i = 0; i < adjList[top].size(); ++i)
{
q.push(ii(adjList[top][i], hops+1));
}
}
return dist;
}
int main() {
int caseNum = 1;
cout << "Case " << caseNum << ":" << endl;
string line;
while (getline(cin, line))
{
stringstream ss(line);
string command;
ss >> command;
if (command == "add")
{
string s, t;
ss >> s;
int si = add(s);
if (ss >> t)
{
int ti = add(t);
connect(si, ti);
connect(ti, si);
}
}
else if (command == "connections")
{
string s;
ss >> s;
if (!targs.count(s))
{
cout << "target does not exist" << endl;
continue;
}
int st = targs[s];
if (adjList[st].empty())
{
cout << "no connections" << endl;
}
else
{
vi dist = bfs(st);
vi away(adjList.size(), 0);
int maxd = -1;
for (int i = 0; i < dist.size(); ++i)
{
if (dist[i] == INF || dist[i] == -1)
continue;
++away[dist[i]];
maxd = max(maxd, dist[i]);
}
for (int i = 0; i <= maxd; ++i)
{
cout << i << ": " << away[i] << endl;
}
}
}
else if (command == "associated")
{
string s, t;
ss >> s >> t;
if (!targs.count(s) || !targs.count(t))
{
cout << "target does not exist" << endl;
continue;
}
int si = targs[s], ti = targs[t];
vi dist = bfs(si);
if (dist[ti] == INF)
{
cout << "no" << endl;
}
else
{
cout << "yes " << dist[ti] << endl;
}
}
else
{
adjList.clear();
targs.clear();
cout << "----------" << endl;
cout << "Case " << ++caseNum << ":" << endl;
}
}
cout << "----------" << endl;
return 0;
}
I am using this as input:
add a b
add a c
add b d
add e b
add c f
add c g
add f h
add h i
add j k
associated a i
associated i a
associated f k
associated a h
connections a
connections i
add k g
associated a j
connections a
add h a
connections a
associated a h
add m
add n n
connections n
add a n
connections n
In Visual C++, the code produces this output (it does so on Debug or Release):
Case 1:
yes: 3
yes: 3
no
yes: 2
0: 2
1: 4
2: 1
3: 1
0: 1
1: 1
2: 1
3: 2
4: 1
5: 2
yes: 3
0: 2
1: 4
2: 2
3: 2
0: 3
1: 5
2: 1
3: 1
yes: 0
no connections
0: 1
1: 3
2: 5
3: 1
4: 1
----------
On gcc g++, it produces this output:
Case 1:
no
no
yes 0
no
0: 2
1: 2
2: 2
3: 1
0: 1
no
0: 2
1: 2
2: 2
3: 1
0: 3
1: 2
2: 2
3: 1
yes 0
----------
For reference, I am trying to solve this problem: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=620&page=show_problem&problem=4574.
Any ideas why the input and output would be different on the different compilers? I don't believe I am using any undefined behavior.
The cause of the differences in the behavior of the code in the two platforms is the add function. You have:
int add(string &s)
{
if (targs.count(s))
return targs[s];
targs[s] = targs.size();
adjList.push_back(vi());
return targs.size()-1;
}
In that function, the problematic line is:
targs[s] = targs.size();
The line is tricky because depending on which side of the assignment operator gets evaluated first, you get different behavior. Please note that targs[s] involves a function call that changes the object.
You can change the function a little bit to make it consistent and predictable across platforms.
int add(string &s)
{
if (targs.count(s))
return targs[s];
int size = targs.size();
targs[s] = size;
adjList.push_back(vi());
return size;
}