Cannot declare map with integer keys in C++ - c++

I was attempting to write a Longest Common Substring program using Rabin Karp and Binary search. For that I wrote a method which basically create a hash table for one of the strings and the key would be the hash value of the pattern of length M starting at index i . The value of they key would be index i .
I have written the following code :
#include <iostream>
#include <string>
#include<map>
#include<math.h>
#define BASE 10
#define BASE2 10.0
#define M 99999989
using namespace std;
map<int, int> hashmap;
int pHash=0;
int mod(int a, int b) {
return (a%b + b)%b;
}
int getHash(string & pattern) {
int hashVal = 0;
for ( int i =0 ; i<pattern.length();i++) {
int val = (int) pattern[i];
hashVal = mod(hashVal*BASE + val, M);
}
return hashVal;
}
int rabinKarp(string &pattern, string & text)
{
pHash = getHash(pattern);
cout<<"P HASH : "<<pHash<<endl;
int m = pattern.size();
int fHash = getHash(text.substr(0, pattern.size()));
int newKey = fHash;
hashmap.insert(newKey, 0);
if(fHash==pHash)
cout<<"Rabin Karp found a match at index : 0 "<< endl;
for(int i = 1; i <=text.size()-pattern.size();i++) {
int val = (int)text[i-1];
double sz = (double)pattern.size()-1.0;
int temp = pow(BASE2, sz);
int mult= mod(temp,M);
fHash = mod(fHash - mod(val*mult,M),M);
fHash= mod(fHash*BASE, M);
fHash= mod(fHash+(int)text[i+m-1], M);
int key = fHash ;
hashmap.insert(key, i);
if(fHash==pHash)
cout<<"Rabin Karp found a match at index : "<< i<<endl;
}
return 1;
}
int main() {
string pattern;
string text;
cout<<"Please enter the pattern "<<endl;
getline(cin, pattern) ;
cout<<"Please enter the text " <<endl;
getline(cin, text);
int index = rabinKarp(pattern, text) ;
}
The problem is that I am unable to insert the keys into the map . I am getting the following error of which I can make no sense . Anyone can help me understand what this is ?
Error 3 error C2664: 'std::pair<_Ty1,_Ty2> std::_Tree<_Traits>::insert(const std::pair<_Kty,_Ty> &)' : cannot convert parameter 1 from 'int' to 'const std::pair<_Ty1,_Ty2> &' c:\program files\microsoft visual studio 9.0\vc\include\xtree 760 SPOJ
Error 2 error C2100: illegal indirection c:\program files\microsoft visual studio 9.0\vc\include\xtree 760 SPOJ

If you are trying to insert a key-value pair, you need to insert an std::pair<K, V>, where K and V are the key and value types respectively. See std::map:insert. You need something like
hashmap.insert(std::make_pair(newKey, 0));
If you want to insert a value for a given key, and you don't mind about potentially overwriting a previously existing value, you can use operator[]:
hashmap[newKey] = someValue;

Since C++11, you can also use emplace(key, value). This constructs a pair for you using the given arguments, and then inserts it into the map.
hashmap.emplace(newKey, 0);

You should call
result = hashmap.insert(map<int, int>::value_type (newKey, 0));
// or
result = hashmap.insert(std::make_pair(newKey, 0));
insert als0 returns std::pair<iterator, bool> - you can check with result.second if you have successfully inserted the element (for instance if there were element with the same key , it would not insert it and return false.

Related

Error when calling void function with <set> operator

I am trying to pass a string and and an empty set into my function. Then I would like to call the function in my main and print all of the elements in the set.
This is my function code:
#include<iostream>
using std::cout; using std::endl;
#include<algorithm>
using std::set_union; using std::copy;
#include<iterator>
using std::inserter; using std::ostream_iterator;
#include<string>
using std::string;
#include<set>
using std::set;
void removing(const string &word, set<string> &result) {
string del_word = word;
char erased_l;
for(int i = 0; i < del_word.length(); i++) {
erased_l = word[i];
del_word.erase(0, 1);
del_word = erased_l + del_word;
}
}
Below is my main code where I call the function:
int main (){
set<string> jump = {};
set<string> del = removing("axiom", jump);
for (string ele:del) {
cout << ele << endl;
}
}
I get the following error:
No viable conversion from 'void' to 'set<std::__1::string>' (aka 'set<basic_string<char, char_traits<char>, allocator<char> > >')
The error is in line 16:
set<string> del = removing("axiom", jump);
My code is trying to accomplish:
If I pass in axiom, then I would like my string set to have {xiom, aiom, axom, axim, axio}. So remove first letter, keep rest of the word. Then remove second letter, keep rest of the word, etc...
Primary issues include:
The return value of a void function can't be assigned to a set, hence your compiler error. Your design is to pass a reference to an empty result set into the removing function and have it populated with the result data, so you can remove the assignment here.
Nothing is added to your result inside your removing function, so it starts empty and ends empty after the function call.
Here's a working version:
void removing(const string &word, set<string> &result) {
for (int i = 0; i < word.length(); i++) {
result.insert(word.substr(0, i) + word.substr(i + 1, word.length()));
}
}
int main () {
set<string> jump = {};
removing("axiom", jump);
for (string ele : jump) {
cout << ele << endl;
}
}
Output:
aiom
axim
axio
axom
xiom
Having said that, it's not clear to me why result should be a parameter to the function. If you're only planning on using it to store this particular result, this design seems much cleaner from the perspective of the caller:
set<string> removing(const string &word) {
set<string> result;
for (int i = 0; i < word.length(); i++) {
result.insert(word.substr(0, i) + word.substr(i + 1, word.length()));
}
return result;
}
int main () {
set<string> jump = removing("axiom");
for (string ele : jump) {
cout << ele << endl;
}
}
Try it!

Class template, no constructor could take the source(string)

attempting to compile the code gives several errors(error codes at the bottom)
//heap.h
#include <iostream>
#include <vector>
using namespace std;
template<class TYPE>
class Heap{
private:
vector<TYPE> heap;
int size;// number of elements in the heap
bool maxheap = true;
TYPE bubble_up(TYPE item);
TYPE bubble_down(TYPE item);
public:
Heap();
Heap(bool maxheap);
Heap(vector<TYPE>, bool order);
~Heap();
void build_heap();
TYPE Insert(TYPE item);
TYPE Delete(TYPE& item);
const vector<TYPE> sort(bool order);
const vector<TYPE> sort();// defualt sort if no variable given, max sort
TYPE get_size();
void print_heap();
void clear_heap();
};
template<class TYPE>
Heap<TYPE>::Heap(){
TYPE dummy{};
heap.push_back(dummy);
size = heap.size() - 1;
}
template<class TYPE>
Heap<TYPE>::Heap(bool order){
maxheap = order; // true is max, false is min
TYPE dummy{};
heap.push_back(dummy);
size = heap.size() - 1;
}
template<class TYPE>
Heap<TYPE>::Heap(vector<TYPE> x, bool order){
maxheap = order;// true is max, false is min
TYPE tempSize;
TYPE dummy{};
heap.push_back(dummy);
size = heap.size() - 1;
tempSize = x.size();
for (TYPE y = 0; y < tempSize; y++){
heap.push_back(x[y]);
}
size = heap.size() - 1;
build_heap();
}
template<class TYPE>
TYPE Heap<TYPE>::Insert(TYPE item){
heap.push_back(item);
size = heap.size() - 1;
return bubble_up(size);
}
TYPE Heap<TYPE>::bubble_up(TYPE pos){
TYPE retVal;
if (pos == 1)// root of tree
{
return pos;
}
if (maxheap == true){
if (heap[pos] > heap[pos / 2]){// greater than parent
TYPE temp = heap[pos / 2]; //swap method
heap[pos / 2] = heap[pos];
heap[pos] = temp;
return retVal = bubble_up(pos / 2);
}
else{
return pos;
}
}
if (maxheap == false){//min heap
if (heap[pos] < heap[pos / 2]){// less than parent
TYPE temp = heap[pos / 2]; //swap method
heap[pos / 2] = heap[pos];
heap[pos] = temp;
return retVal = bubble_up(pos / 2);
}
else{
return pos;
}
}
}
here is the driver file currently being used.
#include <iostream>
#include <string>
#include "Heap.h"
using std::cout;
using std::endl;
typedef string TYPE;
int main(void) {
Heap<std::string> *s_heap = new Heap<std::string>(); // string heap
std::string s_item = "0";
vector<std::string> s_blah(11, s_item);
cout << "\n*** Test insert elements ***";
cout << endl << s_heap->Insert("15");
cout << endl << s_heap->Insert("1");
cout << endl << s_heap->Insert("3");
cout << endl << s_heap->Insert("4");
cout << endl;
}
full error code:
c:\users\\documents\visual studio 2013\projects\pa 3 templates\pa 3 templates\heap.h(85): error
C2664: 'std::string Heap<std::string>::bubble_up(TYPE)' : cannot convert argument 1 from 'int' to 'std::string'
1> with
1> [
1> TYPE=std::string
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
1> c:\users\\documents\visual studio 2013\projects\pa 3 templates\pa 3 templates\heap.h(82) : while compiling class template member function 'std::string Heap<std::string>::Insert(TYPE)'
1> with
1> [
1> TYPE=std::string
1> ]
1> c:\users\\documents\visual studio 2013\projects\pa 3 templates\pa 3 templates\driver.cpp(17) : see reference to function template instantiation 'std::string Heap<std::string>::Insert(TYPE)' being compiled
1> with
1> [
1> TYPE=std::string
1> ]
You've got a handful of problems here, mostly related to your attempt to make your Heap generic, which you've failed to do.
You're trying to create a heap of std::string (despite all the values you're adding being numbers, but lets skip that form the moment).
The argument of bubble_up will therefor also be a string:
TYPE Heap<TYPE>::bubble_up(TYPE pos){
The problem comes in lines like this:
if (pos == 1)// root of tree
and this:
heap[pos / 2] = heap[pos];
You're trying to compare a string with a number in the first case, and trying to perform division on the string in the second case! This isn't going to work. The problem can only get worse if you try to pass in structs and classes and whatever else.
You will either need to enforce that TYPE is an integral type that you can perform these operations on, or seriously rewrite the way your heap works.
To allow a generic-ish heap that fails with a sensible error when supplied a non-integral TYPE, you can do this:
template<class TYPE>
class Heap{
private:
static_assert(std::is_integral<TYPE>::value, "Must be an integral type");
If you actually wanted your heap to work with strings... well. That's another problem altogether. You could try storing a hash of all your values:
#include <functional>
// ...
std::hash<TYPE> hashfunc;
size_t hashval = hashfunc(pos);
Hash functions are defined for all the standard library types, and return a nice integral size_t value that can be fed to the rest of your heap algorithm without any substantial changes, I think. You'd still need to keep a mapping back from hash values to original data if you wanted to return useful values from bubble_up, etc, but I'll leave that as an exercise to the reader.

C++ vector of vectors in class

I have a class in which vectors of doubles are stored like this this:
class clsHalfphoneUnitJoinFeatures : public CBaseStructure
{
private:
vector<double> m_content;
protected:
virtual void ProcessTxtLine(string line);
public:
vector<double> &Content();
void Add(vector<double> &jf);
};
However, when I want to add a new vector of doubles, it won't work:
void clsHalfphoneUnitJoinFeatures::ProcessTxtLine(string line)
{
line = CompactLine(line);
if (line == "")
return;
int b = 0;
int n = line.find("\t");
string s = "";
int idx = 0;
vector<double>jf;
jf.resize(16);
int i = 0;
for(;;)
{
if (n == -1)//if this is the last item in this line
{
s = line.substr(b,line.length()-b);
jf[i++] = atof(s.c_str());
break;
}
s = line.substr(b,n-b);
jf[i++] = atof(s.c_str());
b = n+1;
n = line.find("\t",b);
}
m_content.push_back(jf);
}
The error I am getting is in
m_content.push_back(jf);
error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)': Conversion of parameter 1 from 'std::vector<_Ty>' in 'double &&' not possible
Can somebody tell me where I went wrong?
Thank you!
jf and m_content have the same type, you can't push jf as an element of m_content.
Try change
m_content.push_back(jf);
To:
m_content = jf;
If you want to have a vector of vector of double type, you need to declare m_content as:
std::vector<std::vector<double> > m_content;
a) Error m_content.push_back(jf);. You are trying to push vector to a vector which can store double. so the compiler is giving error.
You can resolve it by assigning jf to m_context
m_content = jf;
b) Else if your implementation needs vector of vector follow the steps below
Declare m_content as vector of double vector.
vector<vector<double>> m_content;
...
m_content.push_back(jf);

All possible combinations(with repetition) as values in array using recursion

I'm trying to solve a problem in which I need to insert math operations(+/- in this case) between digits or merge them to get a requested number.
For ex.: 123456789 => 123+4-5+6-7+8-9 = 120
My concept is basically generating different combinations of operation codes in array and calculating the expression until it equals some number.
The problem is I can't think of a way to generate every possible combination of math operations using recursion.
Here's the code:
#include <iostream>
#include <algorithm>
using namespace std;
enum {noop,opplus,opminus};//opcodes: 0,1,2
int applyOp(int opcode,int x, int y);
int calculate(int *digits,int *opcodes, int length);
void nextCombination();
int main()
{
int digits[9] = {1,2,3,4,5,6,7,8,9};
int wantedNumber = 100;
int length = sizeof(digits)/sizeof(digits[0]);
int opcodes[length-1];//math symbols
fill_n(opcodes,length-1,0);//init
while(calculate(digits,opcodes,length) != wantedNumber)
{
//recursive combination function here
}
return 0;
}
int applyOp(int opcode,int x, int y)
{
int result = x;
switch(opcode)
{
case noop://merge 2 digits together
result = x*10 + y;
break;
case opminus:
result -= y;
break;
case opplus:
default:
result += y;
break;
}
return result;
}
int calculate(int *digits,int *opcodes, int length)
{
int result = digits[0];
for(int i = 0;i < length-1; ++i)//elem count
{
result = applyOp(opcodes[i],result,digits[i+1]);//left to right, no priority
}
return result;
}
The key is backtracking. Each level of recursion handles
a single digit; in addition, you'll want to stop the recursion
one you've finished.
The simplest way to do this is to define a Solver class, which
keeps track of the global information, like the generated string
so far and the running total, and make the recursive function
a member. Basically something like:
class Solver
{
std::string const input;
int const target;
std::string solution;
int total;
bool isSolved;
void doSolve( std::string::const_iterator pos );
public:
Solver( std::string const& input, int target )
: input( input )
, target( target )
{
}
std::string solve()
{
total = 0;
isSolved = false;
doSolve( input.begin() );
return isSolved
? solution
: "no solution found";
}
};
In doSolve, you'll have to first check whether you've finished
(pos == input.end()): if so, set isSolved = total == target
and return immediately; otherwise, try the three possibilities,
(total = 10 * total + toDigit(*pos), total += toDigit(*pos),
and total -= toDigit(*pos)), each time saving the original
total and solution, adding the necessary text to
solution, and calling doSolve with the incremented pos.
On returning from the recursive call, if ! isSolved, restore
the previous values of total and solution, and try the next
possibility. Return as soon as you see isSolved, or when all
three possibilities have been solved.

Sorting of vector containing structure

I was trying to sort a vector of struct.The following is my code.I am not able to sort it properly...Can anyone help me..?I need to sort according to the mmNo.Sorry ...i missed some part of the code...
typedef struct MMInfo
{
std :: string strMmNo;
std :: string strMmName;
std :: string strMmsPlace;
std :: string strMmAdd;
std :: string strMmPh;
MMInfo(const std::string& mmNo,
const std::string& mmName,
const std::string& mmPlace,
const std::string& mmAdd,
const std::string& mmPh) : stringValue(mmNo,),stringValue(mmName),
stringValue(mmPlace),stringValue(mmAdd),
stringValue(mmPh) {}
bool operator < (const MMInfo& str) const
{
return (mmNo < str.mmNo);
}
} MMInfo;
std::vector < MMInfo > mmlist;
MMInfo mmInfo = {"", "", "", "", ""};
mmInfo.strMmNo = "3452132"; //actually , i have used a loop to get it from the user
mmInfo.strMmName="Peter";
mmInfo.strMmPlace="TCR";
mmInfo.strMmAdd="Street 453";
mmInfo.strMmPh="8587556587";
mmlist.push_back(mmInfo);
sort(mmlist.begin(),mmlist.end());
for (int i=0; i<mmlist.size(); i++)
{
cout << " first row :" << mmlist[i].strMmNo << " " << mmlist[i].strMmName
<<" " <<mmlist[i].strMmsPlace << " " << mmlist[i].strMmsAdd ;
}
Your code has no problems. I mean, the usage is right but the structure definition seems not correct. It's not compilable at least in Visual C++ 9.0 Please make a proper initialization list. The following code worked fine for me
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct NodeInfo
{
int x;
NodeInfo( int xi ){ x = xi; }
bool operator < (const NodeInfo& str) const
{
return (x < str.x);
}
}MMInfo;
int _tmain(int argc, _TCHAR* argv[])
{
std::vector < MMInfo > mmlist;
mmlist.push_back( 1 );
mmlist.push_back( 31 );
mmlist.push_back( 21 );
mmlist.push_back( 11 );
mmlist.push_back( 41 );
sort(mmlist.begin(),mmlist.end());
for (unsigned int i=0; i<mmlist.size(); i++)
{
cout<< " x row : \n" << mmlist[i].x ;
}
return 0;
}
Does that even compile? (No!)
You're trying to initialize values that don't exist. Maybe initialize your strMm* values instead of stringValue?
You're initializing the same value (that doesn't even exist!) multiple times (Initialize strMm* members with a corresponding mm* value)
Your comparison function compares values that don't exist. (Compare strMmNo < str.strMmNo).
Also, you don't even have values to sort in your list.