Create the largest possible number from input - implementation issue with cout - c++

I am trying to implement an algorithm that will take a set of numbers and output the largest possible number (without breaking up the individual numbers). So in an example like this where I give 4 numbers:
4
43 12 3 91
The output would be
91-43-3-12 or 9143312.
My attempt is below.
#include <algorithm>
#include <sstream>
#include <iostream>
#include <vector>
#include <string>
using std::vector;
using std::string;
bool compare (int x, int y) {
std::cout << "in func \n";
string a = std::to_string(x);
string b = std::to_string(y);
std::cout << a << " " << b << "\n";
std::cout << std::stoi(a.substr(0, 1)) << " " << std::stoi(b.substr(0, 1)) << "\n" ;
if (std::stoi(a.substr(0, 1)) < std::stoi(b.substr(0, 1))) {
std::cout.flush();
std::cout << "if \n";
return true;
}
else {
std::cout.flush();
std::cout <<"else \n";
return false;
}
}
string largest_number(vector<string> a) {
std::stringstream ret;
while (a.size() > 0) {
int maxNumber =-1;
int index = -1;
std::cout << "going into for " << a.size() << "\n";
for (size_t i = 0; i < a.size(); i++) {
if (! compare (stoi(a[i]), maxNumber ) ) { //stoi(a[i]) >= maxNumber) {
maxNumber = stoi(a[i]);
std::cout << maxNumber << " " << i << "\n";
index = i;
}
std::cout << "here \n";
}
ret << maxNumber;
a.erase(a.begin() + index);
}
string result;
ret >> result;
return result;
}
int main() {
int n;
std::cin >> n;
vector<string> a(n);
for (size_t i = 0; i < a.size(); i++) {
std::cin >> a[i];
}
std::cout << largest_number(a);
}
I do not understand what is wrong with my compare function. When I run it, say with this input:
$ g++ -pipe -O2 -std=c++14 largest_number.cpp -lm -o largest1
$ ./largest1.exe
4
4 23 1 45
going into for 4
in func
4 -1
It doesnt print the cout statements in the conditional if or else. How could this be possible? I even tried flushing. However, if I take the entire conditional out, put a cout statement and the return true or something, then it runs the program in entirety (although this is not the expected output).
I do not mind harsh criticism. What am I doing wrong here? Any advice will be appreciated.
Thanks in advance.

In this statement
std::cout << std::stoi(a.substr(0, 1)) << " " << std::stoi(b.substr(0, 1)) << "\n" ;
when b is equal to -1 the expression b.substr(0, 1) is equal to an object of type std::string that contains one character '-' that is the minus sign.
If to apply the standard function std::stoi to such a string then an exception will be thrown.
Consider the following code snippet
std::string s("-");
try
{
std::stoi(s);
}
catch (const std::exception &e)
{
std::cout << e.what() << std::endl;
}
Its output will be
invalid stoi argument
It seems what you need is just to sort the strings. For example
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
std::vector<std::string> v { "4", "23", "1", "45" };
auto cmp = [](const std::string &a, const std::string &b)
{
std::string::size_type i = 0, m = a.size();
std::string::size_type j = 0, n = b.size();
int result;
do
{
if (m < n)
{
result = a.compare(i, m, b, j, m);
j += m;
n -= m;
}
else
{
result = a.compare(i, n, b, j, n);
i += n;
m -= n;
}
} while (result == 0 && m && n);
return 0 < result;
};
std::sort(v.begin(), v.end(), cmp);
for (const auto &s : v) std::cout << s;
std::cout << std::endl;
return 0;
}
The output of the program will be
454231
Or for this set of numbers
std::vector<std::string> v{ "43", "12", "3", "91" };
the output will be
9143312
or for one more set of numbers
std::vector<std::string> v{ "93", "938" };
the output will be
93938

Related

Why is this ranged based for loop causing issues with subtraction?

I'm having an issue with a ranged based for loop causing my values to go negative, and I've resolved the issue with a regular for loop but want to understand why it messed up in the first place. You can see from the sample output below that the initial values exist correctly, but then when attempting to subtract from them, they get reset to a default initialized value of 0 I guess?
Broken code:
#include <iostream>
#include <vector>
#define IS_TRUE(x) { if (!(x)) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; }
int maximumScore(std::vector<int>& nums, std::vector<int>& multipliers) {
std::vector<int> multRank;
multRank.resize(multipliers.size());
std::cout << "multRank: ";
//ISSUE IS IN THE LOOP BELOW
for (int n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}
std::cout << std::endl;
for (auto i = 0; i < multipliers.size(); ++i) {
for (auto j = 0; j < multipliers.size(); ++j) {
int abs1 = std::abs(multipliers[i]);
int abs2 = std::abs(multipliers[j]);
if (abs1 > abs2) {
multRank[i] = multRank[i] - 1;
std::cout << multRank[i];
}
}
}
std::cout << std::endl << "multRank after: ";
for (int n : multRank) {
std::cout << " " << n;
}
std::cout << std::endl << std::endl;
return 0;
}
void test1()
{
std::vector<int> nums = { 1, 2, 3 };
std::vector<int> multipliers = { 3, 2, 1 };
int test = maximumScore(nums, multipliers);
IS_TRUE(test == 14);
}
int main()
{
std::cout << "Maximum Score from Performing Multiplication Operations\n";
test1();
}
Broken code output:
Maximum Score from Performing Multiplication Operations
multRank: 3 3 3
-1-2-1
multRank after: -2 -1 0
Repaired code:
#include <iostream>
#include <vector>
#define IS_TRUE(x) { if (!(x)) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; }
int maximumScore(std::vector<int>& nums, std::vector<int>& multipliers) {
std::vector<int> multRank;
multRank.resize(multipliers.size());
std::cout << "multRank: ";
//ISSUE WAS IN THE LOOP BELOW
for (auto i = 0; i < multipliers.size(); ++i) {
multRank[i] = multipliers.size();
std::cout << " " << multRank[i];
}
std::cout << std::endl;
for (auto i = 0; i < multipliers.size(); ++i) {
for (auto j = 0; j < multipliers.size(); ++j) {
int abs1 = std::abs(multipliers[i]);
int abs2 = std::abs(multipliers[j]);
if (abs1 > abs2) {
multRank[i]--;
std::cout << multRank[i];
}
}
}
std::cout << std::endl << "multRank after: ";
for (int n : multRank) {
std::cout << " " << n;
}
std::cout << std::endl << std::endl;
return 0;
}
void test1()
{
std::vector<int> nums = { 1, 2, 3 };
std::vector<int> multipliers = { 3, 2, 1 };
int test = maximumScore(nums, multipliers);
IS_TRUE(test == 14);
}
int main()
{
std::cout << "Calculate Rank\n";
test1();
}
Repaired code output:
Maximum Score from Performing Multiplication Operations
multRank: 3 3 3
212
multRank after: 1 2 3
The first range based for loop is not using references:
for (int n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}
In this loop, n is a copy of the data in multRank. If you want to be able to modify the data in multRank, you want n to be a reference:
for (int& n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}

Infinite loop using string.substr(post,len)

Could you figure out why it keeps looping infinitely in the console? The programmer's supposed to list out each character of a user-inserted string and next to each unique character, in brackets, it's supposed to display the number of times that character occurs in the string... no idea why.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main () {
string input;
cout << "input string: " , cin >> input;
sort (input.begin() , input.end());
while (!input.empty()) {
int j{1}, i{0};
while (input.at(i) == input.at(i+1)) {
j++;
i++;
}
cout << input.at(i) << " (" << j << "), ";
input.substr(i);
}
return 0;
}
This statement
input.substr(i);
does not change the object input itself.
So, either you will have an infinite loop if for some index i input.at(i) is not equal to input.at(i+1), or you can have an exception out of range because i + 1 can be equal to input.size().
From the description of the member function at
Throws: out_of_range if pos >= size().
The program can be implemented in different ways. For example the following way
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::cout << "input string: ";
std::string input;
std::cin >> input;
std::sort( input.begin() , input.end() );
for ( size_t i = 0; i < input.size(); )
{
size_t j = input.find_first_not_of( input[i], i );
if ( j == std::string::npos ) j = i + 1;
if ( i != 0 ) std::cout << ", ";
std::cout << input[i] << " (" << j - i << ")";
i = j;
}
std::cout << '\n';
return 0;
}
The program output is
input string: Hello
H (1), e (1), l (2), o (1)
Or you can use the standard container std::map or std::unordered_map as for example
#include <iostream>
#include <string>
#include <map>
int main()
{
std::cout << "input string: ";
std::string input;
std::cin >> input;
std::map<char, size_t> m;
for ( const auto &c : input )
{
++m[c];
}
bool first = true;
for ( const auto &p : m )
{
if ( !first ) std::cout << ", ";
std::cout << p.first << " (" << p.second << ")";
first = false;
}
std::cout << '\n';
return 0;
}
If you want that characters of the inputted string were output in the order in which they are present in the string then the program can look like
#include <iostream>
#include <string>
#include <map>
int main()
{
std::cout << "input string: ";
std::string input;
std::cin >> input;
auto less = [&input]( const auto &c1, const auto &c2 )
{
return input.find( c1 ) < input.find( c2 );
};
std::map<char, size_t, decltype( less )> m( less );
for ( const auto &c : input )
{
++m[c];
}
bool first = true;
for ( const auto &p : m )
{
if ( !first ) std::cout << ", ";
std::cout << p.first << " (" << p.second << ")";
first = false;
}
std::cout << '\n';
return 0;
}
Or without changing the original string and without using an additional container the program can look the following way.
#include <iostream>
#include <string>
int main()
{
std::cout << "input string: ";
std::string input;
std::cin >> input;
for ( size_t i = 0; i < input.size(); i++ )
{
size_t j = 0;
while ( j != i && input[j] != input[i] ) j++;
if ( j == i )
{
size_t count = 1;
while ( ++j < input.size() )
{
if ( input[j] == input[i] ) ++count;
}
if ( i != 0 ) std::cout << ", ";
std::cout << input[i] << " (" << count << ")";
}
}
std::cout << '\n';
return 0;
}
The program output might look like
input string: elephant
e (2), l (1), p (1), h (1), a (1), n (1), t (1)

c++ How can I count the unique elements in a vector?

I have this c++ code:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>
#include <cmath>
using namespace std;
struct szemelyadat {
string vnev;
string knev;
int szulev;
int szulhonap;
int szulnap;
};
int vfmeret(const char* fajlnev)
{
string temp;
int merettemp = 0;
ifstream meretBE(fajlnev);
while (!meretBE.eof()) {
meretBE >> temp;
merettemp++;
}
meretBE.close();
return merettemp;
}
void vfbeolv(szemelyadat* vek, int elemszam, const char* fajlnev)
{
int i, j;
string stemp, stempresz;
ifstream adatBE(fajlnev);
for (i = 0; i < elemszam; i++) {
adatBE >> stemp;
istringstream sorfolyam(stemp);
j = 0;
while (getline(sorfolyam, stempresz, ';')) {
if (j == 0)
vek[i].vnev = stempresz;
if (j == 1)
vek[i].knev = stempresz;
if (j == 2)
vek[i].szulev = atoi(stempresz.c_str());
if (j == 3)
vek[i].szulhonap = atoi(stempresz.c_str());
if (j == 4)
vek[i].szulnap = atoi(stempresz.c_str());
j++;
}
}
adatBE.close();
}
void vfkiir(szemelyadat* vek, int elemszam)
{
cout << "Vezeteknev "
<< "Keresztnev "
<< "Szuletesiev "
<< "Szuletesihonap "
<< "Szuletesinap " << endl;
for (int i = 0; i < elemszam; i++)
cout << vek[i].vnev << " " << vek[i].knev << " " << vek[i].szulev << ". " << vek[i].szulhonap << ". " << vek[i].szulnap << endl;
}
int main()
{
int n = vfmeret("szuletesi_nevlista.txt");
szemelyadat* vektor;
vektor = new szemelyadat[n];
vfbeolv(vektor, n, "szuletesi_nevlista.txt");
vfkiir(vektor, n);
delete[] vektor;
cin.get();
cin.get();
return 0;
}
I need to cout the count of the unique elements which is in the "vek[i].szulev"
please help me somebody, how can I do this ?
Here's one simple way to count the unique values in a vector:
using Size = ptrdiff_t;
template< class Item >
auto n_unique_items( vector<Item> const& v )
-> Size
{ return set<Item>{ v.begin(), v.end() }.size(); }
Since you insisted on using "your code", you can still utilize std::set to do the counting.
It all boils down to this:
#include <set>
#include <iostream>
void count_items(szemelyadat* vek, int elemszam)
{
std::set<int> counter;
for (int i = 0; i < elemszam; i++)
counter.insert(vek[i].szulev);
std::cout << "The number of unique items is " << counter.size();
}
If you call the count_items once you fill your "vektor", then this will give you then unique number of szulev in the vektor.

how can I find the sequence number (index) of word in such a paragraph c++?

I'm working on a project which needs to find the number of words and the indices of each word in the paragraph ...I have written the code which is counting the number of word in a string but I stuck with finding the indices of words,
such as : Hi John How are you I miss you ..
I need to print the indices like : 0 1 2 3 4 5 6 7
here is the code:
int _tmain(int argc, _TCHAR* argv[])
{
int count_words(std::string);
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
int number_of_words=1;
int counter []={0};
for(int i = 0; i < input_text.length();i++)
if(input_text[i] == ' ')
number_of_words++;
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl;
system ("PAUSE");
}
Hopefully this helps. Edited to include use of count_words function.
#include <iostream>
#include <sstream>
void count_words(std::string);
int main(){
std::string input_text, output_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
count_words(input_text);
system ("PAUSE");
return 0; //MUST RETURN AN INTEGER VALUE FROM 'INT MAIN'
}
void count_words(std::string inputString){
std::string output_text;
std::stringstream indexes;
int number_of_words=0; //If there are no words, it would be false, make it 0.
//int counter []={0}; //This serves no purpose.
if(!inputString.empty()){// test to make sure it isn't empty.
number_of_words++;
for(int i = 0; i < inputString.length();i++){ // For loops should have curly braces {} containing their statement.
if(inputString[i] == ' '){
number_of_words++;
}
if((isalpha(inputString[i]))&&inputString[i-1]==' '){ //test for following space separated word
indexes << i << " ";
}
}
}
output_text = indexes.str(); //convert stringstream to string
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl; //duplicate info
std::cout << "Indexes: " << output_text << std::endl;
}
I'm not sure if i understand the question. You only need print the "indices"?? like this? (Using your own code)
#include <iostream>
#include <vector>
#include <string>
void stringTokenizer(const std::string& str, const std::string& delimiter, std::vector<std::string>& tokens) {
size_t prev = 0, next = 0, len;
while ((next = str.find(delimiter, prev)) != std::string::npos) {
len = next - prev;
if (len > 0) {
tokens.push_back(str.substr(prev, len));
}
prev = next + delimiter.size();
}
if (prev < str.size()) {
tokens.push_back(str.substr(prev));
}
}
int main()
{
std::vector <std::string> split;
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
stringTokenizer(input_text, " ", split);
int number_of_words = 0;
for (std::vector<std::string>::iterator it = split.begin(); it != split.end(); it++, number_of_words++) {
std::cout << *it << " " << number_of_words << std::endl;
}
}

For loop prints an extra comma

cout<<"Set B : {";
for(i=0;i<b;i++)
{
cout<<setB[i];
cout<<",";
}
cout<<" }"<<endl;
The code above is not printing correctly. It should print Set B : {1,2,3} but it prints an extra comma ==> Set B : {1,2,3,}
Use
cout << "Set B : {";
for (i = 0; i < b; ++i) {
if (i > 0) cout << ",";
cout << setB[i];
}
cout << " }" << endl;
I changed your algorithm :
Before it meant : "Put the number and then put a comma"
Now it means : "If there is a number behind me put a comma, then put the number"
Before, you always printed a comma when you printed a number so you had an extra comma.
For each iteration of the for loop, the program is going to execute -everything- inside the for loop. So, your loop runs through and prints each number in your set and then a comma.
The problem is that even on your last run through the loop, it is going to print a comma, because it's part of the loop.
cout << "Set B : {";
for(i = 0; i < b; i++){
cout << setB[i];
if (i < (b-1))
cout << ",";
}
cout << " }" << endl;
This code will run the exact same, except the second to last time it runs through the loop, it will not print a comma. No need to get too fancy. :)
Personally I like this solution better. You first print out the first element and then a , [second element].
cout <<"Set B : {" << setB[0];
for(i = 1; i < b; i++)
{
cout << ",";
cout<<setB[i];
}
cout << " }" << endl;
Warning!: This will NOT work if the array is empty.
The loop code prints a pair of number and comma. Try using this one:
cout<<"Set B : {";
for(i=0;i<b;i++)
{
cout<<setB[i];
if(i < b-1) cout<<",";
}
cout<<"}"<<endl;
You're loop is executing the cout << "," 3 times. The following will give what you want:
#include <iostream>
using namespace std;
int main(){
int setB[] = {1,2,3};
cout<<"Set B : {";
for(int i=0;i<3;i++)
{
cout<<setB[i];
if ( i < 2 )
cout<<",";
}
cout<<" }"<<endl;
return 0;
}
The way I often deal with these loops where you want to put something like a space or a comma between a list of items is like this:
int main()
{
// initially the separator is empty
auto sep = "";
for(int i = 0; i < 5; ++i)
{
std::cout << sep << i;
sep = ", "; // make the separator a comma after first item
}
}
Output:
0, 1, 2, 3, 4
If you want to make it more speed efficient you can output the first item using an if() before entering the loop to output the rest of the items like this:
int main()
{
int n;
std::cin >> n;
int i = 0;
if(i < n) // check for no output
std::cout << i;
for(++i; i < n; ++i) // rest of the output (if any)
std::cout << ", " << i; // separate these
}
An other way, without extra branch:
std::cout << "Set B : {";
const char* sep = "";
for (const auto& e : setB) {
std::cout << sep << setB[i];
sep = ", ";
}
std::cout <<" }" << std::endl;
I really like to promote the use of a range library to write declarative code instead of nested for-if statements in an imperative style.
#include <range/v3/all.hpp>
#include <vector>
#include <iostream>
#include <string>
int main()
{
using namespace ranges;
std::vector<int> const vv = { 1,2,3 };
auto joined = vv | view::transform([](int x) {return std::to_string(x);})
| view::join(',');
std::cout << to_<std::string>(joined) << std::endl;
return 0;
}
If you can use STL, try the following:
#include <iterator>
#include <iostream>
int main() {
int setB[]{1,2,3};
std::cout << "Set B : { ";
for(auto i = std::begin(setB), e = std::end(setB); i != e;) {
std::cout << *i;
for(++i; i !=e; ++i) { std::cout << ", " << *i; }
}
std::cout << " }" << std::endl;
return 0;
}