inverted index node addword - c++

I'm new to C++. I'm trying to make inverted index but I can't understand the cord. I want to count the frequency of the word. Can you explain this code and how to count the frequency of the word? Please help me to solve this problem.
class node{
public:
node() {
clear();
}
node(char z) {
clear();
}
~node() {
for (int x = 0; x < MAX_NODES; x++) {
if (next[x]) {
delete next[x];
}
}
}
void clear() {
for (int x = 0; x < MAX_NODES; x++){
next[x] = 0;
isWord = false;
}
}
bool isWord;
int count;//frq
std::vector<std::string> files;
node* next[MAX_NODES];
map<string, int> counts;
};
class index {
public:
void add(std::string s, std::string fileName) {
std::transform(s.begin(), s.end(), s.begin(), tolower);
std::string h;
int freq=0;
for (std::string::iterator i = s.begin(); i != s.end(); i++) {
if (*i == 32) {
pushFileName(addWord(h), fileName);
h.clear();
continue;
}
h.append(1, *i);
}
if (h.length()){
pushFileName(addWord(h), fileName);
}
}
void findWord(std::string s, map<string, int> counts) {
std::vector<std::string> v = find(s);
if (!v.size()) {
std::cout <<"'"<< s + "' is not found!\n";
return;
}
std::cout << "'" << s << "' is found in:\n";
for (std::vector<std::string>::iterator i = v.begin(); i != v.end(); i++) {
std::cout << *i << "\n";
}
std::cout << "frequency is : ";
}
private:
void pushFileName(node* n, std::string fn) {
std::vector<std::string>::iterator i = std::find(n->files.begin(), n->files.end(), fn);
if (i == n->files.end()){
n->files.push_back(fn);
n->count;
}
}
const std::vector<std::string>& find(std::string s) {
size_t idx;
std::transform(s.begin(), s.end(), s.begin(), tolower);
node* rt = &root;
for (std::string::iterator i = s.begin(); i != s.end(); i++) {
idx = _CHARS.find(*i);
if (idx < MAX_NODES) {
if (!rt->next[idx]){
return std::vector<std::string>();
}
rt = rt->next[idx];
}
}
if (rt->isWord) return rt->files;
return std::vector<std::string>();
}
node* addWord(std::string s) {
size_t idx;
node *rt = &root, *n;
for (std::string::iterator i = s.begin(); i != s.end(); i++) {
idx = _CHARS.find(*i);
if (idx < MAX_NODES) {
n = rt->next[idx];
if (n){
rt = n;
continue;
}
n = new node(*i);
rt->next[idx] = n;
rt = n;
}
}
rt->isWord = true;
rt->count++;
return rt;
}
node root;
};
class index {
public:
void add(std::string s, std::string fileName) {
std::transform(s.begin(), s.end(), s.begin(), tolower);
std::string h;
int freq=0;
for (std::string::iterator i = s.begin(); i != s.end(); i++) {
if (*i == 32) {
pushFileName(addWord(h), fileName);
h.clear();
continue;
}
h.append(1, *i);
}
if (h.length()){
pushFileName(addWord(h), fileName);
}
}
void findWord(std::string s, map<string, int> mFilesFreq) {
std::vector<std::string> v = find(s);
if (!v.size()) {
std::cout <<"'"<< s + "' is not found!\n";
return;
}
std::cout << "'" << s << "' is found in:\n";
for (std::vector<std::string>::iterator i = v.begin(); i != v.end(); i++) {
std::cout << *i << "\n";
}
std::cout << "frequency is : ";
}

If you are counting the number of times add was called for a given word, you probably want to replace rt->isWord = true; with rt->count++; and in your struct node replace bool isWord with int count.

Related

Counting vowels in a book

I'm trying to count vowels in a book "War and Peace" by Lev Tolstoi with 4 different methods:
Using Count_if/find
Using Count_if/for
for/find
4.for/for
The programm also calculates time it takes for every method to get the number of vowels. I'm using a russian version of the book as a reference so all the vowels are taken from cyrillic alphabet. Here is the code:
#include <chrono>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <Windows.h>
#include <string>
#include <fstream>
#include <iterator>
class Timer
{
private:
using clock_t = std::chrono::high_resolution_clock;
using second_t = std::chrono::duration<double, std::ratio<1> >;
std::string m_name;
std::chrono::time_point<clock_t> m_beg;
double elapsed() const
{
return std::chrono::duration_cast<second_t>(clock_t::now()
- m_beg).count();
}
public:
Timer() : m_beg(clock_t::now()) { }
Timer(std::string name) : m_name(name), m_beg(clock_t::now()) { }
void start(std::string name) {
m_name = name;
m_beg = clock_t::now();
}
void print() const {
std::cout << m_name << ":\t" << elapsed() * 1000 << " ms" << '\n';
}
};
const std::string vowels = "аеёиоуыэюяАЕЁИОУЫЭЮЯ";
bool containVowel(const std::string& s, const char& a)
{
for (size_t i = 0; i < s.size(); i++)
{
if (a == s[i])
{
return true;
}
return false;
}
}
void ForFor(std::ifstream& ifs, std::string& ww)
{
size_t count = 0;
Timer t1("for for");
while (ifs >> ww)
{
for (size_t i = 0; i < ww.size(); i++)
{
if (containVowel(vowels, ww[i]))
{
count++;
}
}
}
t1.print();
std::cout << count << std::endl;
}
//bool findVowel(char c)
//{
// return vowels.find(c) != std::string::npos;
//}
void CountIfFind(std::ifstream& ifs, std::string& ww) // not sure what is the way to cout count here...
{
Timer t("count_if/find");
while (ifs >> ww)
{
size_t count = std::count_if(ww.begin(), ww.end(), [&](char c) {return vowels.find(c) != std::string::npos; });
}
t.print();
}
void CountIfFor(std::ifstream& ifs, std::string& ww) // not sure what is the way to cout count here...
{
Timer t("count_if/for");
while (ifs >> ww)
{
for (size_t i = 0; i < vowels.size(); i++)
{
auto count = std::count_if(ww.begin(), ww.end(), [&](char c) {return c == vowels[i]; });
}
}
t.print();
}
void ForFind(std::ifstream& ifs, std::string& ww)
{
char c{};
int count = 0;
Timer t("for/find");
while (ifs >> ww)
{
for (size_t i = 0; i < ww.size(); i++)
{
if (vowels.find(c) != std::string::npos)
{
count++;
}
}
}
t.print();
std::cout << count << std::endl;
}
int main()
{
setlocale(LC_ALL, "ru");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
std::ifstream ifs;
ifs.open("Толстой Лев. Война и мир. Книга 1 - royallib.ru.txt");
if (ifs.is_open())
{
std::string ww;
ForFor(ifs, ww);
CountIfFind(ifs,ww);
CountIfFor(ifs,ww);
ForFind(ifs, ww);
ifs.close();
}
else
{
std::cout << "Can't open the file!" << std::endl;
}
}
Function ForFor works just fine but 3 other don't work (they don't show count but show time though). I'm guessing there is a problem with parsing the file, though I'm not sure because of my inexperience.
Will be hoping for your help!) Thank you all, in advance.
EDIT:Ok so now I'm sure the issue is in while(ifs>>ww). ForFor was the first function in the main so it worked, I tried commenting it and the next one CountIfFind started working. But when I delete while in every function and use it in main like: while(ifs>>ww) {ForFor(ww); CountIfFind(ww); CountIfFor(ww); ForFind(ww);} It doesn't work at all... How do I fix it?
So here is the correct way to do it:
class Timer
{
private:
using clock_t = std::chrono::high_resolution_clock;
using second_t = std::chrono::duration<double, std::ratio<1> >;
std::string m_name;
std::chrono::time_point<clock_t> m_beg;
double elapsed() const
{
return std::chrono::duration_cast<second_t>(clock_t::now()
- m_beg).count();
}
public:
Timer() : m_beg(clock_t::now()) { }
Timer(std::string name) : m_name(name), m_beg(clock_t::now()) { }
void start(std::string name) {
m_name = name;
m_beg = clock_t::now();
}
void print() const {
std::cout << m_name << ":\t" << elapsed() * 1000 << " ms" << '\n';
}
};
const std::string vowels = "аеёиоуыэюяАЕЁИОУЫЭЮЯ";
size_t ForFor(std::string& ww)
{
size_t count = 0;
Timer t1("for for");
for(const auto& ch : ww)
{
for (const auto& vow : vowels)
{
if (ch == vow)
{
++count;
break;
}
}
}
t1.print();
return count;
}
size_t CountIfFind(std::string& ww)
{
Timer t("count_if/find");
size_t count = std::count_if(ww.begin(), ww.end(), [ & ](char c) {return vowels.find(c) != std::string::npos; });
t.print();
return count;
}
size_t CountIfFor(std::string& ww)
{
Timer t("count_if/for");
size_t count = std::count_if(ww.begin(), ww.end(), [&](const char& c1)
{
for (const auto& ch : vowels)
{
if (c1 == ch)
{
return true;
}
}
return false;
});
t.print();
return count;
}
size_t ForFind(std::string& ww)
{
char c{};
size_t count = 0;
Timer t("for/find");
for (const auto& ch :ww)
{
if (vowels.find(ch) != std::string::npos)
{
++count;
}
}
t.print();
return count;
}
int main()
{SetConsoleCP(1251);
SetConsoleOutputCP(1251);
std::ifstream file("Толстой Лев. Война и мир. Книга 1 - royallib.ru.txt");
file.seekg(0, std::ios::end);
size_t size = file.tellg();
file.seekg(0);
std::string s(size, ' ');
file.read(&s[0], size);
std::cout << CountIfFind(s) << std::endl;
std::cout << ForFor(s) << std::endl;
std::cout << ForFind(s) << std::endl;
std::cout << CountIfFor(s) << std:: endl;
}

Overloading Operator and vector STL problems

I have a task: Implementing 60.000 English words from EnglishWords.txt, then Sorting it and Searching.
I have done the Sorting and Linear Search using custom MergeSort and find_if STL but when i tried to use other vector STL like upper_bound, lower_bound, binary_search it cause some problems below:
If the lower_bound function run, it does not return the same "Index" with "searchmanually" function.
Can not use "MatchString" (My overload operator) for lower_bound and binary_search ST or other vector STL and return C2672 and C2893 code.
Also, can some one give me some advices on "sorting" base on alphabetical.
My full code is on https://onlinegdb.com/l4pfS9pYJ, please click on "Fork this" to edit the code.
Some additional requirements and notions.
I'm new to OOP so show me some advices to improve my code writing skills.
Do not use STL sort(), write your own.
Must put all sorting, searching and working function to FastDictionary.
Below is my overload operator and the function that has problem.
void searchmanually(vector<Dictionary> list, string value)
{
vector<Dictionary>::iterator it;
it = find_if(list.begin(), list.end(), FastDictionary::MatchString(value));
if (it != list.end())
{
auto idx = distance(list.begin(), it);
cout << "Index = " << idx << endl;
}
else
{
cout << "Can not find the value !." << endl;
}
}
void binary_search_find_index(vector<Dictionary> list, string value)
{
vector<Dictionary>::iterator it1;
it1 = lower_bound(list.begin(), list.end(), FastDictionary::MatchString(value));
if (it1 != list.end())
{
auto idx1 = distance(list.begin(), it1);
cout << "Index = " << idx1 << endl;
}
else
{
cout << "Can not find the value !." << endl;
}
}
struct MatchString
{
private:
const std::string& s_;
public:
MatchString(const std::string& s) : s_(s) {}
bool operator()(const Dictionary& obj) const
{
return obj._word == s_;
}
friend bool operator<(const Dictionary& obj, const MatchString &str)
{
return obj._word < str.s_;
}
friend bool operator>(const Dictionary& obj, const MatchString &str)
{
return obj._word > str.s_;
}
};
Because i think that my "errors" are kinda chained so i try to described the error as much detail as possible.
Many thanks.
First The problem is that at your given link you have named your input file incorrectly. Note carefully your input file name in the main.cpp file is EnglishWord.txt while your actual input file name is EnglistWord.txt. Note the t at the end of the file name.
Second you should replace while (reader >> word) with:
while (std::getline(reader, word))
as i have done in the below correct example:
#include<iostream>
#include<string>
#include<vector>
#include<fstream>
#include<sstream>
#include<algorithm>
using namespace std;
class Dictionary
{
public:
string _word;
public:
string word() { return _word; }
void getword(string value) { _word=value; }
string display()
{
stringstream writer;
writer << _word << " ";
return writer.str();
}
};
class FastDictionary : public Dictionary
{
public:
void merge(std::vector<Dictionary>& list, int start, int middle, int end)
{
std::vector<Dictionary> left_vector(middle - start + 1);
std::vector<Dictionary> right_vector(end - middle);
for (int i = 0; i < left_vector.size(); ++i)
left_vector[i] = list[start + i];
for (int i = 0; i < right_vector.size(); ++i)
right_vector[i] = list[middle + 1 + i];
int left_value = 0, right_value = 0;
int currentIndex = start;
while (left_value < left_vector.size() && right_value < right_vector.size()) {
if (left_vector[left_value]._word.size() <= right_vector[right_value]._word.size()) {
list[currentIndex] = left_vector[left_value];
left_value++;
}
else {
list[currentIndex] = right_vector[right_value];
right_value++;
}
currentIndex++;
}
while (left_value < left_vector.size()) list[currentIndex++] = left_vector[left_value++];
while (right_value < right_vector.size()) list[currentIndex++] = right_vector[right_value++];
}
void mergeSort(std::vector<Dictionary>& list, int start, int end) {
if (start < end) {
int middle = (start + end) / 2;
mergeSort(list, start, middle);
mergeSort(list, middle + 1, end);
merge(list, start, middle, end);
}
}
public:
void searchmanually(vector<Dictionary> list, string value)
{
vector<Dictionary>::iterator it;
it = find_if(list.begin(), list.end(), FastDictionary::MatchString(value));
if (it != list.end())
{
auto idx = distance(list.begin(), it);
cout << "Index = " << idx << endl;
}
else
{
cout << "Can not find the value !." << endl;
}
}
void binary_search_find_index(vector<Dictionary> list, string value)
{
vector<Dictionary>::iterator it1;
it1 = lower_bound(list.begin(), list.end(), FastDictionary::MatchString(value));
if (it1 != list.end())
{
auto idx1 = distance(list.begin(), it1);
cout << "Index = " << idx1 << endl;
}
else
{
cout << "Can not find the value !." << endl;
}
}
struct MatchString
{
private:
const std::string& s_;
public:
MatchString(const std::string& s) : s_(s) {}
bool operator()(const Dictionary& obj) const
{
return obj._word == s_;
}
friend bool operator<(const Dictionary& obj, const MatchString &str)
{
return obj._word < str.s_;
}
friend bool operator>(const Dictionary& obj, const MatchString &str)
{
return obj._word > str.s_;
}
};
};
void readfile(vector<Dictionary>& list)
{
ifstream reader("EnglishWord.txt");
string word;
//reader.open(, ios::in);//no need for this
if(reader)//check the state
{
while (std::getline(reader, word))//use getline
{
std::cout<<word<<std::endl;
Dictionary newList;
newList.getword(word);
list.push_back(newList);
}
}
else
{
std::cout<<"file cannot be opened"<<std::endl;
}
}
void displayvector(vector<Dictionary>& list)
{
unsigned int size = list.size();
for (int i = 0; i < size; i++)
{
cout << list[i].display();
}
}
int main()
{
vector<Dictionary>list;
FastDictionary fd;
readfile(list);
fd.mergeSort(list, 0, list.size() - 1);
displayvector(list);
cout << endl;
cout << endl;
fd.binary_search_find_index(list, "decidedly");
cout << endl;
fd.searchmanually(list, "decidedly");
cout << endl;
return 0;
}
The output of this corrected/modified example can be seen here.

VS Code not showing local variables at all

I am using VS code for coding in C++. The problem arises when I try to debug a code and set a breakpoint. The local variables pane doesn't show any variables at all. Sometimes it does show some variables but not all of them.
Also when I try to close the debugger and click on the stop button, it does not stop. It requires me to click on it multiple times, which I think means, that multiple debuggers are opened or something like that.
To reproduce this problem, save this text as input_static.txt.
T1 1 2 5
T2 2 4
T3 2 3
T4 1 2 4
T5 1 3
T6 2 3
T7 1 3
T8 1 2 3 5
T9 1 2 3
And debug the following code by setting a breakpoint at line number 201.
#include <bits/stdc++.h>
using namespace std;
ifstream fin;
ofstream fout;
typedef struct fptnode
{
int item, count;
fptnode *next;
map<int, fptnode *> children;
fptnode *parent;
fptnode(int item, int count, fptnode *parent)
{
this->item = item;
this->count = count;
this->parent = parent;
}
} * FPTPTR;
map<int, int> frequency;
bool isMoreFrequent(int a, int b)
{
if (frequency[a] == frequency[b])
return a < b;
return frequency[a] > frequency[b];
}
class FPTREE
{
public:
FPTPTR root;
map<int, list<FPTPTR>> headers;
// map<int, int> frequency;
FPTREE()
{
this->root = new fptnode(-1, 0, NULL);
}
// class isMoreFrequent
// {
// public:
// FPTREE *T;
// isMoreFrequent(FPTREE *T)
// {
// this->T = T;
// }
// bool operator()(int item1, int item2)
// {
// return T->frequency[item1] > T->frequency[item2];
// }
// };
FPTPTR getNewNode(int item, int count, fptnode *parent)
{
FPTPTR T = new fptnode(item, count, parent);
this->headers[item].push_back(T);
return T;
}
void add(vector<int> &transaction)
{
stack<int> S;
std::sort(transaction.begin(), transaction.end(), isMoreFrequent);
for (int i = transaction.size() - 1; i >= 0; i--)
{
S.push(transaction[i]);
}
insert(root, S);
}
int insert(FPTPTR T, stack<int> &S)
{
T->count++;
if (S.empty())
return 0;
int top = S.top();
S.pop();
if (T->children[top] == NULL)
{
T->children[top] = getNewNode(top, 0, T);
}
insert(T->children[top], S);
return 0;
}
void printPreOrder(ofstream &fout)
{
printPreOrder(fout, this->root);
}
void printPreOrder(ofstream &fout, FPTPTR T)
{
if (T)
{
fout << "[" << T->item << ", " << T->count << "]" << ' ';
for (auto p : T->children)
{
printPreOrder(fout, p.second);
}
}
}
void printTree(ofstream &fout)
{
printTree(fout, this->root);
}
void printTree(ofstream &fout, FPTPTR T, int level = 0)
{
if (T)
{
for (int i = 0; i < level; i++)
fout << "\t";
fout << "[" << T->item << ", " << T->count << "]" << endl;
for (auto p : T->children)
{
printTree(fout, p.second, level + 1);
}
}
}
void generatePath(FPTPTR node, vector<int> &path)
{
if (node && node->item >= 0)
{
path.push_back(node->item);
generatePath(node->parent, path);
}
}
FPTREE newTree(int item)
{
list<FPTPTR> &nodes = this->headers[item];
vector<int> patternBase;
FPTREE f;
for (auto node : nodes)
{
patternBase.clear();
generatePath(node->parent, patternBase);
for (int j = 0; j < node->count; ++j)
f.add(patternBase);
}
return f;
}
int clear()
{
return this->clear(this->root);
}
int clear(FPTPTR T)
{
for (auto p : T->children)
{
clear(p.second);
}
return 0;
}
bool isEmpty()
{
// return this->root->count == 0;
return this->root->children.empty();
}
} F;
ofstream tempout;
map<set<int>, int> mine(FPTREE f, int r = -1)
{
map<set<int>, int> M;
if (!f.isEmpty())
{
// if (f.root->children.empty())
// M[{}] += f.root->count;
tempout << "\nOn removing " << r << ":\n";
f.printTree(tempout);
for (auto p : frequency)
{
FPTREE subF = f.newTree(p.first);
map<set<int>, int> m = mine(subF, p.first);
for (auto q : m)
{
auto itemset = q.first;
itemset.insert(p.first);
M[itemset] += q.second;
}
subF.clear();
}
return M;
}
// tempout << "\nTerminated.\n";
return {};
}
int main(int argc, char const *argv[])
{
fin.open("input_static.txt");
fout.open("output_static.txt");
tempout.open("temp");
string str, s;
while (fin >> s)
{
if (s.front() != 'T')
{
frequency[stoi(s)]++;
}
}
vector<int> transaction;
stringstream st;
fin.clear();
fin.seekg(0);
while (std::getline(fin, str))
{
st.clear();
st.str(str);
transaction.clear();
while (st >> s)
{
if (s.front() != 'T')
{
transaction.push_back(stoi(s));
}
}
F.add(transaction);
}
fout << "Preorder:\n";
F.printPreOrder(fout);
fout << endl
<< endl;
fout << "Tree in directory form:\n";
F.printTree(fout);
// printPrefixes(5);
map<set<int>, int> frequentItemsets = mine(F);
fout << endl;
for (auto p : frequentItemsets)
{
fout << "Frequency=" << p.second << "\t";
for (int item : p.first)
{
fout << item << ' ';
}
fout << endl;
}
// for (int i = 1; i <= 5; ++i)
// {
// fout << i << ":\n";
// FPTREE f = F.newTree(i);
// f.printTree();
// }
// F.newTree(1).newTree(2).printTree(fout);
return 0;
}
If it helps this is a program to generate and mine an FP-tree to find frequent itemsets in a transactional database.

Printing from Trie

I have built a trie in C++ designed to hold words of sentences. Each sentence will have a weight which determines the order in which they should be output. I have several recursive functions that call other recursive functions, and the dilemma I am facing is that I want to print my list only once.
Basically my get function calls the printFromNode function which creates the vector of pairs p that I want to sort and print. If someone could point me in the right direction in how to do that it would be much appreciated.
Code:
Trie.cpp:
//#include "Trie.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <sstream>
#include <stack>
using namespace std;
class Node
{
private:
string word = "";
bool endOfSentence = false;
int weight = -1;
public:
vector<Node> children = {};
Node() {
this->setWord("");
}
Node(string s){
this->setWord(s);
}
string getWord(){
return this->word;
}
void setWord(string s) {
this->word = s;
}
void setEOS(){
this->endOfSentence = true;
}
void setWeight(int weight){
this->weight = weight;
}
int getWeight() {
return this->weight;
}
};
class Trie
{
public:
Node root;
void add(vector<string> phrase, int weight, Node* n){
Node* current = n;
int w = weight;
int found = -1;
for (int i = 0; i < current->children.size(); i++) {
if (phrase[0] == current->children[i].getWord()) {
found = i;
}
}
if (found > -1) {
current = &current->children[found];
phrase.erase(phrase.begin());
add(phrase, w, current);
}
else {
addPhrase(phrase, w, current);
}
}
void addPhrase(vector<string> phrase, int weight, Node* n) {
Node* current = n;
for (int i = 0; i < phrase.size(); i++) {
Node temp = *new Node(phrase[i]);
current->children.push_back(temp);
current = &current->children.back();
if (i == phrase.size() - 1) {
current->setEOS();
current->setWeight(weight);
}
}
}
void get(vector<string> search) {
Node* current = &this->root;
get(search, current);
}
void get(vector<string> search, Node* n) {
Node* current = n;
int found = -1;
//test search size
if (search.size() == 0) {
cout << "Please enter a valid search" << endl;
}
for (int i = 0; i < current->children.size(); i++) {
if (search[0] == current->children[i].getWord()) {
found = i;
}
}
if (found > -1 && search.size() == 1) {
current = &current->children[found];
printFromNode(*current);
maxNode(*current);
}
else if (found > -1 && search.size() != 1) {
current = &current->children[found];
search.erase(search.begin());
get(search, current);
}
else {
cout << "Not Found" << endl;
}
}
void printOutput(vector<pair<int,string>> p){
sort(p.begin(), p.end());
cout << p.size() << endl;
for (int i = 0; i < p.size(); i++) {
cout << p[i].second << " " << endl;
}
}
void printFromNode(Node n) {
vector<string> phrase = {};
vector <pair < int, string>> final = {};
printFromNode(n,phrase,final);
}
void printFromNode(Node n, vector<string> &v, vector<pair<int,string>> &p) {
string output;
if (n.getWord() == "") {
return;
}
for (int i = 0; i < n.children.size(); i++) {
if (n.children[i].getWeight() > 0) {
for (int i = 0; i < v.size(); i++)
{
output.append(v[i] + " ");
}
output.append(n.children[i].getWord());
p.push_back(make_pair(n.children[i].getWeight(), output));
}
v.push_back(n.children[i].getWord());
printFromNode(n.children[i], v, p);
v.pop_back();
sort(p.begin(), p.end());
}
return;
}
void maxNode(Node n) {
int max = 0;
int index = 0;
int temp = 0;
for (int i = 0; i < n.children.size(); i++) {
temp = n.children[i].children.size();
if (temp > max) {
max = temp;
index = i;
}
}
cout << n.children[index].getWord() << " " << max << endl;
}
};
Main.cpp:
#include "Trie.cpp"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char* argv[]) {
// Initialize trie up here
Trie myTrie = *new Trie();
// parse input lines until I find newline
for(string line; getline(cin, line) && line.compare(""); ) {
stringstream ss(line);
string string_weight;
ss >> string_weight;
int weight = stoi(string_weight);
// I am just going to put these words into a vector
// you probably want to put them in your trie
vector<string> phrase = {};
for(string word; ss >> word;) {
phrase.push_back(word);
}
myTrie.add(phrase, weight, &myTrie.root);
vector<string> ans = {};
}
// parse query line
string query;
getline(cin, query);
stringstream ss(query);
vector<string> search = {};
for (string query; ss >> query;) {
search.push_back(query);
}
myTrie.get(search);
return 0;
}
You can remove recursive methods, and doing something like the following:
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <set>
class Node
{
public:
bool endOfSentence = false;
std::set<int> weights;
std::map<std::string, Node> children;
Node() = default;
const Node* get(const std::string& word) const
{
auto it = children.find(word);
if (it == children.end()) {
return nullptr;
}
return &it->second;
}
auto find_by_weight(int weight) const
{
return std::find_if(children.begin(),
children.end(),
[=](const auto& p){ return p.second.weights.count(weight);});
}
};
class Trie
{
Node root;
public:
void add(int weight, const std::vector<std::string>& phrase)
{
Node* node = &root;
for (const auto& word : phrase) {
node->weights.insert(weight);
node = &node->children[word];
}
node->weights.insert(weight);
node->endOfSentence = true;
}
bool contains(const std::vector<std::string>& phrase) const
{
const Node* node = &root;
for (const auto& word : phrase) {
node = node->get(word);
if (node == nullptr) {
return false;
}
}
return node->endOfSentence;
}
void print(int weight) const
{
const Node* node = &root;
const char* sep = "";
while (node) {
const auto it = node->find_by_weight(weight);
if (it == node->children.end()) {
break;
}
std::cout << sep << it->first;
sep = " ";
node = &it->second;
}
std::cout << std::endl;
}
void print_all() const
{
for (int i : root.weights) {
print(i);
}
}
};
And usage/Test:
int main(int argc, char* argv[]) {
const std::vector<std::vector<std::string>> sentences = {
{"My", "name", "is", "John"},
{"My", "house", "is", "small"},
{"Hello", "world"},
{"Hello", "world", "!"}
};
Trie trie;
int i = 0;
for (const auto& sentence : sentences) {
trie.add(i, sentence);
++i;
}
const std::vector<std::vector<std::string>> queries = {
{"My", "name", "is", "John"},
{"My", "house"},
{"Hello", "world"}
};
for (const auto& query : queries) {
std::cout << trie.contains(query) << std::endl;
}
trie.print_all();
}
Demo

FileManager isn't working properly

I've been following some tutorials for allegro 5 and Im trying to load a tile map and I keep getting a vector subscript out of range error. I've been trying for so long to get this fixed but I cannot figure it out. The filemanager is supposed to read from a map.txt then go through layer.cpp then actually make the map.
EDIT:
It stops after the 5th loop of contents[i][j]
FileManager.CPP
#include "FileManager.h"
FileManager::FileManager()
{
identifierFound = false;
}
FileManager::~FileManager()
{
}
void FileManager::LoadContent(const char *filename, std::vector<std::vector<std::string>> &attributes, std::vector<std::vector<std::string>> &contents)
{
std::ifstream openFile(filename);
std::string line, newLine;
if(openFile.is_open())
{
while(std::getline(openFile, line))
{
std::stringstream str;
if(line.find("Load=") != std::string::npos)
{
type = LoadType::Attributes;
line = line.erase(0, line.find("=") + 1);
tempAttributes.clear();
}
else
{
type = LoadType::Contents;
tempContents.clear();
}
str << line;
while(std::getline(str, newLine, ']'))
{
newLine.erase(std::remove(newLine.begin(), newLine.end(), '['), newLine.end());
std::string erase = " \t\n\r";
newLine.erase(newLine.find_last_not_of(erase) + 1);
if(type == LoadType::Attributes)
tempAttributes.push_back(newLine);
else
tempContents.push_back(newLine);
std::cout << newLine << std::endl;
}
if(type == LoadType::Contents && tempContents.size() > 0)
{
attributes.push_back(tempAttributes);
contents.push_back(tempContents);
}
}
}
else
{
}
}
void FileManager::LoadContent(const char *filename, std::vector<std::vector<std::string>> &attributes, std::vector<std::vector<std::string>> &contents, std::string identifier)
{
std::ifstream openFile(filename);
std::string line, newLine;
if(openFile.is_open())
{
while(std::getline(openFile, line))
{
std::stringstream str;
if(line.find("EndLoad=") != std::string::npos && line.find(identifier) != std::string::npos)
{
identifierFound = false;
break;
}
else if(line.find("Load=") != std::string::npos && line.find(identifier) != std::string::npos)
{
identifierFound = true;
}
if(identifierFound)
{
if(line.find("Load=") != std::string::npos)
{
type = LoadType::Attributes;
line = line.erase(0, line.find("=") + 1);
tempAttributes.clear();
}
else
{
type = LoadType::Contents;
tempContents.clear();
}
str << line;
while(std::getline(str, newLine, ']'))
{
newLine.erase(std::remove(newLine.begin(), newLine.end(), '['), newLine.end());
std::string erase = " \t\n\r";
newLine.erase(newLine.find_last_not_of(erase) + 1);
if(type == LoadType::Attributes)
tempAttributes.push_back(newLine);
else
tempContents.push_back(newLine);
std::cout << newLine << std::endl;
}
if(type == LoadType::Contents && tempContents.size() > 0)
{
attributes.push_back(tempAttributes);
contents.push_back(tempContents);
}
}
}
}
else
{
std::cout << "Error reading file!" << std::endl;
}
}
Layer.CPP
#include "Layer.h"
Layer::Layer(void)
{
}
Layer::~Layer(void)
{
}
std::pair<int, int> Layer::SetTiles(std::string tileString)
{
std::pair<int, int> tile;
tile.first = atoi(tileString.substr(0, tileString.find(',')).c_str());
tile.second = atoi(tileString.substr(tileString.find(',') + 1).c_str());
return tile;
}
void Layer::LoadContent(std::string layerID, std::string mapID)
{
std::string fileName = "Maps/"+mapID+".txt";
fileManager.LoadContent(fileName.c_str(), attributes, contents, layerID);
int indexY = 0;
for(int i = 0; i < attributes.size(); i++)
{
for(int j = 0; j < contents[i].size(); j++)
{
std::cout << attributes[i][j] << std::endl << std::endl;
std::cout << contents[i][j] << std::endl << std::endl;
if(attributes[i][j] == "SolidTiles")
solidTiles.push_back(SetTiles(contents[i][j]));
else if(attributes[i][j] == "TileSheet")
{
tileSheet = al_load_bitmap(contents[i][j].c_str());
}
else if(attributes[i][j] == "StartLayer")
{
for(int k = 0; k < contents[i].size(); k++)
{
if(contents[i][k] != "---")
{
std::cout << contents[i][k] << std::endl << std::endl;
ALLEGRO_BITMAP *tileImage;
Tile::State tempState = Tile::State::Passive;
std::pair<int, int> tile = SetTiles(contents[i][k]);
if(std::find(solidTiles.begin(), solidTiles.end(), tile) != solidTiles.end())
{
tempState = Tile::State::Solid;
}
tileImage = al_create_sub_bitmap(tileSheet, tile.first * 32, tile.second * 32, 32, 32);
std::pair<float, float> position(k * 32, indexY * 32);
Tile tileInstance;
tiles.push_back(tileInstance);
tiles[tiles.size()-1].SetContent(tileImage, tempState, position);
}
}
indexY++;
}
}
}
}
void Layer::UnloadContent()
{
for(int i = 0; i < tiles.size(); i++)
tiles[i].UnloadContent();
al_destroy_bitmap(tileSheet);
}
void Layer::Update()
{
}
void Layer::Draw(ALLEGRO_DISPLAY *display)
{
for(int i = 0; i < tiles.size(); i++)
tiles[i].Draw(display);
}
map1.txt
Load=[MapProperties]
EndLoad=[MapProperties]
Load=[Layer1]
Load=[SolidTiles]
[2,0]
[1,0]
Load=[TileSheet]
[TileSheets/tilesheet1.png]
Load=[StartLayer]
[2,0][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][2,0][2,0][2,0][---][---][---][---]
[---][---][---][---][---][---][---][2,0][---][---][---][---][---][---][---]
[---][---][---][---][---][---][2,0][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[---][---][2,0][2,0][2,0][---][---][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[---][---][---][---][---][---][---][---][---][---][---][---][---][---][---]
[1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0][1,0]
Load=[EndLayer]
[dummy]
EndLoad=[Layer1]
Load=[PlayerPosition]
[0,0]