Using https://github.com/nlohmann/json, I am trying to assign values to a recursive data structure (json_node_t):
#include <iostream>
#include <string>
#include <vector>
#include "json.hpp"
using namespace std;
using json = nlohmann::json;
struct json_node_t {
int id;
std::vector<json_node_t> children;
};
void to_json(json& j, const json_node_t& node) {
j = {{"ID", node.id}};
if (!node.children.empty())
j.push_back({"children", node.children});
}
int main() {
json_node_t node_0;
std::vector<int> values = {1,2,3};
std::vector<json_node_t> parents;
parents.resize(20);
for(int i = 0; i < values.size(); i++) {
if ( i == 0 )
{
node_0.id = values[0];
std::vector<json_node_t> node_children_;
node_0.children = node_children_;
parents[0] = node_0;
} else {
json_node_t node_i;
node_i.id = values[i];
std::vector<json_node_t> node_i_children_;
parents[i] = node_i;
parents[i-1].children.push_back(node_i);
}
}
json j = node_0;
cout << j.dump(2) << endl;
return 0;
}
My purpose is to create a JSON representation like the following:
{
"ID": 1,
"children": [
{
"ID": 2
},
{
"ID": 3,
"children": []
}
]
}
However, the nested children are not getting printed. I only get this output:
{
"ID": 1
}
What is wrong? I cannot connect the child to his parent correct. How can I fix the problem?
You output node_0;, but you never append any children to it. The reason for that, is parents[0] = node_0; copies node_0. So when you parents[0].children.push_back(node_i); you append node_i as a child to the copy of node_0 - the original one remains unchanged. That is why it contains no children in the end.
EDIT:
My code.
#include "json.hpp"
#include <memory>
#include <vector>
#include <iostream>
struct json_node;
using json_node_ptr = std::shared_ptr<json_node>;
struct json_node
{
int id;
std::vector<json_node_ptr> children;
json_node(int _id)
: id{ _id }
{
}
};
void to_json(nlohmann::json& j, const json_node_ptr& node)
{
j = {{"ID", node->id}};
if (!node->children.empty()) {
j.push_back({"children", node->children});
}
}
int main()
{
std::vector<int> values = {1,2,3};
std::vector<json_node_ptr> parents;
for(int i = 0; i < values.size(); i++)
{
if ( i == 0 ) {
auto root = std::make_shared<json_node>(values[0]);
parents.push_back(root);
} else {
parents.push_back(std::make_shared<json_node>(values[i]));
parents[i-1]->children.push_back(parents[i]);
}
}
nlohmann::json j = parents[0];
std::cout << j.dump(2) << std::endl;
return 0;
}
Output:
{
"ID": 1,
"children": [
{
"ID": 2,
"children": [
{
"ID": 3
}
]
}
]
}
Related
I'm trying to print the structure in an array whose int prejetih member is highest.
#include <iostream>
using namespace std;
struct Tekma {
int prejetih;
};
Tekma najvec_kosev(Tekma tekme[]) {
int maksi = 0, index = 0;
for (int i = 0;i < 2;i++) {
if (maksi < tekme[i].prejetih) {
index = i;
maksi = tekme[i].prejetih;
}
}
return tekme[index];
}
void vpis(Tekma tekme[]) {
for (int i = 0;i < 2;i++)
cin >> tekme[i].prejetih;
}
int main() {
Tekma tekme[2];
vpis(tekme);
cout << najvec_kosev(tekme);
}
The compiler reports
C++ no operator matches these operands
operand types are: std::ostream << Tekma
over cout << najvec_kosev(tekme);
Here using a solution with std::vector and fixing your cout problem:
#include <iostream>
#include <vector>
using namespace std;
struct Tekma {
int prejetih;
};
Tekma najvec_kosev(vector<Tekma>& tekme) {
Tekma lowest = tekme[0]
for(auto& t : tekme) {
if(lowest.prejetih < t.prejetih) {
lowest = t;
}
}
return lowest ;
}
void vpis(vector<Tekma>& tekme) {
int input;
while(true) {
cin >> input;
// Check if the input is valid else quit the loop.
if(input == valid) {
Tekma newStruct = {input};
tekme.push(newStruct);
}
else {
// Stop the loop
break;
}
}
}
int main() {
vector<Tekma> tekme;
vpis(tekme);
cout << najvec_kosev(tekme).prejetih; // This fixes your error.
}
I am trying to use a set method to apply 7 colors to an array in c++. I am not entirely sure how to use the setElement method in my main function to help me append colors to the indices in my array, as I cannot find any help online or in my book. So far, I have:
#include <iostream>
#include <string>
using namespace std;
class randColor
{
private:
string colors[7];
public:
void setElement(index, "color")
{
colors[] = index;
index = "color";
}
void printColor()
{
int i = 0;
for(i = 0; i <= 7; i++)
{
cout << colors[i] << endl;
}
}
};
int main()
{
randColor RandomOne;
RandomOne.setElement(index, {"red", "orange", "yellow", "blue", "green", "indigo", "violet"});
RandomOne.printColor();
return 0;
}
setElement() is for setting just one element, you can't give it an array.
You need to declare the types of the function parameters, and they shouldn't be in quotes.
void setElement(unsigned int index, std::string color)
{
colors[index] = color;
}
If you want to set all the elements, you need to call it in a loop.
std::string rainbow[] = {"red", "orange", "yellow", "blue", "green", "indigo", "violet"};
for (int i = 0; i < sizeof rainbow/sizeof *rainbow; i++) {
RandomOne.setElement(i, rainbow[i]);
}
Your setElement() method is implemented all wrong. It needs to look like this instead:
void setElement(int index, const string &color)
{
colors[index] = color;
}
Also, your printColor() method is going out of bounds of the array. The loop needs to use < instead of <=:
for(i = 0; i < 7; i++)
And then, your main() should look like this:
int main()
{
randColor RandomOne;
RandomOne.setElement(0, "red");
RandomOne.setElement(1, "orange");
RandomOne.setElement(2, "yellow");
RandomOne.setElement(3, "blue");
RandomOne.setElement(4, "green");
RandomOne.setElement(5, "indigo");
RandomOne.setElement(6, "violet");
RandomOne.printColor();
return 0;
}
Alternatively:
int main()
{
randColor RandomOne;
const string colors[] = {"red", "orange", "yellow", "blue", "green", "indigo", "violet"};
for(int i = 0; i < 7; ++i) {
RandomOne.setElement(i, colors[i]);
}
RandomOne.printColor();
return 0;
}
In case you want to keep the setElement() function call in the main() function as is you could use an std::initializer_list, although I personally wouldn't recommend it in this case.
#include <iostream>
#include <string>
#include <initializer_list>
using namespace std;
class randColor
{
private:
string colors[7];
public:
void setElement(int index, initializer_list<string> cols)
{
int i = 0;
for (auto it = cols.begin(); ++it; it != cols.end()) {
if (i++ == index) {
colors[i] = *it;
break;
}
}
}
void printColor()
{
int i = 0;
for (i = 0; i < sizeof(colors) / sizeof(string); i++)
{
cout << colors[i] << endl;
}
}
};
int main()
{
randColor RandomOne;
int index = 5;
RandomOne.setElement(index, { "red", "orange", "yellow", "blue", "green", "indigo", "violet" });
RandomOne.printColor();
return 0;
}
Can anyone solve this for me? I couldn't find why is it giving error on these specific lines. I guess the syntax is right. I have commented the error lines. It is giving error on open.push_back(p) in DFID function and mylist.push_back(p); in GenerateChildren function Please help me on this. Much Thanks
#include <iostream>
#include <algorithm>
#include <list>
#include <string>
using namespace std;
const int n = 3;
int goal[n][n] = { { 1, 2, 3 },{ 8, 0, 4 },{ 7, 6, 5 } };
static int max_depth = 0;
list <int[3][3]> open;
list <string> closed;
bool DFID(int[3][3]);
list<int[3][3]> generateChildren(int[3][3]);
bool isGoal(int [3][3]);
string convertToString(int[3][3]);
bool inClosed(string);
void main()
{
int puzzle[n][n] = { { 1, 2, 3 }, { 8, 6, 4 }, { 7, 0, 5 } };
DFID(puzzle);
}
bool DFID(int p[3][3])
{
open.push_back(p); // Error on this line
open.pop_front();
list<int[3][3]> mylist = generateChildren(p);
list<int[3][3]>::iterator it;
for (it = mylist.begin(); it != mylist.end(); ++it)
{
if (isGoal(*it))
return true;
else
{
string s =convertToString(*it);
if (inClosed(s))
{
continue;
}
else
{
//
}
}
}
}
list<int[3][3]> generateChildren(int p[3][3])
{
//finding zero element
int a = 0, b = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; i < n; j++)
{
if (p[i][j] == 0)
{
a = i;
b = j;
break;
}
}
}
list <int[3][3]> mylist;
if (p[-a][b] != -1)
{
swap(p[a][b], p[--a][b]);
mylist.push_back(p); //Error on this line
}
if (p[a][--b] != -1)
{
swap(p[a][b], p[a][--b]);
mylist.push_back(p); //Error
}
if (p[++a][b] != 3)
{
swap(p[a][b], p[++a][b]);
mylist.push_back(p); //Error
}
if (p[a][++b] != 3)
{
swap(p[a][b], p[a][++b]);
mylist.push_back(p); //Error
}
return mylist;
}
bool isGoal(int p[3][3])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; i < n; j++)
{
if (p[i][j] != goal[i][j]);
return false;
}
}
return true;
}
string convertToString(int p[3][3])
{
string puzz;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
puzz = puzz + to_string(p[i][j]);
}
}
return puzz;
}
bool inClosed(string s)
{
list<string>::iterator it;
for (it = closed.begin(); it != closed.end(); ++it)
{
if (*it == s);
return true;
}
return false;
}
There are multiple problems with the code as you show it.
One issue is that putting data into a container means it either needs to be move or copied. And arrays can't be neither moved nor copied.
Another issue is that e.g.
bool DFID(int[3][3]);
is equal to
bool DFID(int(*)[3]);
That is, the argument is a pointer and not an array. Pointers and arrays are different.
One possible way to solve your problems (both of them) is to use another standard container, such as std::array:
std::array<std::array<int, n>, n> goal;
std::list<std::array<std::array<int, n>, n>> open;
You can simplify the type with a type-alias:
using matrix_type = std::array<std::array<int, n>, n>;
matrix_type goal;
std::list<matrix_type> open;
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 = ¤t->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 = ¤t->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 = ¤t->children[found];
printFromNode(*current);
maxNode(*current);
}
else if (found > -1 && search.size() != 1) {
current = ¤t->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
Okay so I have an array like this:
class name {
public:
string first;
int last;
name(string a, int b){
first = a;
last = b;
}
};
name arr[] { { "John", 1 }, { "Jane", 2 }, { "Dick", 3 }, { "John", 1 }, { "Jane", 2 } };
For now I am only able to print them all out like this:
int main() {
int icount = sizeof(arr) / sizeof(name);
for (int i = 0; i < icount; i++){
cout << arr[i].first << " " << arr[i].last << endl;
}
}
Output will be like this:
John 1
Jane 2
Dick 3
John 1
Jane 2
However I need merge any similar results, meaning if the name is the same I need to add up the numbers behind them. The desired output should be like this:
John 2
Jane 4
Dick 3
Is there any function I can use to merge them or how should I go about doing it?
Here is another variant:
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
class name {
public:
string first;
int last;
name(string a, int b);
};
name::name(string a, int b) : first(a), last(b)
{
}
int main(int argc, char **argv)
{
string names[] =
{
"John", "Jane", "Dick", "John", "Jane"
};
int values[] =
{
1, 2, 3, 1, 2
};
vector<name> people;
for (int i = 0; i < sizeof(names) / sizeof(*names); ++i)
{
people.push_back(name(names[i], values[i]));
}
map<string, int> unique_people;
for (vector<name>::const_iterator it = people.begin(),
end = people.end(); it != end; ++it)
{
if (unique_people.count(it->first) != 0)
{
unique_people[it->first] += it->last;
}
else
{
unique_people.insert(pair<string, int>(it->first, it->last));
}
}
for (map<string, int>::const_reverse_iterator it = unique_people.rbegin(),
end = unique_people.rend(); it != end; ++it)
{
cout << it->first << " " << it->second << endl;
}
return 0;
}
Since you are using C++ you can use Map to finish your job.
Here is the complete program you need.
#include <iostream>
#include <map>
using namespace std;
map<string, int> mer;
class name
{
public:
string first;
int last;
name (string a, int b)
{
first = a;
last = b;
}
};
name arr[] { { "John", 1 }, { "Jane", 2 }, { "Dick", 3 }, { "John", 1 }, { "Jane", 2 } };
void merge()
{
int icount = sizeof(arr) / sizeof(name);
for (int i = 0; i < icount; i++)
{
if (mer.count(arr[i].first) > 0)
{
mer[arr[i].first]++;
}
else
{
mer[arr[i].first] = 1;
}
}
}
int main()
{
int icount = sizeof(arr) / sizeof(name);
merge();
map<string,int>::iterator it;
for(it = mer.begin(); it != mer.end(); it++)
{
cout << it->first << " " << it->second << endl;
}
return 0;
}
This will print the result of what you expected. Of course it will print in reverse order. You can use reverse iterator to get the desired result.