#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<double> numbers(input_number);
cout << "Enter numbers from 0 to 50: " << endl;
for (int i = 0; i < input_number; ++i) {
cin >> numbers[i];
}
unordered_map<int, int> freq;
for (int i = 0; i < numbers.size(); i++) {
freq[numbers[i]]++;
}
for (int i = 0; i < numbers.size(); i++) {
cout << freq[numbers[i]];
}
return 0;
}
When the use inputs numbers, for example 1,1,1,2 the output should be "1" because it is the most frequent number but the output here became "3,3,3,1" How to solve this problem?
You are most of the way there. Your frequencies are all stored, and you just need to search through the unordered_map now to find the item that has the largest value. Since you're already using <algorithm> you can leverage std::max_element to help:
#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <vector>
int main()
{
std::vector<int> numbers = { 1, 2, 3, 2, 3, 2, 2 };
std::unordered_map<int, int> freq;
for (int n : numbers) ++freq[n];
if (!freq.empty())
{
auto it = std::max_element(freq.begin(), freq.end(),
[](const auto& a, const auto& b) { return a.second < b.second; });
std::cout << "Most frequent is " << it->first << "\n";
}
}
Output:
Most frequent is 2
Here, a custom comparison function is supplied that tests only the frequency part of the element (otherwise the default behavior will compare the full key/value pairs which will result in finding the largest number).
Note that because the map is unordered, there won't be a predictable outcome for tie-breakers (where more than one number is the most frequent). If you need to handle that in a more predictable way, you'll need to adjust the comparison function or possibly just loop over the container yourself if it requires additional work.
One option for tie-breaking is to choose the lowest number. That could be achieved by modifying the comparison to:
return std::make_pair(a.second, b.first) < std::make_pair(b.second, a.first);
The problem is that you just output all the values in map. In a naive implementation you have to iterate through map and register the maximum value and it's frequency:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
int main()
{
using std::cin, std::cout, std::endl;
using std::vector, std::unordered_map;
int input_number = 0, max_freq = 0, max_val = 0;
cout << "How many numbers you want to input: " << endl;
cin >> input_number;
// Making input double may creates questions
vector<int> numbers(input_number);
cout << "Enter numbers from 0 to 50: " << endl;
for (int i = 0; i < input_number; ++i) {
cin >> numbers[i];
}
unordered_map<int, int> freq;
for (int i = 0; i < numbers.size(); i++) {
freq[numbers[i]]++;
}
// iterating over the map and finding max value
for (auto val : freq) {
if( val.second > max_freq) {
max_val = val.first;
max_freq = val.second;
}
}
cout << max_val;
return 0;
}
Standard maps do store values as pairs of key and value (std::pair). This can be done in easier way: you can do that right while inputting the numbers.
for (int i = 0; i < numbers.size(); i++) {
int val = numbers[i];
int curfreq = ++freq[val];
if (curfreq > max_freq) {
max_val = val;
max_freq = curfreq;
}
}
cout << max_val;
Your array freq has to proper values in it. But your logic in the print out is wrong. You are printing the numbers twice. I guess you want to print all the numbers from 0 to 50.
cout << freq[i]
Then you see which entries have values or not. Then add some logic (which doesn't exist in your code) to pick the proper value. Like the biggest count..
Related
Below I have attached code for a project that is intended to find the lowest value in a user-inputed vector, return -1 if the vector is empty, and 0 if the vector only has one index. I have run into an issue with the condition in which a vector is empty as the unit test continues to fail the returns_negative_one_for_empty_vector test.
main.cc
#include <iostream>
#include <vector>
#include "minimum.h"
int main() {
int size;
std::cout << "How many elements? ";
std::cin >> size;
std::vector<double> numbers(size);
for (int i = 0; i < size; i++) {
double value;
std::cout << "Element " << i << ": ";
std::cin >> value;
numbers.at(i) = value;
}
double index;
index = IndexOfMinimumElement(numbers);
std::cout << "The minimum value in your vector is at index" << index << std::endl;
}
minimum.cc
#include "minimum.h"
#include <vector>
int IndexOfMinimumElement(std::vector<double> input) {
int i, min_index;
double min_ = input.at(0);
for (int i = 0; i < input.size(); i++) {
if (input.at(i) < min_) {
min_index = i;
return min_index;
}
else if (input.size() == 0) {
return -1;
}
else if(input.size() == 1) {
return 0;
}
}
};
minimum.h
#include <vector>
int IndexOfMinimumElement(std::vector<double> input);
find the lowest value in a user-inputed vector, return -1 if the
vector is empty, and 0 if the vector only has one index.
Instead of writing raw for loops, this can be accomplished much more easily by using the STL algorithm functions.
There are other issues, one being that the vector should be passed by const reference, not by value. Passing the vector by-value incurs an unnecessary copy.
#include <algorithm>
#include <vector>
#include <iostream>
int IndexOfMinimumElement(const std::vector<double>& input)
{
if (input.empty())
return -1;
auto ptrMinElement = std::min_element(input.begin(), input.end());
return std::distance(input.begin(), ptrMinElement);
}
int main()
{
std::cout << IndexOfMinimumElement({ 1.2, 3.4, 0.8, 7.8 }) << std::endl;
std::cout << IndexOfMinimumElement({}) << std::endl; // empty
std::cout << IndexOfMinimumElement({3}) << std::endl; // only 1 element
return 0;
}
Output:
2
-1
0
The relevant functions are std::min_element and std::distance. The std::min_element returns an iterator (similar to a pointer) to the minimum element in the range.
The code is written with a clear understanding of what each function does -- it is practically self-documenting. To get the minimum element, you call std::min_element. To get the distance from the first to the found minimum element, you call std::distance with an iterator to the starting position and an iterator to the ending position.
The bottom line is this: the STL algorithm functions rarely, if ever, fail when given the proper input parameters. Writing raw for loops will always have a much greater chance of failure, as you have witnessed. Thus the goal is to minimize having to write such for loops.
In IndexOfMinimumElement you return on the very first iteration, as all branches of your if/else lead to a return.
If your vector contained {14, 2, 10, 1} the index it would return would be 1, because 2 is less than 14.
Instead, you want to have a couple of conditional checks at the top of your function that return based on the length of the vector.
If the function call gets past those, it should iterate over the values in the vector, checking if they are less than the running minimum value, and update the minimum index accordingly.
int IndexOfMinimumElement(std::vector<double> input) {
if (input.size() == 0) return -1;
if (input.size() == 1) return 0;
int i = 0;
double min = input[0];
int min_idx = 0;
for (auto &v : input) {
if (v < min) {
min = v;
min_idx = i;
}
++i;
}
return min_idx;
}
A minimal test:
int main() {
std::vector<double> foo { 1.2, 3.4, 0.8, 7.8 };
std::cout << IndexOfMinimumElement(foo) << std::endl;
return 0;
}
Prints, as expected:
2
#include <iostream>
#include <string>
using namespace std;
int main () {
int cnt[26] {};
char alpha[26];
string s = "abcdefffggghiii";
for (int i = 0; i < s.length(); i++) {
cnt[s[i] - 'a']++;
}
for (int i = 'a'; i <= 'z'; i++) {
alpha[i - 'a'] = i;
}
for (int i = 0; i < 26; i++) {
if (cnt[i]) {
cout << alpha[i] << " " << cnt[i] << endl;
}
}
return 0;
}
I wanted to print the frequencies of each letter in the string in descending order. I've thought to sort the cnt array and print from 25 to 0 but it will only print the frequencies with wrong letter. How can I fix it to print for example i 3 and so on in descending order?
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
// Create result container
auto x = vector<pair<char, int>>();
std::string s = "abcdefffggghiii";
for (auto& l : s) {
// Find the item that corresponds to letter
auto pLetter =
find_if(x.begin(), x.end(), [&l](pair<char, int> &arg) {
return arg.first == l;
});
if (pLetter != x.end())
pLetter->second++; // If item corresponding to letter is found, increment count
else {
x.push_back(make_pair(l, 1)); // Otherwise, create a new result entry
}
}
// Sort results by count in descending order
std::sort(x.begin(), x.end(),
[](auto &left, auto &right) { return left.second > right.second; });
for (auto i = x.begin(); i != x.end(); ++i)
std::cout << i->first << ':' << i->second << '\n';
}
Produces
f:3
g:3
i:3
a:1
b:1
c:1
d:1
e:1
h:1
You can run it here. This uses C++14 lambdas for the find_if and sort predicates. This solution is very similar to #Retired Ninja's, except that the result vector contains items only for those letters that have non-zero counts. This means that it is extendable to wstrings without the need for a large result vector.
Here's how I might do it. You just need to keep the letter and the count together.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
struct LetterFreq
{
char letter;
int freq;
};
int main()
{
std::vector<LetterFreq> cnt(26);
for (size_t i = 0; i < cnt.size(); ++i)
{
cnt[i].freq = 0;
cnt[i].letter = static_cast<char>(i) + 'a';
}
std::string s = "abcdefffggghiii";
for (auto& l : s)
{
cnt[l - 'a'].freq++;
}
std::sort(cnt.begin(), cnt.end(), [](const LetterFreq& lhs, const LetterFreq& rhs)
{
return lhs.freq > rhs.freq;
});
for (auto& item : cnt)
{
if (item.freq == 0)
{
break;
}
std::cout << item.letter << " : " << item.freq << "\n";
}
return 0;
}
This is simple if all you have it lowercase ASCII letters. For more complicated input you can use the same idea of the letter and count in a struct, but you'd either want to increase the size of the vector to 256 to keep track of all possibilities, or use something like an unordered map to only store used symbols and then copy them out into a container you can sort to display them. You could also use parallel arrays and while sorting swap the letter positions at the same time you're swapping the counts. There are many ways to handle this.
You could use pairs, but it looks like you're doing this with more basic types. In that case you might have to use nested loops. Keep finding the highest frequency character, print it, and then set its frequency to -1 to indicate that you've processed it already.
I'm trying to pass random integers (between 0 and 11) to the Numbers[] array, but i have to make sure that all 10 of its elements are different. I've tried to pass the numbers first in the array, and then check if there are any numbers that are equal but its not working this way. Here's my code:
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
int main()
{
int Numbers[10];
srand( time(NULL) );
for (int i = 0; i < 10; i++ )
{
Numbers[i] = rand() % 12; // First, the integers are passed
to the array (They must be between 0 and 11)
cout << Numbers[i] << endl; // and printed to the screen
}
cout << endl << endl;
for (int u = 0; u < 10; u++)
{
if(Numbers[u] == Numbers[u - 1]) // If there are two equal
numbers
{
switch (Numbers[u]) // One of them is incremented (But that
causes problems as well because it can lead to another pair of equals)
{
case 11: // In case one of them is 11
Numbers[u]--;
break;
default:
Numbers[u]++;
break;
}
}
cout << Numbers[u] << endl;
}
return 0;
}
Halp!
Just use std::vector, std::iota and std::shuffle:
std::vector<int> v( 12 );
std::iota( v.begin(), v.end(), 0 ); // initialize with values 0..11
std::shuffle(v.begin(), v.end(), std::mt19937{std::random_device{}()}); // make em random
v.resize( 10 ); // remove extra elements
and you do not need to validate that all elements are unique
What I understood from your question that you are trying to read random numbers till all 10 numbers are different. Have a look on code below:
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <bitset>
using namespace std;
int main()
{
int Numbers[10] ;
srand(time(NULL));
//Keep flag with all the bits '0' initially
bitset<12> flags;
flags.reset();
// keep taking input till all bits are not '1'
int i = 0;
do
{
int in_num = rand() % 12;
// check if the bit at position "in_num" is 0
if (!flags[in_num])
{
Numbers[i++] = in_num;
flags.set(in_num);// set the bit 1
}
} while (i < 10);
for (int u = 0; u < 10; u++)
{
cout << endl << Numbers[u];
}
return 0;
}
I am writing a Caesar cipher decoding program that sorts the frequency of letters of a message in descending order. My issue is when I print out the results the positions of the frequencies in the array no longer match the letters I have set up. How do I fix this? I have other code that removes punctuation and capitals, all characters besides spaces and lowercase letters from the message being decoded.
I have trimmed down the code to just what is being questioned.
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
void sortArray(int*, int);
int main()
{
string fileContent = "a coded message which is several hundreds of characters long is being passed into the program";
int count[26];
// This code is skipping over spaces and other characters
for(int f = 0; f < fileContent.length(); f++)
{
if(fileContent[f] == 32)
{
continue;
}
if(fileContent[f] >= 48 && fileContent[f] <= 57)
{
continue;
}
count[(fileContent[f]-'a')%26]++;
}
// Here is where my issue begins. In sortArray, the position of the characters are being changed.
cout << "Letter frequency: Most common to least common" << endl;
sortArray(count, 26);
for(int p = 0; p < 26; p++)
{
cout << char(p + 97) << ": " << count[p] << endl;
}
return 0;
}
void sortArray(int* srcArray, int numElements)
{
for(int x = 0; x < numElements; x++)
{
int max = srcArray[x];
int maxIndex = x;
int hold;
for(int y = x + 1; y < numElements; y++)
{
if(srcArray[y] > max)
{
max = srcArray[y];
maxIndex = y;
}
}
hold = srcArray[x];
srcArray[x] = max;
srcArray[maxIndex] = hold;
hold = 0;
}
}
Please kindly let me know how I can solve this issue, I've been theorizing but I cannot seem to figure out a viable solution.
After you compute the frequency in count array.
std::array<std::pair<char, int>, 26> pairArray;
for (int i = 0; i < 26; ++i)
{
pairArray[i] = std::make_pair('a' + i, count[i]);
}
std::sort(pairArray.begin(), pairArray.end(), myCompare);
for (int i = 0; i < 26; ++i)
std::cout << pairArray[i].first << ": " << pairArray[i].second << std::endl;
For myCompare,
bool myCompare(const std::pair<char, int>& p1, const std::pair<char, int>& p2)
{
return p1.second > p2.second;
}
This should sort the array in descending order.
The problem you are facing is because you have frequencies in the array but the frequencies are not mapped to corresponding character. When the frequencies are sorted,the array is rearranged but your printing of the frequencies is not character dependent,you are printing characters from a-z and assigning frequencies as they are in sorted array.
What you can do is map the frequencies with corresponding character. One solution can be using an unordered map,char being key. An unordered map because it won't internally sort the map on character value,so u can maintain frequency ordering as well.
You can also use vector with pair as #lamandy suggested.
vector< pair <char, int> > vect;
for (int i = 0; i < 26; i++)
{
vect.push_back(make_pair(char(i + 97), count[i]));
}
sort(vect.begin(), vect.end(), sortbysecVal);
// Printing the sorted vector(after using sort())
cout << "The vector after sort operation is:\n";
for (int i = 0; i<26; i++)
{
// "first" and "second" are used to access
// 1st and 2nd element of pair respectively
cout << vect[i].first << " "
<< vect[i].second << endl;
}
sort by second value of pair
bool sortbysecVal(const pair<int, int> &a, const pair<int, int> &b)
return (a.second > b.second);
Once after you have calculated frequencies,you can use this,this will solve your purpose and you wont need your sort function.
P.S : One more thing,you must initialize your (array)count to 0,like int count[26] = {0},because initially it contains garbage if uninitialized and adding up 1 ( count[(fileContent[f]-'a')%26]++;) to a garbage will not produce result(frequency) u expect
The answer is probably a three-liner for a standard library guru, which I am not quite yet. I hate the standard library. It makes programming so easy that anyone can do it.
Here are two versions that I hacked out. This is fun.
#include <map>
#include <string_view>
#include <vector>
#include <algorithm>
using counted = std::pair<char, unsigned>;
std::vector<counted>
counted_chars(const std::string_view input) {
// Return a vector of <char, count> pairs, where char is an uppercase
// letter, and count is the number of occurrences of the letter (upper or lower).
// It is sorted from highest count to lowest.
using namespace std;
map<char, unsigned> count;
// Count them.
for(char next: input) {if (isalpha(next)) {count[toupper(next)] += 1;}}
// Sort them
vector<counted> sorted(count.size());
copy(count.cbegin(), count.cend(), sorted.begin());
sort(sorted.begin(), sorted.end(), [](counted c1, counted c2)
{ return c1.second > c2.second; });
return sorted;
}
int main() {
std::string str = "a coDed; MESSage which_is several hundreds of characters long is being passed into the program";
auto result = counted_chars(str);
return 0;
}
Another one that doesn't use std::map.
#include <map>
#include <vector>
#include <algorithm>
using counted = std::pair<char, unsigned>;
std::vector<counted> counted_chars(std::string input) {
using namespace std;
input.resize(remove_if(input.begin(), input.end(), [](char ch) { return !isalpha(ch); })-input.begin());
for(char &ch: input) { ch = toupper(ch); }
sort(input.begin(), input.end());
string present {input};
present.resize(unique(present.begin(), present.end())-present.begin());
std::vector<counted> sorted;
for (char ch:present) {sorted.push_back(make_pair(ch, count(input.begin(), input.end(), ch)));}
sort(sorted.begin(), sorted.end(), [](counted c1, counted c2) { return c1.second > c2.second; });
return sorted;
}
int main() {
std::string str = " -- I have always wished for my computer to be as easy to use as my telephone; My wish has come true because I can no longer figure out how to use my telephone.";
auto result = counted_chars(std::move(str));
return 0;
}
This program reads strings of numbers from a txt file, converts them to integers, stores them in a vector, and then tries to output them in an organized fashion like so....
If txt file says:
7 5 5 7 3 117 5
The program outputs:
3
5 3
7 2
117
so if the number occurs more than once it outputs how many times that happens. Here is the code so far.
#include "std_lib_facilities.h"
int str_to_int(string& s)
{
stringstream ss(s);
int num;
ss >> num;
return num;
}
int main()
{
cout << "Enter file name.\n";
string file;
cin >> file;
ifstream f(file.c_str(), ios::in);
string num;
vector<int> numbers;
while(f>>num)
{
int number = str_to_int(num);
numbers.push_back(number);
}
sort(numbers.begin(), numbers.end());
for(int i = 0; i < numbers.size(); ++i)
{
if(i = 0 && numbers[i]!= numbers[i+1]) cout << numbers[i] << endl;
if(i!=0 && numbers[i]!= numbers[i-1])
{
cout << numbers[i] << '\t' << counter << endl;
counter = 0;
}
else ++counter;
}
}
Edit: Program is getting stuck. Looking for an infinite loop right now.
You could use a map of numbers to counters:
typedef map<int,unsigned int> CounterMap;
CounterMap counts;
for (int i = 0; i < numbers.size(); ++i)
{
CounterMap::iterator it(counts.find(numbers[i]));
if (it != counts.end()){
it->second++;
} else {
counts[numbers[i]] = 1;
}
}
... then iterate over the map to print results.
EDIT:
As suggested by lazypython: if you have the TR1 extensions [wikipedia.org] available, unordered_map should have better performance...
typedef std::tr1::unordered_map<int,unsigned int> CounterMap;
CounterMap counts;
for (int i = 0; i < numbers.size(); ++i)
{
CounterMap::iterator it(counts.find(numbers[i]));
if (it != counts.end()){
it->second++;
} else {
counts[numbers[i]] = 1;
}
}
How about using a map, where the key is the number you're tracking and the value is the number of occurrences?
If you must use a vector, you've already got it sorted. So just keep track of the number you previously saw. If it is the same as the current number, increment the counter. Every time the number changes: print out the current number and the count, reset the count, set the last_seen number to the new number.
Using a map is the practical solution. What you should do is to solve this problem :)
This is called frequency counter. So, you have a sorted vector and all what you have to do is to count successive equal numbers. In other words, you have to check each number with its successor.
for(size_t i = 0; i < numbers.size(); i++)
{
size_t count = 1;
size_t limit = numbers.size() - 1;
while(i < limit && numbers[i] == numbers[i+1])
{
count++;
i++;
}
std::cout << numbers[i] << "\t" << count << std::endl;
}
This program reads strings of numbers
from a txt file, converts them to
integers, stores them in a vector, and
then tries to output them in an
organized fashion like so....(emphasis added)
What is the point of this storage step? If you are reading the numbers from a file, then you already have them in order, ready to be processed (counted) one at time, as you encounter them.
However, I would need a way for it to know when it sees a new number.
I advise you to have a look at std::set or std::map. I expect either of these containers would do what you're looking for.
Std::count() fits the bill nicely.
std::vector<int>::const_iterator cur = numbers.begin();
std::vector<int>::const_iterator last = numbers.end();
while (cur != last) {
unsigned cnt = std::count(cur, last, *cur);
std::cout << *cur;
if (cnt != 1) {
std::cout << " " << c;
}
std::cout << std::endl;
int saved = *cur;
while (*cur == saved) {
++cur;
}
}
Of course there are a bunch of other algorithms out there that will do the same job. Play with things like std::equal_range() in conjunction with std::distance() will do the job just as nicely.
That was fun:
#include <map>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
struct IncrementMap
{
IncrementMap(std::map<int,int>& m): m_map(m) {}
void operator()(int val) const
{
++m_map[val];
}
std::map<int,int>& m_map;
};
struct SpecialPrint
{
SpecialPrint(std::ostream& s): m_str(s) {}
void operator()(std::map<int,int>::value_type const& value) const
{
m_str << value.first;
if (value.second != 1)
{
m_str << "\t" << value.second;
}
m_str << "\n";
}
std::ostream& m_str;
};
int main()
{
std::fstream x("Plop");
std::map<int,int> data;
std::for_each( std::istream_iterator<int>(x),
std::istream_iterator<int>(),
IncrementMap(data)
);
std::for_each( data.begin(),
data.end(),
SpecialPrint(std::cout)
);
}