c++ map of vector in structure - c++

The program I want to do is an anagram finder
From a dictionary file and a string input, the function "anagrams" should return me a vector (one for each size from 1 to max) of vector of words found in the dictionary that match all the combination of sub-words possible with input as anagram
When I create the new dictionary with the function createdictionary, I put every anagram in a vector of string
However, when I want to check for these anagrams in my anagrams function, I don't know how to access it (line 74)
In uniqueAnagram, I have every sub-anagram possible, everything is ok, but using
if (dict.words.find(it->second)){
cout << dict.words.find(it->second)->second[0] << endl;
}
in the loop (as a test to see if the expression actually write the right words) leads me to this error and I don't understand why:
In function 'std::vector, std::allocator >, std::allocator, > std::allocator > > >, std::allocator std::char_traits, std::allocator >, std::allocator std::char_traits, std::allocator > > > > > anagrams(const std::string&, const > Dictionary&, int)':|
error: could not convert 'dict->Dictionary::words.std::map<_Key, _Tp,
_Compare, _Alloc>::find [with _Key = std::basic_string, std::allocator >, _Tp =
std::vector,
std::allocator >, std::allocator, std::allocator > > >, _Compare =
std::less,
std::allocator > >, _Alloc = std::allocator
I've been stuck the last 10 hours on this and I can't take it anymore, I really don't know how to solve that issue
Thank for you help, you'd save me life
//anagrams.h
#ifndef ANAGRAMS_H_INCLUDED
#define ANAGRAMS_H_INCLUDED
#include <vector>
#include <string>
#include <map>
using namespace std;
struct Dictionary{
map<string, vector<string> > words;
};
Dictionary createdictionary(const string&);
vector<vector<string> > anagrams(const string&, const Dictionary&, int);
#endif // ANAGRAMS_H_INCLUDED
//anagrams.cpp
#include "anagrams.h"
#include <iostream>
#include <fstream>
#include <map>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
string sortString(string input);
Dictionary createdictionary(const string& filename){
Dictionary dictionary;
ifstream ifs;
ifs.open(filename.c_str());
string word;
while (ifs >> word){
string sortedWord = sortString(word);
(dictionary.words[sortedWord]).push_back(word);
}
return dictionary;
}
string sortString(string input){
vector<char> vectorWord(input.begin(), input.end());
sort(vectorWord.begin(), vectorWord.end());
string sortedInput(vectorWord.begin(), vectorWord.end());
return sortedInput;
}
vector<vector<string> > anagrams(const string& input, const Dictionary& dict, int max){
vector<vector<string> > anagrams;
size_t n = input.length();
for (int r = 0; r < max + 1; r++){
vector<bool> v(n);
fill(v.begin() + r, v.end(), true);
map<string, string> uniqueAnagram;
do {
string word;
for (size_t i = 0; i < n; ++i) {
if (!v[i]) {
word = word + input[i];
}
}
word = sortString(word);
uniqueAnagram[word] = word;
} while (next_permutation(v.begin(), v.end()));
vector<string> tempAnagram;
for(map<string, string>::iterator it = uniqueAnagram.begin(); it != uniqueAnagram.end(); it++){
if (dict.words.find(it->second)){
cout << dict.words.find(it->second)->second[0] << endl;
}
}
sort(tempAnagram.begin(), tempAnagram.end());
anagrams.push_back(tempAnagram);
}
vector<char> vectorWord(input.begin(), input.end());
sort(vectorWord.begin(), vectorWord.end());
string sortedWord(vectorWord.begin(), vectorWord.end());
// cout << (dict.words.find(sortedWord)->second)[0] << endl;
return anagrams;
}
//main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "anagrams.h"
using namespace std;
int main()
{
string filename = "C:/dictionary.txt";
Dictionary dictionary = createdictionary(filename);
vector<vector<string> > anagram = anagrams("llohe", dictionary, 5);
return 0;
}

map::find returns an iterator, not a boolean. If the key wasn't found, it returns the map's past-the-end iterator. So instead of
if (dict.words.find(it->second))
you want
if (dict.words.find(it->second) != dict.words.end())
or
if (dict.words.count(it->second) != 0)
It would be more efficient to store the iterator so you don't need to find the key twice:
auto found = dict.words.find(it->second);
if (found != dict.words.end()) {
cout << found->second[0] << endl;
}

Related

C++ - function multiple definition of `Lexer::Tokenize

so I was trying to compile a file and I got this error(mingw-64):
C:\Users\me\AppData\Local\Temp\ccfdOWKk.o:EKLexer.cpp:(.text+0x0): multiple definition of `Lexer::Tokenize(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
C:\Users\me\AppData\Local\Temp\cc9yNSun.o:EnderKnightShell.cpp:(.text+0x0): first defined here
C:\Users\me\AppData\Local\Temp\ccfdOWKk.o:EKLexer.cpp:(.text+0x36a): multiple definition of `Lexer::ProcessVariables(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
C:\Users\me\AppData\Local\Temp\cc9yNSun.o:EnderKnightShell.cpp:(.text+0x36a): first defined here
collect2.exe: error: ld returned 1 exit status
I've tried looking but there's none that seems to fit what issue I'm having(which seems to involve a function being used). I'm not much of a C++ person so I'm not sure what exactly is going on
EnderKnightShell.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "EKLexer.cpp"
#include <C:\EndorCore\EnderKnight Python Port\Full Language\C++ Compiler\Headers\PythonStatements.h>
using std::string;
using std::ifstream;
using std::vector;
using py::Python;
ifstream EnderScript("Test.ek");
int main() {
Lexer EkLexer;
Python python;
cout << "EnderKnight C++ Port Beta 1:" << endl;
for(string CodeLine; getline(EnderScript, CodeLine);){
EkLexer.Tokenize(CodeLine);
}
for (int i = 0; i < python.splitlines.size(); i++){
for (int j = 0; j < python.splitlines[i].size(); j++){
cout << python.splitlines[i][j] << endl;
}
}
}
EKLexer.cpp
class Lexer{
private:
typedef vector<map<string, string>> Tokens;
typedef vector<string> KeyWords;
Tokens tokens;
KeyWords keywords{
"echo",
"goto",
"stop",
"math",
"var",
"edef",
"end_edef",
"/*",
"if",
"end_if_state"};
public:
void Tokenize(string);
void ProcessVariables(string);
Python python;
};
void Lexer::Tokenize(string Code){
stringstream s(Code);
string temp;
while (s >> temp) {
if (temp.compare("echo") == 0) {
map<string, string> EchoMap {{"echo", Code}};
tokens.push_back(EchoMap);
}
else if (temp.compare("var") == 0) {
Lexer::ProcessVariables(Code);
}
// more code
void Lexer::ProcessVariables(string Code){
python.Split(Code, '=');
}
Thanks to templatetypedef's comment, I found that the issue was including a .cpp file. The solution is to use a header and cpp source file combo

C++ Get length of const char* [ ] in vector [duplicate]

This question already has answers here:
How to get the real and total length of char * (char array)?
(15 answers)
Closed 4 years ago.
How do I get the length of const char* arrays indexes?
The vector:
std::vector<const char*> _infoBarText;
The const char* []:
const char* text[4] = {"Current T:", "Target T:", "Time elapsed:", "Time remaining:"};
Assigning the char array to the vector:
_infoBarText.assign(text, text+4);
How can I get the length of the individual strings, like "current T", from the vector?
Raw C strings (bare char*-s) are not a perfect fit for modern C++ code.
If you change it to std::vector<std::string_view> you get your problem solved without (virtually) any overhead (given you are initializing it with literals) and as a bonus you will potentially make it safer and more usable.
See the cppreference article for details.
Example (GodBolt):
#include <string_view>
#include <vector>
#include <iostream>
int main() {
using namespace std::literals;
std::vector<std::string_view> strs = { "hello"sv, "there"sv };
for (auto&& str: strs)
std::cout << str << str.size();
return 0;
}
GodBolt Code Insight Output (note the std::operator""sv("hello", 5ul)):
#include <string_view>
#include <vector>
#include <iostream>
int main()
{
using namespace std::literals;
std::vector<std::string_view> strs = std::vector<std::basic_string_view<char, std::char_traits<char> >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > >{std::initializer_list<std::basic_string_view<char, std::char_traits<char> > >{std::operator""sv("hello", 5ul), std::operator""sv("there", 5ul)}, std::allocator<std::basic_string_view<char, std::char_traits<char> > >()};
{
std::vector<std::basic_string_view<char, std::char_traits<char> >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > > & __range = strs;
__gnu_cxx::__normal_iterator<std::basic_string_view<char, std::char_traits<char> > *, std::vector<std::basic_string_view<char, std::char_traits<char> >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > > > __begin = __range.begin();
__gnu_cxx::__normal_iterator<std::basic_string_view<char, std::char_traits<char> > *, std::vector<std::basic_string_view<char, std::char_traits<char> >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > > > __end = __range.end();
for( ; __gnu_cxx::operator!=(__begin, __end); __begin.operator++() )
{
std::basic_string_view<char, std::char_traits<char> > & str = __begin.operator*();
std::operator<<(std::cout, std::basic_string_view<char, std::char_traits<char> >(str)).operator<<(str.size());
}
}
return 0;
}
The long way:
#include <vector>
#include <cstring> // for strlen
std::vector<const char*> _infoBarText;
char const *str = _infoBarText[0]; // or any other valid index
auto len = std::strlen(str);
Short:
auto len = std::strlen(_infoBarText[0]);

Hash map error: no match for call to ‘(const __gnu_cxx::

After compiling my hash_multimap I get this large one paragraph error for my
In member function ‘size_t __gnu_cxx::hashtable<
I have never seen this huge error and I'm actually not sure what to do to fix this error due to it's abnormal size.
Any suggestions why line:
p = map1.equal_range(searchKey);
is causing this abnormaly long error? FYI- I cut the whole error and removed the middle part because once I pasted it here it was like a page long O.o
ERROR
/usr/include/c++/4.3/backward/hashtable.h: In member function ‘size_t
__gnu_cxx::hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey,
_Alloc>::_M_bkt_num_key(const _Key&, size_t) const [with _Val =
std::pair<const std::basic_string<char, std::char_traits<char>,
std::allocator<char> >, Map2*>, _Key = std::basic_string<char
...
std::char_traits<char>, std::allocator<char> > >, _Alloc =
std::allocator<Map2*>]’
hash_map2.cpp:55: instantiated from here
/usr/include/c++/4.3/backward/hashtable.h:595: error: no match for call to
‘(const __gnu_cxx::hash<std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >) (const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >&)’
Map.h file
#ifndef MAP2_H
#define MAP2_H
#include <iostream>
#include <string>
using namespace std;
class Map2 {
public:
Map2(string data1, string data2, string data3, string data4, string data5);
string pop, keyword, user, desc, id;
string get_pop() {return pop;}
string get_key() {return keyword;}
string get_user() {return user;}
string get_desc() {return desc;}
string get_id() {return id;}
void call_Values(int i);
};
Map2:: Map2(string data1, string data2, string data3, string data4, string data5) {
pop = data1;
keyword = data2;
user = data3;
desc = data4;
id = data5;
}
void Map2:: call_Values(int i) {
get_pop();
get_key();
get_user();
get_desc();
get_id();
}
#endif
hash_map2.cpp
#include <fstream>
#include <iostream>
#include "Map2.h"
#include <ext/hash_map>
#include <string>
#include <sstream>
using namespace std;
using __gnu_cxx::hash_multimap;
int nav() {
cout <<"Select from the following options : " << endl <<endl;
cout <<"Search Tweets based on Keyword (Type 1) " <<endl;
cout <<"End Program (Type 2)"<<endl<<endl;
int key =0;
cin >> key;
return key;
}
int main() {
int option = nav();
if (option == 1) {
ifstream readFile("project4.csv");
string tempPop, tempID, tempKey, tempUser, tempDesc;
string tempRead;
hash_multimap<string, Map2 *>map1;
while (readFile != NULL){
// sends to a temp variable
readFile >> tempRead;
for (int i =0; i<400; i++){
//create new object each time
Map2 *mapNode = new Map2(tempPop,tempID,tempKey,tempUser,tempDesc);
//insert each time new object is made
map1.insert(pair<string, Map2 *> (tempKey, mapNode));
} //end for
} //end while
//Navigation through multimap
//first pointer is for first one and second to last hash table value
pair<hash_multimap<string, Map2 *> :: const_iterator,
hash_multimap<string, Map2 *> :: const_iterator> p;
string searchKey = "";
cout << "Please enter the keyword value exactly so we can search the"<<
"available tweets: " <<endl;
cin >> searchKey;
p = map1.equal_range(searchKey);
}
else
return 0;
}
Issue is the fact of calling string to search. Need to convert the string to int before calling the value inside the equal_range function.

Access elements of boost tokenizer

I'm trying to assign columns of a file using boost to a std::map. I would like to assign element 0 from each line to the index and element 2 to the value. Is there a way to do this without an iterator? The addr_lookup line does not work.
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
int main()
{
std::ifstream myfile("core_info_lowbits.tab", std::ios_base::in);
std::string line;
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep(" ");
std::map<std::string, unsigned int> addr_lookup;
while ( std::getline (myfile,line) )
{
tokenizer tokens(line, sep);
//Line below does not work
addr_lookup[*tokens.begin()] = boost::lexical_cast<unsigned int> (*(tokens.begin()+2));
for (tokenizer::iterator tok_iter=tokens.begin();
tok_iter != tokens.end(); ++tok_iter)
std::cout << *tok_iter << std::endl;
}
}
You are trying to advance the iterator using +, which is not possible
Use:
tokenizer::iterator it1,it2= tokens.begin();
it1=it2;
++it2; ++it2;
addr_lookup[*it1] = boost::lexical_cast<unsigned int> (*it2);
Or simply,
tokenizer::iterator it1,it2= tokens.begin();
it1=it2;
std::advance(it2,2);
addr_lookup[*it1] = boost::lexical_cast<unsigned int> (*it2);

Permutations of letters and numbers in a phone number

For my computer science class, we need to write a program (in C++) that takes an input of characters and outputs the possible permutations of it according to the dial pad on a phone, leaving non-digit characters in place.
For example, inputing 2 outputs 2, A, B, C. Inputing 23 outputs 23, A3, B3, C3, 2D, 2E, 2F, AD, AE, AF, BD, BE, BF, etc...
The application provided for this program is finding permutations of "vanity" phone numbers for a given phone number.
Currently, the program I have written doesn't even compile, and I'm afraid the algorithm I'm using is incorrect:
#include <iostream>
#include <multimap.h>
#include <vector>
using namespace std;
// Prototypes
void initLetterMap(multimap<char,char> &lmap);
void showPermutations(const vector<string> &perms);
vector<string> getPermutations(const string &phoneNumber,const multimap<char,char> &lmap);
vector<char> getLetters(char digit, const multimap<char,char> &lmap);
// Declarations
void initLetterMap(multimap<char,char> &lmap) {
lmap.insert(pair<char,char>('1','1'));
lmap.insert(pair<char,char>('2','2'));
lmap.insert(pair<char,char>('2','A'));
lmap.insert(pair<char,char>('2','B'));
lmap.insert(pair<char,char>('2','C'));
lmap.insert(pair<char,char>('3','3'));
lmap.insert(pair<char,char>('3','D'));
lmap.insert(pair<char,char>('3','E'));
lmap.insert(pair<char,char>('3','F'));
// ...
}
vector<char> getLetters(char digit, const multimap<char,char> &lmap) {
multimap<char,char>::iterator it;
pair<multimap<char,char>::iterator,multimap<char,char>::iterator> range;
vector<char> result;
if (isdigit(digit)) {
range = lmap.equal_range(digit);
for (it=range.first;it!=range.second;++it) {
result.push_back((*it).second);
}
} else {
result.insert(result.end(),digit);
}
return result;
}
void showPermutations(vector<string> &perms) {
vector<string>::iterator it;
for (it = perms.begin(); it != perms.end(); it++) {
cout << *it << endl;
}
}
vector<string> getPermutations(const string &phoneNumber,const multimap<char,char> &lmap) {
vector<string> results;
string number = phoneNumber;
vector<char>::iterator vcit;
vector<char> letters;
unsigned int i;
for (i=0;i<phoneNumber.length();i++) {
letters = getLetters(number[i],lmap);
for (vcit=letters.begin();vcit!=letters.end();vcit++) {
number[i] = *vcit;
results.push_back(number);
}
}
return results;
}
int main() {
multimap<char,char> lmap;
initLetterMap(lmap);
string input;
cout << "Enter a phone number to get all possible vanity numbers" << endl;
cout << "> "; getline(cin,input);
showPermutations(getPermutations(input,lmap));
return 0;
}
I get a whole slew of build issues when I try to build this, and am not sure how to resolve most of them:
In file included from /usr/include/c++/4.0.0/backward/multimap.h:59,
from phone02.cpp:18:
/usr/include/c++/4.0.0/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
/usr/include/c++/4.0.0/bits/stl_pair.h: In constructor 'std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U1 = std::_Rb_tree_const_iterator<std::pair<const char, char> >, _U2 = std::_Rb_tree_const_iterator<std::pair<const char, char> >, _T1 = std::_Rb_tree_iterator<std::pair<const char, char> >, _T2 = std::_Rb_tree_iterator<std::pair<const char, char> >]':
phone02.cpp:75: instantiated from here
/usr/include/c++/4.0.0/bits/stl_pair.h:90: error: no matching function for call to 'std::_Rb_tree_iterator<std::pair<const char, char> >::_Rb_tree_iterator(const std::_Rb_tree_const_iterator<std::pair<const char, char> >&)'
/usr/include/c++/4.0.0/bits/stl_tree.h:167: note: candidates are: std::_Rb_tree_iterator<_Tp>::_Rb_tree_iterator(std::_Rb_tree_node<_Tp>*) [with _Tp = std::pair<const char, char>]
/usr/include/c++/4.0.0/bits/stl_tree.h:164: note: std::_Rb_tree_iterator<_Tp>::_Rb_tree_iterator() [with _Tp = std::pair<const char, char>]
/usr/include/c++/4.0.0/bits/stl_tree.h:152: note: std::_Rb_tree_iterator<std::pair<const char, char> >::_Rb_tree_iterator(const std::_Rb_tree_iterator<std::pair<const char, char> >&)
/usr/include/c++/4.0.0/bits/stl_pair.h:90: error: no matching function for call to 'std::_Rb_tree_iterator<std::pair<const char, char> >::_Rb_tree_iterator(const std::_Rb_tree_const_iterator<std::pair<const char, char> >&)'
/usr/include/c++/4.0.0/bits/stl_tree.h:167: note: candidates are: std::_Rb_tree_iterator<_Tp>::_Rb_tree_iterator(std::_Rb_tree_node<_Tp>*) [with _Tp = std::pair<const char, char>]
/usr/include/c++/4.0.0/bits/stl_tree.h:164: note: std::_Rb_tree_iterator<_Tp>::_Rb_tree_iterator() [with _Tp = std::pair<const char, char>]
/usr/include/c++/4.0.0/bits/stl_tree.h:152: note: std::_Rb_tree_iterator<std::pair<const char, char> >::_Rb_tree_iterator(const std::_Rb_tree_iterator<std::pair<const char, char> >&)
make: *** [phone02.o] Error 1
The line numbers are a bit off, but the important ones that I can see are the two about no matching function for call to 'std::_Rb_tree_iterator<std::pair<const char, char> >::_Rb_tree_iterator(const std::_Rb_tree_const_iterator<std::pair<const char, char> >&)'
Besides the errors, I also believe I am heading in the wrong direction with my algorithm.
So I have 2 questions here:
Why am I getting these build errors, and how do I fix them?
How would you suggest going about solving this problem? Am I on the right track or no?
For question #2, I would prefer to not get solutions, just advice or pointers in the right direction.
Thanks!
PS: I am building this on Mac OS X 10.5.8 with gcc, using QtCreator 1.2.1
UPDATE:
I have successfully compiled a solution program. I will post the source code to those who are curious.
#include <iostream>
#include <map>
#include <vector>
#include <string>
using namespace std;
void initLetterMap(map<char,string> &lmap);
vector<string> getMapped(const string &phoneNumber, map<char,string> &lmap);
vector<string> getPermutations(vector<string> number);
unsigned long int countPermutations(vector<string> number);
void initLetterMap(map<char,string> &lmap) {
lmap['0'] = "0";
lmap['1'] = "1";
lmap['2'] = "2ABC";
lmap['3'] = "3DEF";
lmap['4'] = "4GHI";
lmap['5'] = "5JKL";
lmap['6'] = "6MNO";
lmap['7'] = "7PQRS";
lmap['8'] = "8TUV";
lmap['9'] = "9WXYZ";
}
unsigned long int countPermutations(vector<string> number) {
long int fold = 1;
int vals = 0;
vector<string>::iterator it;
for (it=number.begin();it!=number.end();it++) {
vals = (*it).length();
fold *= vals;
}
return fold;
}
vector<string> getMapped(const string &phoneNumber, map<char,string> &lmap) {
unsigned int i;
vector<string> out;
char digit;
string temp;
for (i=0;i<phoneNumber.length();i++) {
digit = phoneNumber.at(i);
if (isdigit(digit)) {
out.push_back(lmap[digit]);
} else {
temp = string(1,digit);
out.push_back(temp);
}
}
return out;
}
vector<string> getPermutations(vector<string> number) {
vector<string> results;
unsigned long int i,j,k;
unsigned long int perms = countPermutations(number);
vector<string>::reverse_iterator numit;
string temp,temp2;
vector<int> state = vector<int>(number.size(), 0);
vector<int>::reverse_iterator stateit;
for (i=0;i<perms;i++) {
j=i;
temp = "";
for (stateit=state.rbegin(), numit=number.rbegin();stateit!=state.rend();stateit++, numit++) {
*stateit = j % (*numit).length();
j /= (*numit).length();
temp.insert(temp.begin(),(*numit)[*stateit]);
}
results.push_back(temp);
}
return results;
}
int main() {
map<char,string> lettermap;
initLetterMap(lettermap);
string input;
cout << "> "; getline(cin,input);
vector<string> perms = getPermutations(getMapped(input,lettermap));
vector<string>::iterator it;
for (it=perms.begin();it!=perms.end();it++) {
cout << *it << endl;
}
}
The code is probably more complicated than it has to be, but my goal was to just get it to work. It seems to run fairly quickly for 10 digit phone numbers, so I guess it's not too bad.
Thanks to Jacob and ShreevatsaR for getting me pointed in the right direction!
How about the following:
#include <cstddef>
#include <iostream>
#include <iterator>
#include <string>
#include <algorithm>
template <typename Iterator>
bool next_combination(const Iterator first, Iterator k, const Iterator last);
int main()
{
std::string phone_number = "23";
std::string number[] = {
"0", "1", "2abc", "3def", "4ghi",
"5jkl","6mno", "7pqrs", "8tuv","9wxyz"
};
std::string tmp_set;
std::string set;
for(std::size_t i = 0; i < phone_number.size(); ++i)
{
tmp_set += number[static_cast<std::size_t>(phone_number[i] - '0')];
}
std::sort(tmp_set.begin(),tmp_set.end());
std::unique_copy(tmp_set.begin(),
tmp_set.end(),
std::back_inserter(set));
std::string current_set;
current_set.reserve(phone_number.size());
do
{
std::copy(set.begin(),
set.begin() + phone_number.size(),
std::back_inserter(current_set));
do
{
std::cout << current_set << std::endl;
}
while (std::next_permutation(current_set.begin(),current_set.end()));
current_set.clear();
}
while(next_combination(set.begin(),
set.begin() + phone_number.size(),
set.end()));
return 0;
}
template <typename Iterator>
inline bool next_combination(const Iterator first, Iterator k, const Iterator last)
{
/* Credits: Thomas Draper */
if ((first == last) || (first == k) || (last == k))
return false;
Iterator itr1 = first;
Iterator itr2 = last;
++itr1;
if (last == itr1)
return false;
itr1 = last;
--itr1;
itr1 = k;
--itr2;
while (first != itr1)
{
if (*--itr1 < *itr2)
{
Iterator j = k;
while (!(*itr1 < *j)) ++j;
std::iter_swap(itr1,j);
++itr1;
++j;
itr2 = k;
std::rotate(itr1,j,last);
while (last != j)
{
++j;
++itr2;
}
std::rotate(k,itr2,last);
return true;
}
}
std::rotate(first,k,last);
return false;
}
Well if you don't want a solution, I would implement it like this:
Use a vector V with each element drawn from a string. E.g. if it's 23, then your vector V, would have two vectors each containing 2ABC and 3DEF.
Iterate each digit like a counter through the associated string. Move right-to-left and when each digit overflows increment the one to the left, and reset, etc.
Display the counter at every iteration to obtain your "number".
Hint to compile errors:
there is no file called <multimap.h> in STL. it should be <map>
The problem is with getLetters function. multimap lmap has been passed by const reference. Hence, equal_range API on lmap would return pair of const_iterator not just iterator.
Below code demonstrate how to do it in simple steps(Recursively):
1.) Create vector of strings, and push strings which represents "possible characters resulting from that keypress" (0-key to 9-key).
2.) Since each keypress will serve to add ONLY one char to the resultant string, append only one character at a time and call the function recursively for the next keypress. Do it for each possible char at that keypress.
Demo:
void getCombination(vector<string> &combinations, string current, const string &A, int idx, const vector<string> &keyset){
if(idx >= A.size()) {
combinations.push_back(current);
return;
}
int key = (A[idx] - '0');
int len = keyset[key].length();
for( int i = 0; i < len; i++ ){
current.push_back(keyset[key][i]); //pick at once one char corresp. to that keypress
getCombination(combinations, current, A, idx+1, keyset);
current.pop_back();
}
}
vector<string> letterCombinations(string A) {
vector<string> combinations;
vector<string> keyset{"0", "1", "2abc", "3def", "4ghi", "5jkl", "6mno", "7pqrs", "8tuv", "9wxyz"};
getCombination(combinations, std::string({}), A, 0, keyset);
return combinations;
}
int main() {
vector<string> combinations = letterCombinations("23");
for(string word : combinations){
cout << word << ", ";
}
return 0;
}
Gives Output :
23, 2d, 2e, 2f, a3, ad, ae, af, b3, bd, be, bf, c3, cd, ce, cf,