How would I print out a map in descending order? - c++

So I'm trying to iterate through the map from greatest to least and it has to print the top 10. I have to use map.h because its required so I can't use the normal map, I also cant use a vector. How would I just get the top 10 from the map from descending order?
Here is the link to the Stanford Map Library
#include <iostream>
#include "map.h"
using namespace std;
Map <string, int> wordFreq;
int counter = 0;
int max = 0;
for(string s : wordFreq)
{
if(wordFreq[s] > max)
{
counter++;
max = wordFreq[s];
cout << s << " : " << max << endl;
}
if(counter == 10)
{
exit(0);
}
}
I've been at this for a couple of hours so I think my logic is just bad.

If you only need top 10 value, you should use a minHeap with a size of 10 as you don't need to sort all the elements in the map.
Then sort the elements in minHeap before return if you need(maybe unsorted top10 values are excepted).

This class has no way to iterate it other than a "visit all" function. So there's not going to be any good way to do it.
A simple hack is as follows:
Flip the sign of every int you use as a key before storing it in the map.
This will cause the map to visit its elements in reverse order.
Call mapAll with a visitor function that only prints the first ten times it's called. Don't forget to flip the sign of each key before printing it.
A less hacky way is to create reversedInt class that acts like an int but compares in reverse. That will avoid the need to flip signs and still let the map traverse in reverse.
It seems the provided Map class can accept a comparator in its constructor. So this might be the intended way to do this, I guess.
But the provided Map class is really just not suitable for this use.

Related

why doesn't user defined function sort the elements of same length in the order given?

My task is to sort the words of a string in the increasing order of their length and for words of same length, I have to keep them in the order given.
for ex: "to be or not to be" will become "to be or to be not".
i am first making a vector 'v' of all the words in the string and then trying to sort the vector using user defined function in sort() function of C++.
Here is my code:
#include <bits/stdc++.h>
using namespace std;
static bool comparelength(string first,string second){//function to compare length
return first.size()<second.size();
}
int main() {
string text="Jlhvvd wfwnphmxoa qcuucx qsvqskq cqwfypww dyphntfz hkbwx xmwohi qvzegb ubogo sbdfmnyeim tuqppyipb llwzeug hrsaebveez aszqnvruhr xqpqd ipwbapd mlghuuwvec xpefyglstj dkvhhgecd kry";
vector<string> v;
string cur="";
text+=" ";
for(int i=0;i<text.size();i++){
if(text[i]==32){//if space is encountered then the word is inserted in the vector
v.push_back(cur);
cur="";
}
else{
cur+=text[i];//if not space then text[i] is added to the current word
}
}
sort(v.begin(),v.end(),comparelength);//sort the vector
for(int i=0;i<v.size();i++)
cout<<v[i]<<" ";
Now it gives this output:
"Kry xqpqd ubogo hkbwx qvzegb jlhvvd xmwohi qcuucx qsvqskq llwzeug ipwbapd dyphntfz cqwfypww tuqppyipb dkvhhgecd sbdfmnyeim xpefyglstj mlghuuwvec aszqnvruhr hrsaebveez wfwnphmxoa"
But the correct output should be:
"Kry hkbwx ubogo xqpqd jlhvvd qcuucx xmwohi qvzegb qsvqskq llwzeug ipwbapd cqwfypww dyphntfz tuqppyipb dkvhhgecd wfwnphmxoa sbdfmnyeim hrsaebveez aszqnvruhr mlghuuwvec xpefyglstj"
see the position 1,2 and 3(using 0 indexing).
it should give: hkbwx ubogo xqpqd.
but it gives: xqpqd ubogo hkbwx.
which makes me think that it is not sorting the words of same length in the order given. You can find many other positions where this happens(for ex: 4,5,6 and 7).
But for the string "leetcode plus try suck geaser is cool best"
it gives the correct output which is: "is try plus suck cool best geaser
leetcode"
Can anyone make it clear why is it not working for the former string but working for the latter.
I've tried doing
static bool comparelength(string first,string second){
if(first.size()==second.size())
return true;
if(first.size()<second.size())
return true;
else
return false;
}
But this throws runtime error.
sorry for making the question messy but i really want to understand this.
std::sort is not stable, ie order of elements that are equivalent is not necessarily preserved. If you get a stable sorting from std::sort then this is just by chance. Stable sorting is more expensive (O(N·log(N)^2) vs O(N·log(N))), hence you have to explicitly ask for it. It can be done with std::stable_sort.
You could use std::sort with a custom comparator if you would populate a container of std::pair<std::string,size_t> where second is the index in the original container. However, I suppose using std::stable_sort is simpler.

Show the percentage of process completion in a C++ program

I am making a set of C++ library as a part of my Data Structures assignment, which includes custom implementation of vector, sorting algorithms, stacks, etc. I am supposed to work on the running time of sorting algorithms, bubble sort, selection sort, quick sort, etc., which are part of my library.
Now the data set given to test the algorithms in of the order of 10^6. I ran bubble sort on a data of 2*10^6 elements, and it took about 138 minutes for the program to run, and in all this time, I did not know if my sorting algorithm is working correctly or not, or is it even working or not. I would want to add another feature to the sorting functions, i.e they could display the percentage of sorting done, and I think this is possible, since algorithms like bubble sort are deterministic.
I need a message like something to appear as soon as I start the process:
Bubble sort under progress. Done: 17%
This percentage is to be determined by the algorithm. Consider the example of bubble sort with 10000 elements. If you look at the bubble sort algorithm(refer here: https://en.wikipedia.org/wiki/Bubble_sort), it has 2 loops, and after each iteration of the main loop, one element is fixed to its correct position in the sorted array. So after like 1 iteration, the percentage should increase by 0.01%.
Though this percentage calculation has a problem that in this case, the time for the percentage to increase keeps on decreasing, but something like this would do.
Also, this number should increase as and when required, on the same place. But I have no idea how to implement it.
You can pass a callback function of a generic type to your bubblesort function and call the function at reasonable intervals.
This will impact performance, but this shouldn't be a concern when you're using bubblesort anyway.
First we'll need some includes:
#include <iostream>
#include <vector>
#include <random>
#include <chrono>
And then the bubblesort function, which I essentially took from wikipedia: https://en.wikipedia.org/wiki/Bubble_sort#Optimizing_bubble_sort
template <typename T, typename Func>
void bubblesort(std::vector<T> &v, Func callback) {
size_t const len = v.size();
size_t n = v.size();
while(n > 0) {
size_t newn = 0;
for(size_t i = 1; i <= n-1; ++i) {
if (v[i - 1] > v[i]) {
std::swap(v[i-1], v[i]);
newn = i;
}
}
n = newn;
callback(100-static_cast<int>(n*100/len));
}
}
We will call the given callback function (or use operator() on an object) whenever it's done sorting in one element.
The parameter we pass is an integer percentage of how far we've come. Note that due to integer arithmetic you cannot change the order of operations with n*100/v.size() or else it would always result in 0, since n will always be smaller than v.size();
using namespace std::chrono; //to avoid the horrible line becoming even longer
int main() {
std::vector<int> vec;
/* fill vector with some data */
std::mt19937 generator(static_cast<unsigned long>(duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count())); //oh god
for(int i = 0; i < 100000; ++i) {
vec.push_back(static_cast<int>(generator()));
}
For initialization we get create a random number generator and seed it with the current time. Then we put some elements in the vector.
char const *prefix = "Bubble sort under progress. Done: ";
int lastp = -1;
bubblesort(vec, [&lastp,prefix](int p){
//if progress has changed, update it
if(p != lastp) {
lastp = p;
std::cout << "\r" << prefix << p << "%" << std::flush;
/*std::flush is needed when we don't start a new line
'\r' puts the cursor to the start of the line */
}
});
std::cout << "\r" << prefix << "100%" << std::endl;
//make sure we always end on 100% and end the line
}
Now the core part: we pass a C++ lambda function to our bubblesort function as a callback. Our bubblesort function will then call this lambda with the percentage value and write it to the screen.
And voilà, we got ourselves some neat output:
https://youtu.be/iFGN8Wy9T3o
Closing notes:
You can of course integrate the lamda function into the sort function itself, however I would not recommend this as you lose a lot of flexibility. But it's a design choice that's up to you - if you don't need the flexibility, just hardcode it.
The percentage is not very accurate, in fact knowing you're at 20% (and how long it took to get there) does not tell you much at all about the time it will take to get to 100% as it could very well be, that the last 20% of the vector were sorted (and thus were quick to sort with bubblesort - O(n)), but the remaining 80% are random, and take O(n^2) to sort.
In fact all it tells you is that you're making progress, but that's all you wanted in the first place so I guess that's okay.
If you want a more accurate percentage adjust your program like this:
#include <iomanip>
/* ... */
callback(10000-static_cast<int>(n*10000/len));
/* ... */
std::cout.fill('0'); //to fill leading zero of p%100
std::cout << "\r" << prefix << p/100 << "." << std::setw(2) << p%100 << "%" << std::flush;
If you decide to use floating point values instead remember to clear remnant characters from previous outputs - "\r" only resets the cursor position, but does not clear the line.
Use std::cout.precision(3); for a fixed precision or write some spaces after your message to clear previous runs.
For the special case of bubblesort, you can take the number of elements you have, then divide that by 100. If you have 552 elements, then you will get 5. (integers make sense to work with). Then, have a counter in your loop. If the counter is a multiple of 5, (you've so far sorted 5 elements) then you can increase the percentage by 1 and print it. As far as printing it so that the percentage appears on the spot instead of printing below, you can print backspaces! Either that or try using the ncurses library, though that might be overkill. Finally, a different way to do this might be to use a linux style progress bar that is 50 characters long or something similar.

C++ Generate random numbers for dominoes

My assignment involves writing several classes that will work together to randomly sort 28 dominoes for the user and display them. The main trouble I'm having so far is just creating the dominoes without any duplication. If you're familiar with dominoes, you know that each half of them are either blank or have 1-6 dots. Basically I'll have a dynamic array of 28 unique structs (dominoes) but I'm just stuck on generating these dominoes without having identical ones. I was thinking of using FOR loops to just go through and assign values within each struct but I figured there had to be some easier way.
This is what I have so far below; I know it's not much but I can't and don't want to go on with writing methods for sorting and display without getting this right first.
class CDominoes{
public:
struct Data
{
int top;
int bottom;
Data()
{
top = 0;
bottom = 0;
}
} domino[28];
//methods to assign spots to halves
};
The simplest solution is to generate, and then shuffle. To generate, you need to avoid wasting time generating duplicates. For example, (4,5) is the same as (5,4), so you don't want to generate both. That means that your inner loop should always begin at the current value of the outer loop. In so doing, you'll never repeat a combination. Here's an example:
int main () {
for( int t = 0; t <= 6; ++t ) {
for( int b = t; b <= 6; ++b ) {
std::cout << "(" << t << "," << b << ")\n";
}
}
return 0;
}
In this example, we're considering '0' to be the same as a blank domino.
Next, instead of printing these, put them into a random access container such as std::array or std::vector, and then use std::shuffle to shuffle your container.

Time complexity issues with multimap

I created a program that finds the median of a list of numbers. The list of numbers is dynamic in that numbers can be removed and inserted (duplicate numbers can be entered) and during this time, the new median is re-evaluated and printed out.
I created this program using a multimap because
1) the benefit of it being already being sorted,
2) easy insertion, deletion, searching (since multimap implements binary search)
3) duplicate entries are allowed.
The constraints for the number of entries + deletions (represented as N) are: 0 < N <= 100,000.
The program I wrote works and prints out the correct median, but it isn't fast enough. I know that the unsorted_multimap is faster than multimap, but then the problem with unsorted_multimap is that I would have to sort it. I have to sort it because to find the median you need to have a sorted list. So my question is, would it be practical to use an unsorted_multimap and then quick sort the entries, or would that just be ridiculous? Would it be faster to just use a vector, quicksort the vector, and use a binary search? Or maybe I am forgetting some fabulous solution out there that I haven't even thought of.
Though I'm not new to C++, I will admit, that my skills with time-complexity are somewhat medicore.
The more I look at my own question, the more I'm beginning to think that just using a vector with quicksort and binary search would be better since the data structures basically already implement vectors.
the more I look at my own question, the more I'm beginning to think that just using vector with quicksort and binary search would be better since the data structures basically already implement vectors.
If you have only few updates - use unsorted std::vector + std::nth_element algorithm which is O(N). You don't need full sorting which is O(N*ln(N)).
live demo of nth_element:
#include <algorithm>
#include <iterator>
#include <iostream>
#include <ostream>
#include <vector>
using namespace std;
template<typename RandomAccessIterator>
RandomAccessIterator median(RandomAccessIterator first,RandomAccessIterator last)
{
RandomAccessIterator m = first + distance(first,last)/2; // handle even middle if needed
nth_element(first,m,last);
return m;
}
int main()
{
vector<int> values = {5,1,2,4,3};
cout << *median(begin(values),end(values)) << endl;
}
Output is:
3
If you have many updates and only removing from middle - use two heaps as comocomocomocomo suggests. If you would use fibonacci_heap - then you would also get O(N) removing from arbitary position (if don't have handle to it).
If you have many updates and need O(ln(N)) removing from arbitary places - then use two multisets as ipc suggests.
If your purpose is to keep track of the median on the fly, as elements are inserted/removed, you should use a min-heap and a max-heap. Each one would contain one half of the elements... There was a related question a couple of days ago: How to implement a Median-heap
Though, if you need to search for specific values in order to remove elements, you still need some kind of map.
You said that it is slow. Are you iterating from the beginning of the map to the (N/2)'th element every time you need the median? You don't need to. You can keep track of the median by maintaining an iterator pointing to it at all times and a counter of the number of elements less than that one. Every time you insert/remove, compare the new/old element with the median and update both iterator and counter.
Another way of seeing it is as two multimaps containing half the elements each. One holds the elements less than the median (or equal) and the other holds those greater. The heaps do this more efficiently, but they don't support searches.
If you only need the median a few times you can use the "select" algorithm. It is described in Sedgewick's book. It takes O(n) time on average. It is similar to quick sort but it does not sort completely. It just partitions the array with random pivots until, eventually, it gets to "select" on one side the smaller m elements (m=(n+1)/2). Then you search for the greatest of those m elements, and this is the median.
Here is how you could implement that in O(log N) per update:
template <typename T>
class median_set {
public:
std::multiset<T> below, above;
// O(log N)
void rebalance()
{
int diff = above.size() - below.size();
if (diff > 0) {
below.insert(*above.begin());
above.erase(above.begin());
} else if (diff < -1) {
above.insert(*below.rbegin());
below.erase(below.find(*below.rbegin()));
}
}
public:
// O(1)
bool empty() const { return below.empty() && above.empty(); }
// O(1)
T const& median() const
{
assert(!empty());
return *below.rbegin();
}
// O(log N)
void insert(T const& value)
{
if (!empty() && value > median())
above.insert(value);
else
below.insert(value);
rebalance();
}
// O(log N)
void erase(T const& value)
{
if (value > median())
above.erase(above.find(value));
else
below.erase(below.find(value));
rebalance();
}
};
(Work in action with tests)
The idea is the following:
Keep track of the values above and below the median in two sets
If a new value is added, add it to the corresponding set. Always ensure that the set below has exactly 0 or 1 more then the other
If a value is removed, remove it from the set and make sure that the condition still holds.
You can't use priority_queues because they won't let you remove one item.
Can any one help me what is Space and Time complexity of my following C# program with details.
//Passing Integer array to Find Extreme from that Integer Array
public int extreme(int[] A)
{
int N = A.Length;
if (N == 0)
{
return -1;
}
else
{
int average = CalculateAverage(A);
return FindExtremes(A, average);
}
}
// Calaculate Average of integerArray
private int CalculateAverage(int[] integerArray)
{
int sum = 0;
foreach (int value in integerArray)
{
sum += value;
}
return Convert.ToInt32(sum / integerArray.Length);
}
//Find Extreme from that Integer Array
private int FindExtremes(int[] integerArray, int average) {
int Index = -1; int ExtremeElement = integerArray[0];
for (int i = 0; i < integerArray.Length; i++)
{
int absolute = Math.Abs(integerArray[i] - average);
if (absolute > ExtremeElement)
{
ExtremeElement = integerArray[i];
Index = i;
}
}
return Index;
}
You are almost certainly better off using a vector. Possibly maintaining an auxiliary vector of indexes to be removed between median calculations so you can delete them in batches. New additions can also be put into an auxiliary vector, sorted, then merged in.

the value of iterator

i created a map.
i want to print the index of the key to a file using the itr in the map.
this is what i mean:
map <string,int> VendorList;
VendorList[abc] = 0;
VendorList[mazda] = 111;
VendorList[ford] = 222;
VendorList[zoo] = 444;
map <string,int>::iterator itr=VendorList.find("ford");
fstream textfile;
textfile << itr;
if i put in the find line abc i wish the program to cout 1.
if i put in the find line mazda i wish the program to cout 2.
if i put in the find line ford i wish the program to cout 3.
if i put in the find line zoo i wish the program to cout 4.
how do i do that?
the compiler is shouting on the line:
textfile << itr;
it gives this error:
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'std::_Tree<_Traits>::iterator' (or there is no acceptable conversion)
Your program has many bugs. Frankly speaking I am not sure about your requirement.
But anyways try this :
map <string,int> VendorList;
VendorList["abc"] = 1;
VendorList["mazda"] = 2;
VendorList["ford"] = 3;
VendorList["zoo"] = 4;
map <string,int>::iterator itr=VendorList.find("ford");
cout<<(itr->second);// this will print 3
EDIT :
Also as somebody has suggested to use vector of pairs,I think he is right. Try something like this.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
typedef vector<pair<string,int> > Vm;
Vm V;
V.push_back(make_pair("abc",0));
V.push_back(make_pair("mazda",111));
V.push_back(make_pair("ford",222));
V.push_back(make_pair("zoo",444));
for(size_t i=0;i!=V.size();++i)
if(V[i].first=="ford")
cout<<(i+1);
}
Modify the above program as per requirement.
Hope that helps.
In map, the elements aren't stored in the order of insertion, so you have to hold the "order" data yourself.
I would suggest you to consider using a vector of pairs instead of a map. Vector does store the elements in the order of insertion, and its iterator is Random-Access so you will be able to check the position using the operator-.
vector <pair<string, int> >::iterator itr;
// itr = the needed element
cout << itr - VendorList.begin();
As such, the concept of 'index' doesn't really fit with Maps.
Maps are just key-value pairs where you store a value (say, '111') and access it using a key (say 'mazda'). In this way you don't really need an index in order to access '111', you can just use the key 'mazda'.
If you do want your application to be index based however, consider using a different data structure like a Vector or a Linked List.