Implementing Adapter into c++ program - c++

I am trying to implement Adapter which would enable me to use class "TecajnaLista" with function Statistika::prosjek.
End result I am looking for is to call function Statistika::prosjek like this:
> map<string, tuple<double, int>> pr = Statistika::prosjek(adapter);
Insted of this:
> map<string, tuple<double, int>> pr = Statistika::prosjek(p);
Program without Adapter looks like this:
Za_adaptaciju.h
#pragma once
#include <fstream>
#include <vector>
#include <map>
using namespace std;
//=============================================================================
//=============================================================================
//=============================================================================
namespace PostojeciProgram {
class ITecaj {
public:
virtual void ucitaj(fstream*) = 0;
virtual const vector<tuple<string, double>>* podaci() const = 0;
};
class Tecaj : public ITecaj {
public:
void ucitaj(fstream*);
const vector<tuple<string, double>>* podaci() const;
private:
vector<tuple<string, double>> vrijednosti;
};
class Statistika {
public:
static map<string, tuple<double, int>> prosjek(ITecaj&);
};
void ispisi(map<string, tuple<double, int>>& pr);
void ispisi_tecaj();
}
Za_adaptaciju.cpp
#include <string>
#include <iostream>
#include "za_adaptaciju.h"
//=============================================================================
//=============================================================================
//=============================================================================
namespace PostojeciProgram {
void Tecaj::ucitaj(fstream* datoteka) {
string red;
while (true) {
*datoteka >> red;
if (datoteka->eof()) {
break;
} else {
int zarez = red.find(',');
string mjesec = red.substr(0, zarez);
double cijena = atof(red.substr(zarez + 1, red.size()).c_str());
vrijednosti.push_back({mjesec, cijena});
}
}
}
const vector<tuple<string, double>>* Tecaj::podaci() const {
return &vrijednosti;
}
map<string, tuple<double, int>> Statistika::prosjek(ITecaj& tecaj) {
map<string, tuple<double, int>> prosjek;
for (tuple<string, double> v : *(tecaj.podaci())) {
string kljuc = get<0>(v);
double nova_vrijednost = get<1>(v);
tuple<double, int>& p = prosjek[kljuc];
double vrijednost = get<0>(p);
int broj_pojavljivanja = get<1>(p);
if (broj_pojavljivanja == 0) {
prosjek[kljuc] = {nova_vrijednost, 1};
} else {
prosjek[kljuc] = {vrijednost + nova_vrijednost, broj_pojavljivanja + 1};
}
}
return prosjek;
}
void ispisi(map<string, tuple<double, int>>& pr) {
for (auto v : pr) {
string kljuc = get<0>(v);
tuple<double, int> v = pr[kljuc];
double n = get<0>(v) / get<1>(v);
cout << kljuc << ": " << n << endl;
}
}
void ispisi_tecaj() {
Tecaj p;
fstream f;
f.open("tecaj_eur.csv", fstream::in);
p.ucitaj(&f);
map<string, tuple<double, int>> pr = Statistika::prosjek(p);
ispisi(pr);
}
}
Main.cpp
#include <iostream>
#include "za_adaptaciju.h"
using namespace PostojeciProgram;
void test_adapter() {
cout << "--- TECAJ - klasa Tecaj\n";
ispisi_tecaj();
cout << endl;
}
int main() {
test_adapter();
}
My attempt:
Za_adaptaciju.h
#pragma once
#include <fstream>
#include <vector>
#include <map>
using namespace std;
//=============================================================================
//=============================================================================
//=============================================================================
namespace PostojeciProgram {
class ITecaj {
public:
virtual void ucitaj(fstream*) = 0;
virtual const vector<tuple<string, double>>* podaci() const = 0;
};
class Tecaj : public ITecaj {
public:
void ucitaj(fstream*);
const vector<tuple<string, double>>* podaci() const;
private:
vector<tuple<string, double>> vrijednosti;
};
class TecajnaLista {
public:
void ucitaj_valutu(string ime_datoteke);
const vector<tuple<string, double>>* podaci() const;
private:
vector<tuple<string, double>> vrijednosti;
};
/* ########################### moj adapter #################################################*/
class Adapter : public TecajnaLista {
public:
void ucitaj_valutu(string ime_datoteke) {
stream.open("tecaj_eur.csv", fstream::in);
tecaj.ucitaj(&stream);
}
const vector<tuple<string, double>>* podaci() const {
tecaj.podaci();
return &vrijednosti;
}
protected:
vector<tuple<string, double>> vrijednosti;
PostojeciProgram::ITecaj* itecaj;
PostojeciProgram::Tecaj tecaj;
fstream stream;
};
class Statistika {
public:
static map<string, tuple<double, int>> prosjek(Adapter& adapter);
};
void ispisi(map<string, tuple<double, int>>& pr);
void ispisi_tecaj();
}
za_adaptaciju.cpp
#include <string>
#include <iostream>
#include "za_adaptaciju.h"
//=============================================================================
//=============================================================================
//=============================================================================
namespace PostojeciProgram {
void Tecaj::ucitaj(fstream* datoteka) {
string red;
while (true) {
*datoteka >> red;
if (datoteka->eof()) {
break;
} else {
int zarez = red.find(',');
string mjesec = red.substr(0, zarez);
double cijena = atof(red.substr(zarez + 1, red.size()).c_str());
vrijednosti.push_back({mjesec, cijena});
}
}
}
const vector<tuple<string, double>>* Tecaj::podaci() const {
return &vrijednosti;
}
map<string, tuple<double, int>> Statistika::prosjek(Adapter& tecaj) {
map<string, tuple<double, int>> prosjek;
for (tuple<string, double> v : *(tecaj.podaci())) {
string kljuc = get<0>(v);
double nova_vrijednost = get<1>(v);
tuple<double, int>& p = prosjek[kljuc];
double vrijednost = get<0>(p);
int broj_pojavljivanja = get<1>(p);
if (broj_pojavljivanja == 0) {
prosjek[kljuc] = {nova_vrijednost, 1};
} else {
prosjek[kljuc] = {vrijednost + nova_vrijednost, broj_pojavljivanja + 1};
}
}
return prosjek;
}
void ispisi(map<string, tuple<double, int>>& pr) {
for (auto v : pr) {
string kljuc = get<0>(v);
tuple<double, int> v = pr[kljuc];
double n = get<0>(v) / get<1>(v);
cout << kljuc << ": " << n << endl;
}
}
void ispisi_tecaj() {
Tecaj p;
Adapter adapter;
adapter.ucitaj_valutu("tecaj_eur.csv");
map<string, tuple<double, int>> pr = Statistika::prosjek(adapter);
ispisi(pr);
}
}
Program is compiling but I am getting empty result instead of expected result which I am getting with program without adapter :
Result of program execution without adapter
Thank you in advance!

Related

std::cout stopping the program

I was trying to fix a bug, and I am extremely confused, it seems that whenever I use std::cout the program will freeze. I have absolutely no idea why this is happening, and if any of you I know why I would love to know.
here is my source code for reference (the std::cout is at the bottom in the main function):
#include <iostream>
#include <vector>
#include <unordered_map>
#include <exception>
#include <string>
#include <fstream>
/*
template<
typename T
>
std::ostream& operator<< (std::ostream& stream, std::vector<T> vec)
{
for (int i = 0; i < vec.size() - 1; ++i)
{
stream << vec[i] << " ";
}
stream << vec.back();
return stream;
}
*/
class gate
{
public:
std::unordered_map<std::string, int> m_inputs;
std::unordered_map<std::string, int> m_outputs;
virtual std::vector<bool> calculate(const std::vector<bool>& inputs) = 0;
gate(const std::unordered_map<std::string, int>& inputs, const std::unordered_map<std::string, int>& outputs) :
m_inputs(inputs),
m_outputs(outputs)
{}
};
class elementary_gate : public gate
{
private:
std::unordered_map<std::vector<bool>, std::vector<bool>> m_truth_table;
public:
elementary_gate(const std::unordered_map<std::vector<bool>, std::vector<bool>>& truth_table,
const std::unordered_map<std::string, int>& inputs,
const std::unordered_map<std::string, int>& outputs
) :
gate(inputs, outputs),
m_truth_table(truth_table)
{}
std::vector<bool> calculate(const std::vector<bool>& inputs) override
{
return m_truth_table[inputs];
}
};
class gate_reference
{
private:
gate* m_gate;
std::vector<int> m_input_connection_ids;
std::vector<int> m_output_connection_ids;
public:
gate_reference(gate* gate_ref, const std::vector<int>& input_connection_ids, const std::vector<int>& output_connection_ids) :
m_gate(gate_ref),
m_input_connection_ids(input_connection_ids),
m_output_connection_ids(output_connection_ids)
{}
std::vector<bool> calculate(const std::vector<bool>& inputs)
{
return m_gate->calculate(inputs);
}
std::vector<int> get_input_connection_ids()
{
return m_input_connection_ids;
}
void set_output_connection_ids(const std::vector<bool>& output_vector, std::vector<bool>& connection_values)
{
for (int i = 0; i < output_vector.size(); ++i)
{
connection_values[m_output_connection_ids[i]] = output_vector[i];
}
}
};
class compound_gate : public gate
{
private:
std::vector<gate_reference> m_gates;
std::vector<int> m_output_connection_ids;
int connection_count;
int input_count;
public:
std::vector<bool> calculate(const std::vector<bool>& inputs) override
{
if (inputs.size() != input_count)
{
throw std::length_error("incorrect input size for logic gate");
}
std::vector<bool> connection_values(connection_count);
for (int i = 0; i < input_count; ++i)
{
connection_values[i] = inputs[i];
}
for (gate_reference gate_ref : m_gates)
{
std::vector<int> input_ids = gate_ref.get_input_connection_ids();
std::vector<bool> input_vector = construct_io_vector(input_ids, connection_values);
std::vector<bool> output_vector = gate_ref.calculate(input_vector);
gate_ref.set_output_connection_ids(output_vector, connection_values);
}
return construct_io_vector(m_output_connection_ids, connection_values);
}
private:
std::vector<bool> construct_io_vector(const std::vector<int>& connection_ids, const std::vector<bool>& connection_values)
{
std::vector<bool> input_vector;
for (int connection_id : connection_ids)
{
input_vector.push_back(connection_values[connection_id]);
}
return input_vector;
}
};
std::vector<bool> get_vector_from_int(int num, int pad_length)
{
std::vector<bool> bool_vec;
while (num)
{
if (num % 2)
{
bool_vec.push_back(true);
}
else
{
bool_vec.push_back(false);
}
num >>= 1;
}
while (bool_vec.size() < pad_length)
{
bool_vec.push_back(false);
}
std::reverse(bool_vec.begin(), bool_vec.end());
return bool_vec;
}
class gates
{
public:
static std::unordered_map<std::string, elementary_gate*> gate_list;
};
std::unordered_map<std::string, elementary_gate*> gates::gate_list;
gate* load_elementary_gate(const std::string& filename)
{
std::ifstream file(filename);
std::string gate_name = filename.substr(0, filename.find('.'));
int input_count;
file >> input_count;
std::unordered_map<std::string, int> inputs;
for (int i = 0; i < input_count; ++i)
{
std::string input_name;
file >> input_name;
inputs.insert(std::make_pair(input_name, i));
}
int output_count;
file >> output_count;
std::unordered_map<std::string, int> outputs;
for (int i = 0; i < output_count; ++i)
{
std::string output_name;
file >> output_name;
outputs.insert(std::make_pair(output_name, i));
}
int table_rows = 1 << input_count;
std::unordered_map<std::vector<bool>, std::vector<bool>> truth_table;
for (int i = 0; i < table_rows; ++i)
{
std::vector<bool> input_vector = get_vector_from_int(i, input_count);
std::vector<bool> output_vector(output_count);
for (int i = 0; i < output_count; ++i)
{
int val;
file >> val;
output_vector[i] = val;
}
truth_table.insert(std::make_pair(input_vector, output_vector));
}
elementary_gate* gate = new elementary_gate(truth_table, inputs, outputs);
gates::gate_list.insert(std::make_pair(gate_name, gate));
return gate;
}
gate* extract_gate_type(std::string& raw_gate)
{
std::string gate_name = raw_gate.substr(0, raw_gate.find('('));
raw_gate = raw_gate.substr(raw_gate.find('(') + 1, raw_gate.size() - raw_gate.find('(')- 2);
return gates::gate_list[gate_name];
}
std::vector<std::string> split_string(std::string str, char delim)
{
std::vector<std::string> split;
bool new_str = true;
for (char c : str)
{
if (new_str)
{
split.emplace_back("");
}
if (c == delim)
{
new_str = true;
}
else
{
if (c != ' ')
{
new_str = false;
split.back() += c;
}
}
}
return split;
}
gate* load_circuit(const std::string& filename)
{
std::ifstream file(filename);
std::string gate_name = filename.substr(0, filename.find('.'));
int input_count;
file >> input_count;
std::unordered_map<std::string, int> inputs;
for (int i = 0; i < input_count; ++i)
{
std::string input_name;
file >> input_name;
inputs.insert(std::make_pair(input_name, i));
}
int output_count;
file >> output_count;
std::unordered_map<std::string, int> outputs;
for (int i = 0; i < output_count; ++i)
{
std::string output_name;
file >> output_name;
outputs.insert(std::make_pair(output_name, i));
}
std::vector<gate*> gates;
std::vector<std::string> sub_gates_raw;
while (!file.eof())
{
std::string gate_str;
char c = ' ';
while (c != ')')
{
file >> c;
gate_str += c;
}
std::cout << gate_str.size() << std::endl;
if (gate_str.size() < 1)
{
continue;
}
gates.push_back(extract_gate_type(gate_str));
sub_gates_raw.push_back(gate_str);
}
std::vector<std::vector<std::string>> io_split;
for (std::string str : sub_gates_raw)
{
io_split.push_back(split_string(str, ','));
}
std::vector<std::vector<std::pair<std::string, std::string>>> gate_io_split;
for (std::vector<std::string> gate_strs : io_split)
{
std::vector<std::pair<std::string, std::string>> gate_strs_lr_split;
for (std::string io_str : gate_strs)
{
std::vector<std::string> gate_str_lr_split = split_string(io_str, '=');
gate_strs_lr_split.push_back(std::make_pair(gate_str_lr_split[0], gate_str_lr_split[1]));
}
gate_io_split.push_back(gate_strs_lr_split);
}
std::unordered_map<std::string, int> connection_list;
for (std::vector<std::pair<std::string, std::string>> gate_strs : gate_io_split)
{
for (std::pair<std::string, std::string> connection : gate_strs)
{
connection_list.insert(std::make_pair(connection.first, connection_list.size() - 1));
}
}
for (std::pair<std::string, int> input : inputs)
{
inputs.insert_or_assign(input.first, connection_list[input.first]);
}
for (std::pair<std::string, int> output : outputs)
{
outputs.insert_or_assign(output.first, connection_list[output.first]);
}
std::vector<std::vector<std::pair<int, int>>> gates_connection_indexes;
std::vector<std::vector<bool>> is_input;
for (int i = 0; i < gate_io_split.size(); ++i)
{
std::vector<std::pair<std::string, std::string>> gate_connection_indexes_str = gate_io_split[i];
std::vector<std::pair<int, int>> gate_connection_indexes;
std::vector<bool> gate_connections;
for (std::pair<std::string, std::string> gate_connection_index_str : gate_connection_indexes_str)
{
gate_connections.push_back(gates[i]->m_inputs.count(gate_connection_index_str.first));
std::pair<int, int> connnection_indexes = std::make_pair(connection_list[gate_connection_index_str.first], connection_list[gate_connection_index_str.second]);
gate_connection_indexes.push_back(connnection_indexes);
}
is_input.push_back(gate_connections);
gates_connection_indexes.push_back(gate_connection_indexes);
}
std::vector<gate_reference> gate_references;
for (int i = 0; i < gates_connection_indexes.size(); ++i)
{
}
return nullptr;
}
int main(void)
{
std::cout << "hello";
//load_elementary_gate("nand.gate");
//load_circuit("not.circuit");
//load_circuit("or.circuit");
return 0;
}

Creating std::set copies only one element, how to fix this?

v_map has the correct amount of information stored, however when i try to use std::set it only copies one element ,I assume the first one. This is my first time using std::set , maybe I miss something here...Thanks for your help !
typedef std::map<std::string,std::pair<int,int>> points_map;
void list_average(points_map &v_map)
{
Comparator compFunctor = [](std::pair<std::string,std::pair<int,int>> elem1,std::pair<std::string,std::pair<int,int>> elem2)
{
std::pair<int,int> it = elem1.second;
std::pair<int,int> jt = elem2.second;
return it.first < jt.first;
};
std::set<std::pair<std::string,std::pair<int,int>>,Comparator> v_set(v_map.begin(),v_map.end(),compFunctor);
for (std::pair<std::string,std::pair<int,int>> it : v_set)
{
std::pair<int,int> jt = it.second;
std::cout << it.first << " " << (jt.second - jt.first) / jt.first<< std::endl;
}
}
Note the following is the full program, I apologize in advance for the ugly code , and length of the code ,also I rewrote the name in the upper part of my code, in the full code , this particular function is called list_atlag
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <codecvt>
#include <iterator>
#include <numeric>
#include <functional>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>
#include <boost/tokenizer.hpp>
class Adatok
{
public:
Adatok(std::string name, std::string path, std::string date, int points) : _name(name), _path(path), _date(date), _points(points) {}
Adatok(const Adatok &other) = default;
Adatok &operator=(const Adatok &other) = default;
std::string get_name() { return _name; }
std::string get_path() { return _path; }
std::string get_date() { return _date; }
int get_points() { return _points; }
private:
std::string _name;
std::string _path;
std::string _date;
int _points;
};
class Ranglista
{
public:
Ranglista(std::string name, int points) : _name(name), _points(points) {}
Ranglista(const Ranglista &other) = default;
Ranglista &operator=(const Ranglista &other) = default;
std::string get_name() { return _name; }
int get_points() { return _points; }
bool operator<(const Ranglista &other)
{
return _points > other._points;
}
private:
std::string _name;
int _points;
};
class Vedes
{
public:
Vedes(std::string name, int point) : _name(name), _point(point) { _count++; }
Vedes(const Vedes &other) = default;
Vedes &operator=(const Vedes &other) = default;
std::string get_name() { return _name; }
int get_point() { return _point; }
int get_count() { return _count; }
void set_stuff(int &points)
{
_point += points;
_count++;
}
bool operator<(const Vedes &other)
{
return _count > other._count;
}
private:
std::string _name;
int _point;
int _count = 0;
};
typedef std::map<std::string, int> path_value; //minden path + az erteke
typedef std::vector<Adatok> name_path_date; //bejegyzesek
typedef std::vector<Ranglista> ranglista; //ranglista
typedef std::map<std::string,std::pair<int,int>> vedes_vec; //vedesek
typedef std::function<bool(std::pair<std::string,std::pair<int,int>>,std::pair<std::string,std::pair<int,int>>)> Comparator;
void create_pv(path_value &, boost::filesystem::path); //feltolti a path+ertek map-ot
void create_npd(name_path_date &, path_value &, std::string input); //feltolti a bejegyzesek vektorat + mindenki pontszama map
void create_np(name_path_date &, path_value &); // name + path map
void list_np(path_value &name_point); // nam + path kiiratas
void list_bejegyzesek(name_path_date &bejegyzesek); // bejegyzesek vektora kiiratas
bool check_bejegyzesek(name_path_date &bejegyzesek, std::string name, std::string path); //van-e mar ilyen bejegyzes
void create_rl(ranglista &rl_vec, path_value &name_point); //ranglista feltoltes
void list_rl(ranglista &rl_vec); //ranglista kiiratas
void vedes_atlag(name_path_date &bejegyzesek, vedes_vec &v_vec); //vedes atlag map
void list_atlag(vedes_vec &v_vec); //vedes atlag kiiratas
bool check_vedes(vedes_vec &v_vec, std::string name);
void vedes_elem(vedes_vec &v_vec, std::string name, int &&points); //
//void accumulate_pv(path_value&);
int main(int argc, char **argv)
{
std::vector<std::string> roots = {"City/Debrecen/Oktatás/Informatika/Programozás/DEIK/Prog1/", "City/Debrecen/Oktatás/Informatika/Programozás/DEIK/"};
std::string input_file_name = "db-2018-05-06.csv";
/* OPTIONS */
boost::program_options::options_description desc("ALLOWED OPTIONS");
desc.add_options()("help", "help msg")("root,r", boost::program_options::value<std::vector<std::string>>())("csv", boost::program_options::value<std::string>(), "comma separated values")("rank", "rang lista")("vedes", "labor vedesek");
boost::program_options::positional_options_description pdesc;
pdesc.add("root", -1);
boost::program_options::variables_map vm;
boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(desc).positional(pdesc).run(), vm);
boost::program_options::notify(vm);
int sum = 0;
path_value pv_map;
if (vm.count("help") || argc == 1)
{
std::cout << desc << std::endl;
return 1;
}
if (vm.count("root"))
{
roots = vm["root"].as<std::vector<std::string>>();
for (auto &i : roots)
{
boost::filesystem::path path(i);
create_pv(pv_map, path);
}
for (path_value::iterator it{pv_map.begin()}; it != pv_map.end(); it++)
sum += it->second;
//std::cout << sum << std::endl;create_npd
std::cout << std::accumulate(pv_map.begin(), pv_map.end(), 0, [](int value, const std::map<std::string, int>::value_type &p) { return value + p.second; });
std::cout << std::endl;
}
if (vm.count("csv"))
{
//input_file_name = vm["csv"].as<std::string>();
std::ifstream input_file{vm["csv"].as<std::string>()};
name_path_date bejegyzesek;
std::string temp;
path_value name_point;
while (getline(input_file, temp))
create_npd(bejegyzesek, pv_map, temp);
create_np(bejegyzesek, name_point);
//list_bejegyzesek(bejegyzesek);
//list_np(name_point);
if (vm.count("rank"))
{
ranglista rl_vec;
create_rl(rl_vec, name_point);
list_rl(rl_vec);
}
if (vm.count("vedes"))
{
vedes_vec v_vec;
vedes_atlag(bejegyzesek, v_vec);
list_atlag(v_vec);
}
return 0;
}
return 0;
}
void create_pv(path_value &pv_map, boost::filesystem::path path)
{
boost::filesystem::directory_iterator it{path}, eod;
BOOST_FOREACH (boost::filesystem::path const &p, std::make_pair(it, eod))
{
if (boost::filesystem::is_regular_file(p))
{
boost::filesystem::ifstream regular_file{p};
std::string temp;
int sum = 0; //aktualis .props erteke
while (getline(regular_file, temp))
{
temp.erase(0, temp.find_last_of('/'));
temp.erase(0, temp.find_first_of(' '));
sum += std::atoi((temp.substr(temp.find_first_of("0123456789"), temp.find_last_of("0123456789"))).c_str());
}
std::string result = p.string();
std::string result_path = result.substr(0, result.find_last_of('/'));
//std::cout << result_path << std::endl;
//pv_map.insert(std::make_pair(result, sum));
pv_map[result_path] = sum;
}
else
create_pv(pv_map, p);
}
}
//void accumulate_pv(path_value& pv_map)
//{
// std::cout<<std::accumulate(pv_map.begin(),pv_map.end(),0,[](int value,const path_value::int& p){return value+p.second;});
//}
void create_npd(name_path_date &bejegyzesek, path_value &pv_map, std::string input)
{
boost::tokenizer<boost::escaped_list_separator<char>> tokenizer{input};
boost::tokenizer<boost::escaped_list_separator<char>>::iterator it{tokenizer.begin()};
std::string name = *it;
std::string path = *(++it);
std::string date = *(++it);
path = path.substr(2);
if (!check_bejegyzesek(bejegyzesek, name, path))
bejegyzesek.push_back(Adatok(name, path, date, pv_map["/home/erik/Documents/Programs/"+path]));
}
bool check_bejegyzesek(name_path_date &bejegyzesek, std::string name, std::string path)
{
bool ok = false;
for (name_path_date::iterator it{bejegyzesek.begin()}; it != bejegyzesek.end(); it++)
{
if ((it->get_name() == name) && (it->get_path() == path))
ok = true;
}
return ok;
}
bool check_vedes(vedes_vec &v_vec, std::string name)
{
vedes_vec::iterator it = v_vec.find(name);
if (it != v_vec.end()) return true;
else return false;
}
void vedes_elem(vedes_vec &v_vec, std::string name, int &&points)
{
/*for (auto &it : v_vec)
if (it.get_name() == name)
it.set_stuff(points);
*/
vedes_vec::iterator i = v_vec.find(name);
std::pair<int,int> it = i->second;
//auto& jt = it->second;
it.first++;
it.second += points;
}
void create_np(name_path_date &bejegyzesek, path_value &name_point)
{
for (name_path_date::iterator it{bejegyzesek.begin()}; it != bejegyzesek.end(); it++)
if (name_point.count(it->get_name()) == 0)
name_point.insert(std::make_pair(it->get_name(), it->get_points()));
else
name_point[it->get_name()] += it->get_points();
}
void list_np(path_value &name_point)
{
for (path_value::iterator it{name_point.begin()}; it != name_point.end(); it++)
{
if (it->second)
std::cout << it->first << " " << it->second << std::endl;
}
}
void list_bejegyzesek(name_path_date &bejegyzesek)
{
for (name_path_date::iterator it{bejegyzesek.begin()}; it != bejegyzesek.end(); it++)
if (it->get_name() == "Varga Erik")
std::cout << it->get_name() << " " << it->get_path() << " " << it->get_points() << std::endl;
}
void create_rl(ranglista &rl_vec, path_value &name_point)
{
for (auto &it : name_point)
{
if (it.second > 0)
rl_vec.push_back(Ranglista(it.first, it.second));
}
std::sort(rl_vec.begin(), rl_vec.end());
}
void list_rl(ranglista &rl_vec)
{
for (auto &it : rl_vec)
std::cout << it.get_name() << " " << it.get_points() << std::endl;
}
void vedes_atlag(name_path_date &bejegyzesek, vedes_vec &v_vec)
{
std::string key = "City/Debrecen/Oktatás/Informatika/Programozás/DEIK/Prog1/Labor/Védés/";
for (auto &it : bejegyzesek)
{
if ((it.get_path().find("City/Debrecen/Oktatás/Informatika/Programozás/DEIK/Prog1/Labor/Védés/") != std::string::npos) && (it.get_points()) && (!check_vedes(v_vec, it.get_name())))
v_vec.insert(std::make_pair(it.get_name(),std::make_pair(1,it.get_points())));
else if ((check_vedes(v_vec, it.get_name())) && (it.get_path().find("City/Debrecen/Oktatás/Informatika/Programozás/DEIK/Prog1/Labor/Védés/") != std::string::npos) && (it.get_points()))
vedes_elem(v_vec, it.get_name(), it.get_points());
}
}
void list_atlag(vedes_vec &v_vec)
{
//std::sort(v_vec.begin(), v_vec.end());
Comparator compFunctor = [](std::pair<std::string,std::pair<int,int>> elem1,std::pair<std::string,std::pair<int,int>> elem2)
{
std::pair<int,int> it = elem1.second;
std::pair<int,int> jt = elem2.second;
return it.first < jt.first;
};
std::set<std::pair<std::string,std::pair<int,int>>,Comparator> v_set(v_vec.begin(),v_vec.end(),compFunctor);
//int sum = 0;
//int csum = 0;
for (std::pair<std::string,std::pair<int,int>> it : v_set)
{
std::pair<int,int> jt = it.second;
std::cout << it.first << " " << (jt.second - jt.first) / jt.first<< std::endl;
//sum += it.get_point();
//csum += it.get_count();
//sum = std::accumulate(v_vec.begin(), v_vec.end(), 0, [](int i, Vedes &o) { return i + o.get_point(); });
//csum = std::accumulate(v_vec.begin(), v_vec.end(), 0, [](int i, Vedes &o) { return i + o.get_count(); });
}
//std::cout << (sum - csum) / csum << std::endl;
}
so, as described here
template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
> class set;
std::set is an associative container that contains a sorted set of unique objects of type Key.
I cleaned up your code, and made a Minimal, Complete, and Verifiable example,
#include <iostream>
#include <map>
#include <set>
using point_pair = std::pair<int,int>;
using points_map = std::map<std::string, point_pair>;
using points_set_pair = std::pair<std::string, point_pair>;
auto compFunctor = [](const points_set_pair &elem1, const points_set_pair &elem2)
{
return elem1.second.first < elem2.second.first;
};
using points_set = std::set<points_set_pair, decltype(compFunctor)>;
void list_average(const points_map &v_map)
{
points_set v_set(v_map.begin(),v_map.end(),compFunctor);
for (auto &elem : v_set)
{
const point_pair &jt = elem.second;
std::cout << elem.first << " " << (jt.second - jt.first) / jt.first<< "\n";
}
}
Now consider the first version of main
int main()
{
points_map v_map = { {"foo", { 1, 2}}, {"bar", { 3, 4}}};
list_average(v_map);
}
output:
foo 1
bar 0
Now consider the second version of main:
int main()
{
points_map v_map = { {"foo", { 1, 2}}, {"bar", { 1, 4}}};
list_average(v_map);
}
output:
bar 3
See the problem? As .second.first of the elements are both 1, the latter replaces the first. It is not unique. That's the downside of std::set.
So, what then?
Don't use std::set, but use std::vector and std::sort. Example:
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using point_pair = std::pair<int,int>;
using points_map = std::map<std::string, point_pair>;
using string_point_pair = std::pair<std::string, point_pair>;
auto compFunctor = [](string_point_pair const &elem1, string_point_pair const &elem2)
{
return
elem1.second.first != elem2.second.first?
elem1.second.first < elem2.second.first:
elem1.second.second < elem2.second.second;
};
void list_average(points_map const &v_map)
{
std::vector<string_point_pair> v_vec(v_map.begin(),v_map.end());
std::sort(v_vec.begin(), v_vec.end(), compFunctor);
for (auto &elem : v_vec)
{
const point_pair &jt = elem.second;
std::cout << elem.first << " " << (jt.second - jt.first) / jt.first<< "\n";
}
}
int main()
{
points_map v_map = { {"foo", { 1, 2}}, {"bar", { 1, 4}}, {"baz", { 2, 4}}};
list_average(v_map);
}
Output:
foo 1
bar 3
baz 1
live demo

How to set Eigen DesnseFunctor input and value sizes for use in Eigen Levenberg Marquardt

Problem: I do not always know the exact size of the Jacobian or Function vector that I am going to use Levenberg Marquardt on. Therefore, I need to set the dimensions of them at compile time.
Expected: After I declare an instance of MyFunctorDense. I could set the "InputsAtCompileTime" to my input size and set "ValuesAtCompileTime" to my values size. Then my Jacobian ,aFjac, should have the dimensions tValues x tInputs, and my function vector, aH, should have the dimensions tValues x 1.
Observed:
.h file
#pragma once
#include "stdafx.h"
#include <iostream>
#include <unsupported/Eigen/LevenbergMarquardt>
#include <unsupported/Eigen/NumericalDiff>
//Generic functor
template <typename _Scalar, typename _Index>
struct MySparseFunctor
{
typedef _Scalar Scalar;
typedef _Index Index;
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> InputType;
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> ValueType;
typedef Eigen::SparseMatrix<Scalar, Eigen::ColMajor, Index>
JacobianType;
typedef Eigen::SparseQR<JacobianType, Eigen::COLAMDOrdering<int> >
QRSolver;
enum {
InputsAtCompileTime = Eigen::Dynamic,
ValuesAtCompileTime = Eigen::Dynamic
};
MySparseFunctor(int inputs, int values) : m_inputs(inputs),
m_values(values) {}
int inputs() const { return m_inputs; }
int values() const { return m_values; }
const int m_inputs, m_values;
};
template <typename _Scalar, int NX=Eigen::Dynamic, int NY=Eigen::Dynamic>
struct MyDenseFunctor
{
typedef _Scalar Scalar;
enum {
InputsAtCompileTime = NX,
ValuesAtCompileTime = NY
};
typedef Eigen::Matrix<Scalar,InputsAtCompileTime,1> InputType;
typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,1> ValueType;
typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime>
JacobianType;
typedef Eigen::ColPivHouseholderQR<JacobianType> QRSolver;
const int m_inputs, m_values;
MyDenseFunctor() : m_inputs(InputsAtCompileTime),
m_values(ValuesAtCompileTime) {}
MyDenseFunctor(int inputs, int values) : m_inputs(inputs),
m_values(values) {}
int inputs() const { return m_inputs; }
int values() const { return m_values; }
};
struct MyFunctorSparse : MySparseFunctor<double, int>
{
MyFunctorSparse(void) : MySparseFunctor<double, int>(2 , 2) {}
int operator()(const Eigen::VectorXd &aX, //Input
Eigen::VectorXd &aF) const; //Output
int df(const InputType &aF, JacobianType& aFjac);
};
struct MyFunctorDense : MyDenseFunctor<double>
{
MyFunctorDense(void) : MyDenseFunctor<double>( Eigen::Dynamic ,
Eigen::Dynamic) {}
int operator()(const InputType &aX, //Input
ValueType &aF) const; //Output
int df(const InputType &aX, JacobianType& aFjac);
};
.cpp file
#pragma once
#include "stdafx.h"
#include "Main.h"
int MyFunctorSparse::operator()(const Eigen::VectorXd &aX, //Input
Eigen::VectorXd &aF) const //Output
{
//F = aX0^2 + aX1^2
aF(0) = aX(0)*aX(0) + aX(1)*aX(1);
aF(1) = 0;
return 0;
}
int MyFunctorDense::operator()(const InputType &aX, //Input
ValueType &aF) const //Output
{
//F = aX0^2 + aX1^2
for (int i = 0; i < aF.size(); i++)
{
aF(i) = i*aX(0)*aX(0) + i*(aX(1)-1)*(aX(1)-1);
}
return 0;
}
int MyFunctorSparse::df(const InputType &aX, JacobianType& aFjac)
{
aFjac.coeffRef(0, 0) = 2*aX(0);
aFjac.coeffRef(0, 1) = 2*aX(1);
aFjac.coeffRef(1, 0) = 0.0;
aFjac.coeffRef(1, 1) = 0.0;
return 0;
}
int MyFunctorDense::df(const InputType &aX, JacobianType& aFjac)
{
for(int i = 0; i< aFjac.size(); i++)
{
aFjac(i, 0) = 2*i*aX(0);
aFjac(i, 1) = 2*i*(aX(1)-1);
}
return 0;
}
int main(int argc, char *argv[])
{
int input;
std::cout << "Enter 1 to run LM with DenseFunctor, Enter 2 to run LM with
SparseFunctor: " << std::endl;
std::cin >> input;
Eigen::VectorXd tX(2);
tX(0) = 10;
tX(1) = 0.5;
int tInputs = tX.rows();
int tValues = 60928;
std::cout << "tX: " << tX << std::endl;
if (input == 1)
{
MyFunctorDense myDenseFunctor;
tInputs = myDenseFunctor.inputs();
tValues = myDenseFunctor.values();
std::cout << "tInputs : " << tInputs << std::endl;
std::cout << "tValues : " << tValues << std::endl;
Eigen::LevenbergMarquardt<MyFunctorDense> lm(myDenseFunctor);
lm.setMaxfev(30);
lm.setXtol(1e-5);
lm.minimize(tX);
}
if (input == 2)
{
MyFunctorSparse myFunctorSparse;
//Eigen::NumericalDiff<MyFunctor> numDiff(myFunctor);
//Eigen::LevenbergMarquardt<Eigen::NumericalDiff<MyFunctor>,double>
lm(numDiff);
Eigen::LevenbergMarquardt<MyFunctorSparse> lm(myFunctorSparse);
lm.setMaxfev(2000);
lm.setXtol(1e-10);
lm.minimize(tX);
}
std::cout << "tX minimzed: " << tX << std::endl;
return 0;
}
Solution: I figured out my problem. I replaced:
const int m_inputs, m_values;
with
int m_inputs, m_values;
in the ".h" file this makes the member variable of the struct MyFunctorDense modifiable. So, then in the ".cpp" below the line
std::cout << "tX: " << tX << std::endl;
I added:
Eigen::VectorXd tF(60928);
because this is a test function vector of dimension 60928x1. Therefore, I could put in any arbitrary nx1 dimension.
Then below the line:
MyFunctorDense myDenseFunctor;
I added:
myDenseFunctor.m_inputs = tX.rows();
myDenseFunctor.m_values = tF.rows();
Now I get the result:

implement iterator on every elements of value containers against each key of map using boost iterator

How to implement an iterator of just on values of a map/unordered_map using boost::iterator_adaptor? I've tried following code but it does not work because of the line with comment.
Is there a solution to avoid the problem?
The question here is slightly different from map_values adapter example shown in boost code as here the value field in map is another container like list or vector and the requirement here is to iterate over all elements of those lists for every key of the map.
The deref of iterator is of type of value_type of those list/vector.The end of iterator is the end of list of last key
#include <vector>
#include <boost/unordered_map.hpp>
#include <cassert>
#include <iostream>
#include <boost/iterator/iterator_adaptor.hpp>
class DS {
public:
DS() : _map() {}
~DS() {
for (Map::iterator it = _map.begin(); it != _map.end(); ++it) {
delete (it->second);
}
}
void add(int key_, const std::vector< int > &value_)
{
IntList *ptr = new IntList(value_);
assert(ptr);
_map.insert(Map::value_type(key_, ptr));
}
private:
typedef std::vector< int > IntList;
typedef boost::unordered_map< int, IntList* > Map;
Map _map;
public:
class KeyIter : public boost::iterator_adaptor< KeyIter,
Map::const_iterator,
int,
boost::forward_traversal_tag,
int>
{
public:
KeyIter() : KeyIter::iterator_adaptor_() {}
private:
friend class DS;
friend class boost::iterator_core_access;
explicit KeyIter(Map::const_iterator it) : KeyIter::iterator_adaptor_(it) {}
explicit KeyIter(Map::iterator it) : KeyIter::iterator_adaptor_(it) {}
int dereference() const { return this->base()->first; }
};
class ValueIter : public boost::iterator_adaptor< ValueIter,
Map::const_iterator,
int,
boost::forward_traversal_tag,
int>
{
public:
ValueIter()
: ValueIter::iterator_adaptor_()
, _lIt()
{}
private:
friend class DS;
friend class boost::iterator_core_access;
explicit ValueIter(Map::const_iterator it)
: ValueIter::iterator_adaptor_(it)
, _lIt()
, _mIt(it)
{
IntList *pt = it->second; // <<-- issue here is I can't find if I've already reached the end of the map
if (pt) {
_lIt = it->second->begin();
}
}
int dereference() const { return *_lIt; }
void increment()
{
if (_lIt == _mIt->second->end()) {
++_mIt;
_lIt = _mIt->second->begin();
} else {
++_lIt;
}
}
IntList::iterator _lIt;
Map::const_iterator _mIt;
};
KeyIter beginKey() const { return KeyIter(_map.begin()); }
KeyIter endKey() const { return KeyIter(_map.end()); }
ValueIter beginValue() const { return ValueIter(_map.begin()); }
ValueIter endValue() const { return ValueIter(_map.end()); }
};
int main(int argc, char** argv)
{
DS ds;
std::vector< int > v1;
v1.push_back(10);
v1.push_back(30);
v1.push_back(50);
ds.add(90, v1);
std::vector< int > v2;
v2.push_back(20);
v2.push_back(40);
v2.push_back(60);
ds.add(120, v2);
std::cout << "------------ keys ---------------" << std::endl;
for (DS::KeyIter it = ds.beginKey(); it != ds.endKey(); ++it) {
std::cout << (*it) << std::endl;
}
std::cout << "------------ values ---------------" << std::endl;
// std::cout << (*(ds.beginValue())) << std::endl;
for (DS::ValueIter it = ds.beginValue(); it != ds.endValue(); ++it) {
std::cout << (*it) << std::endl;
}
return 0;
}
Implemented in c++11. You should be able to do the conversion to boost/c++03 fairly simply.
This iterator is FORWARD ONLY and it's quite fragile (see the comparison operator).
user discretion advised.
#include <iostream>
#include <vector>
#include <unordered_map>
typedef std::vector< int > IntList;
typedef std::unordered_map< int, IntList* > Map;
struct whole_map_const_iterator
{
using C1 = IntList;
using C2 = Map;
using I1 = C1::const_iterator;
using I2 = C2::const_iterator;
using value_type = I1::value_type;
using reference = I1::reference;
whole_map_const_iterator(I2 i2) : _i2(i2) {}
bool operator==(const whole_map_const_iterator& r) const {
if (_i2 != r._i2)
return false;
if (deferred_i1 && r.deferred_i1)
return true;
if (deferred_i1 != r.deferred_i1)
return false;
return _i1 == r._i1;
}
bool operator!=(const whole_map_const_iterator& r) const { return !(*this == r); }
reference operator*() const {
check_deferred();
return *_i1;
}
void check_deferred() const {
if (deferred_i1) {
_i1 = _i2->second->begin();
_i1limit = _i2->second->end();
deferred_i1 = false;
}
}
void go_next()
{
check_deferred();
if (++_i1 == _i1limit) {
++_i2;
deferred_i1 = true;
}
}
whole_map_const_iterator& operator++() {
go_next();
return *this;
}
whole_map_const_iterator operator++(int) {
auto result = *this;
go_next();
return result;
}
I2 _i2;
mutable I1 _i1 = {}, _i1limit = {};
mutable bool deferred_i1 = true;
};
IntList a { 1, 2, 3, 4, 5 };
IntList b { 6, 7, 8, 9, 10 };
Map m { { 1, &a }, { 2, &b } };
int main()
{
using namespace std;
auto from = whole_map_const_iterator(m.begin());
auto to = whole_map_const_iterator(m.end());
for ( ; from != to ; ++from) {
std::cout << *from << std::endl;
}
return 0;
}
example output:
6
7
8
9
10
1
2
3
4
5
For bonus points, answer this question:
Q: Why all that damn complication over the deferred flag?

boost qi::grammar not updating valuetype using spirit/phoenix

I have the following problem:
upon parsing a text using qi::grammar the struct grammer is not returning the values of the parsed object.
The Grammer
template<typename Iterator>
struct PositionalDegreeImpl_grammer : qi::grammar<Iterator,PositionalDegreeImpl>
{
struct Type_ : qi::symbols<char,horus::parsergenerator::nmea::CardinalDirection::Direction>
{
Type_()
{
this->add("E", horus::parsergenerator::nmea::CardinalDirection::Direction::EAST)
("N", horus::parsergenerator::nmea::CardinalDirection::Direction::NORTH)
("W", horus::parsergenerator::nmea::CardinalDirection::Direction::WEST)
("S", horus::parsergenerator::nmea::CardinalDirection::Direction::SOUTH);
}
} type_;
qi::rule<Iterator,PositionalDegreeImpl> r;
PositionalDegreeImpl_grammer() : PositionalDegreeImpl_grammer::base_type(r)
{
r = (double_ >> ',' >> type_)
[
qi::_val = boost::phoenix::construct<PositionalDegreeImpl>(qi::_2,qi::_1)
];
}
};
During the debug session is can see that the correct Constructor is being called, with the correct values.
std::string str = "123.2,W";
PositionalDegreeImpl val(horus::parsergenerator::nmea::CardinalDirection::Direction::EAST,1.0);
PositionalDegreeImpl_grammer<std::string::iterator> pos_deg_parser;
bool r = qi::parse(str.begin(), str.end(), pos_deg_parser, &val);
if (!r || val.degrees() != 123.2)
{
std::cout<< "Err" <<std::endl;
}
val contains the initial values after parsing. I have the feeling i am over looking something.
Pure virutal base
class PositionalDegree
{
public:
/*! number of degrees of the position */
virtual double degrees() const = 0;
/*! the direction {N,S,E,W} of the position */
virtual const CardinalDirection& direction() const = 0;
/*! Provide the assignment operator */
virtual PositionalDegree& operator=(const PositionalDegree&) = 0;
};
Implementation
class PositionalDegreeImpl : public PositionalDegree
{
private:
double _degrees;
CardinalDirectionImpl _direction;
public:
PositionalDegreeImpl();
explicit PositionalDegreeImpl(PositionalDegree const &other);
PositionalDegreeImpl(PositionalDegreeImpl const &other);
PositionalDegreeImpl(CardinalDirectionImpl const & cardinal, double degrees);
virtual ~PositionalDegreeImpl();
virtual double degrees() const;
virtual const CardinalDirection& direction() const;
virtual PositionalDegree& operator=(const PositionalDegree& other);
PositionalDegreeImpl& operator=(const PositionalDegreeImpl& other);
};
Any ideas, tips would be appreciated.
Regards Auke
Looks like you're missing parentheses here:
qi::rule<Iterator,PositionalDegreeImpl()> r;
If I remember correctly, the absolute requirement to include the parens will be lifted in an upcoming version (might already be there in 1_57_0
Here's a self contained example
Live On Coliru
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace horus { namespace parsergenerator { namespace nmea {
struct CardinalDirection {
enum class Direction { EAST, NORTH, WEST, SOUTH };
};
struct PositionalDegreeImpl {
PositionalDegreeImpl(CardinalDirection::Direction direction, double d)
: _dir(direction), _degrees(d)
{
}
double degrees() const { return _degrees; }
private:
CardinalDirection::Direction _dir;
double _degrees;
};
template<typename Iterator, typename T = PositionalDegreeImpl>
struct PositionalDegreeGrammar : qi::grammar<Iterator,T()>
{
PositionalDegreeGrammar() : PositionalDegreeGrammar::base_type(r)
{
r = (qi::double_ >> ',' >> type_)
[
qi::_val = boost::phoenix::construct<T>(qi::_2,qi::_1)
];
}
private:
struct Type_ : qi::symbols<char, CardinalDirection::Direction> {
Type_() {
this->add
("E", CardinalDirection::Direction::EAST)
("N", CardinalDirection::Direction::NORTH)
("W", CardinalDirection::Direction::WEST)
("S", CardinalDirection::Direction::SOUTH);
}
} type_;
qi::rule<Iterator,T()> r;
};
} } }
int main()
{
using namespace horus::parsergenerator::nmea;
typedef std::string::const_iterator It;
PositionalDegreeImpl val(CardinalDirection::Direction::EAST, 1.0);
PositionalDegreeGrammar<It> pos_deg_parser;
std::string const str = "123.2,W";
It f = str.begin(), l = str.end();
bool r = qi::parse(f, l, pos_deg_parser, val);
if (r)
std::cout << val.degrees() << ": " << std::boolalpha << (123.2==val.degrees()) << "\n";
else
std::cout << "parsing failed\n";
}
Prints:
123.2: true