<commit_before>#include "../kontsevich_graph_series.hpp"
#include <ginac/ginac.h>
#include <iostream>
#include <fstream>
#include <limits>
#include "../util/continued_fraction.hpp"
#include <Eigen/Dense>
#include <Eigen/SparseCore>
#include <Eigen/SparseQR>
#include <Eigen/OrderingMethods>
using namespace std;
using namespace GiNaC;

typedef Eigen::Triplet<double> Triplet;
typedef Eigen::SparseMatrix<double> SparseMatrix;

double threshold = 1e-5;

int main(int argc, char* argv[])
{
    if (argc != 2 && argc != 3 && argc != 4)
    {
        cout << "Usage: " << argv[0] << " <graph-series-filename> [max-jac-indegree] [--solve]\n\n"
             << "Accepts only homogeneous power series: graphs with n internal vertices at order n.\n"
             << "The optional arguments [max-jacobiators] and [max-jac-indegree] restrict the types of differential consequences of Jacobi taken into account:\n"
             << "- [max-jacobiators] restricts the number of Jacobiators per differential consequence, while\n"
             << "- [max-jac-indegree] restricts the number of arrows falling on Jacobiators.\n"
             << "When the optional argument [--solve] is specified, the undetermined variables in the input are added to the linear system to-be-solved.\n";
        return 1;
    }

    size_t max_jac_indegree = numeric_limits<size_t>::max();
    if (argc == 3 || argc == 4)
        max_jac_indegree = stoi(argv[2]);

    // Reading in graph series
    string graph_series_filename(argv[1]);
    ifstream graph_series_file(graph_series_filename);
    parser coefficient_reader;
    bool homogeneous = true;
    map<size_t, set< vector<size_t> > > in_degrees;
    KontsevichGraphSeries<ex> graph_series = KontsevichGraphSeries<ex>::from_istream(graph_series_file,
        [&coefficient_reader](string s) -> ex { return coefficient_reader(s); },
        [&homogeneous, &in_degrees](KontsevichGraph graph, size_t order) -> bool
                                   {
                                       in_degrees[order].insert(graph.in_degrees());
                                       return homogeneous &= graph.internal() == order;
                                   }
    );
    size_t order = graph_series.precision();
    if (!homogeneous)
    {
        cerr << "Only accepting homogeneous power series: graphs with n internal vertices at order n.\n";
        return 1;
    }

    // Find number of external vertices
    // TODO: move to method in KontsevichGraphSum / KontsevichGraphSeries?
    size_t external = 0;
    for (size_t n = 0; n <= order; ++n)
    {
        if (graph_series[n].size() != 0)
        {
            external = graph_series[n].front().second.external();
            break;
        }
    }
    graph_series.reduce();

    size_t counter = 0;
    vector<symbol> coefficient_list;

    if (argc == 4 && string(argv[3]) == "--solve")
        for (auto namevar : coefficient_reader.get_syms())
            coefficient_list.push_back(ex_to<symbol>(namevar.second));

    map< pair<KontsevichGraph, KontsevichGraph::VertexPair>, symbol> kontsevich_jacobi_leibniz_graphs;

    KontsevichGraphSeries<ex> leibniz_graph_series = graph_series;

    while (true)
    {
        for (size_t n = 0; n <= order; ++n)
        {
            for (auto& term : graph_series[n])
            {
                KontsevichGraph& graph = term.second;
                // Note: we ignore the coefficient and sign of the graph
                for (KontsevichGraph::Vertex v : graph.internal_vertices())
                {
                    for (KontsevichGraph::Vertex w : graph.neighbors_in(v))
                    {
                        vector<KontsevichGraph::VertexPair> targets_template = graph.targets();
                        KontsevichGraph::VertexPair& target_pair_v = targets_template[(size_t)v - external];
                        // Check that there is no loop between v and w
                        if (target_pair_v.first == w || target_pair_v.second == w)
                            continue;
                        KontsevichGraph::VertexPair& target_pair_w = targets_template[(size_t)w - external];
                        // Check that the "Jacobiator" consisting of v and w falls on 3 distinct targets
                        KontsevichGraph::Vertex& a = target_pair_v.first;
                        KontsevichGraph::Vertex& b = target_pair_v.second;
                        KontsevichGraph::Vertex& c = (target_pair_w.first == v) ? target_pair_w.second : target_pair_w.first;
                        if (c == a || c == b)
                            continue;

                        // Build the list of references to bad targets (incoming edges on v or w, except the edge w -> v)
                        set<KontsevichGraph::Vertex*> bad_targets;
                        for (KontsevichGraph::Vertex u : graph.internal_vertices())
                        {
                            if (u == w)
                                continue;
                            KontsevichGraph::VertexPair& target_pair = targets_template[(size_t)u - external];
                            if (target_pair.first == v || target_pair.first == w)
                                bad_targets.insert(&target_pair.first);
                            if (target_pair.second == v || target_pair.second == w)
                                bad_targets.insert(&target_pair.second);
                        }
                        if (bad_targets.size() > max_jac_indegree)
                            continue;

                        symbol coefficient("c_" + to_string(counter));

                        // Normal form of Leibniz graph (three permutations of Jacobi, take minimal encoding, remember where Jacobiator is)
                        for (auto& bad_target : bad_targets)
                            *bad_target = v;
                        vector< vector<KontsevichGraph::Vertex> > jacobi_targets_choices({ { a, b, c },
                                                                                { b, c, a },
                                                                                { c, a, b } });
                        vector< pair<KontsevichGraph, KontsevichGraph::VertexPair> > leibniz_graphs;
                        for (auto jacobi_targets_choice : jacobi_targets_choices)
                        {
                            // Set Jacobiator targets to one of the three permutatations
                            a = jacobi_targets_choice[0];
                            b = jacobi_targets_choice[1];
                            c = jacobi_targets_choice[2];

                            vector<KontsevichGraph::VertexPair> d_targets = targets_template;

                            // Find permutation of vertex labels such that the list of targets is minimal with respect to the defined ordering
                            std::vector<KontsevichGraph::VertexPair> global_minimum = d_targets;
                            sort_pairs(global_minimum.begin(), global_minimum.end());

                            size_t d_internal = graph.internal();
                            size_t d_external = graph.external();

                            KontsevichGraph::VertexPair new_vw = {v, w};
                            std::vector<KontsevichGraph::Vertex> vertices(d_external + d_internal);
                            std::iota(vertices.begin(), vertices.end(), 0);
                            while (std::next_permutation(vertices.begin() + d_external, vertices.end()))
                            {
                                std::vector<KontsevichGraph::VertexPair> local_minimum = d_targets;
                                apply_permutation(d_internal, d_external, local_minimum, vertices);
                                if (local_minimum < global_minimum)
                                {
                                    global_minimum = local_minimum;
                                    // Find where Jacobiator is
                                    new_vw = { vertices[(size_t)v], vertices[(size_t)w] };
                                }
                            }
                            d_targets = global_minimum;

                            KontsevichGraph leibniz_graph(d_targets.size(), d_external, d_targets, 1, true);
                            leibniz_graphs.push_back({ leibniz_graph, new_vw });
                        }
                        pair< KontsevichGraph, KontsevichGraph::VertexPair> leibniz_normal_form = *min_element(leibniz_graphs.begin(), leibniz_graphs.end());

                        if (kontsevich_jacobi_leibniz_graphs.find(leibniz_normal_form) != kontsevich_jacobi_leibniz_graphs.end())
                            continue;

                        KontsevichGraphSum<ex> graph_sum;

                        // Replace bad targets by Leibniz rule:
                        vector<size_t> leibniz_sizes(bad_targets.size(), 2);
                        CartesianProduct leibniz_indices(leibniz_sizes);
                        for (auto leibniz_index = leibniz_indices.begin(); leibniz_index != leibniz_indices.end(); ++leibniz_index)
                        {
                            size_t idx = 0;
                            for (auto& bad_target : bad_targets)
                                *bad_target = (*leibniz_index)[idx++] == 0 ? v : w;
                            for (auto jacobi_targets_choice : jacobi_targets_choices)
                            {
                                // Set Jacobiator targets to one of the three permutatations
                                a = jacobi_targets_choice[0];
                                b = jacobi_targets_choice[1];
                                c = jacobi_targets_choice[2];

                                KontsevichGraph new_graph(targets_template.size(), external, targets_template, graph.sign());

                                graph_sum += KontsevichGraphSum<ex>({ { coefficient, new_graph } });
                            }
                        }

                        graph_sum.reduce();
                        if (graph_sum.size() != 0)
                        {
                            cerr << "\r" << ++counter;
                            coefficient_list.push_back(coefficient);
                            kontsevich_jacobi_leibniz_graphs[leibniz_normal_form] = coefficient;
                        }
                        leibniz_graph_series[n] -= graph_sum;
                    }
                }
            }
        }

        cout << "\nNumber of Leibniz graphs: " << kontsevich_jacobi_leibniz_graphs.size() << "\n";
        cout << "\nNumber of terms: " << leibniz_graph_series[order].size() << "\n";

        cout.flush();

        cerr << "\nReducing...\n";
        leibniz_graph_series.reduce();

        lst equations;

        for (size_t n = 0; n <= order; ++n)
            for (auto& term : leibniz_graph_series[n])
            {
                cerr << term.second.encoding() << "    " << term.first << "==0\n";
                equations.append(term.first);
            }

        // Set up sparse matrix linear system

        cerr << "Setting up linear system for numerical solution...\n";
        size_t rows = equations.nops();
        size_t cols = coefficient_list.size();

        Eigen::VectorXd b(rows);
        SparseMatrix matrix(rows,cols);

        vector<Triplet> tripletList;
        size_t idx = 0;
        for (ex equation : equations)
        {
            if (!is_a<add>(equation))
                equation = lst(equation);
            for (ex term : equation)
            {
                if (!is_a<mul>(term))
                    term = lst(term);
                double prefactor = 1;
                symbol coefficient("one");
                for (ex factor : term)
                {
                    if (is_a<numeric>(factor))
                        prefactor *= ex_to<numeric>(factor).to_double();
                    else if (is_a<symbol>(factor))
                        coefficient = ex_to<symbol>(factor);
                }
                if (coefficient.get_name() == "one") // constant term
                    b(idx) = -prefactor;
                else
                    tripletList.push_back(Triplet(idx,find(coefficient_list.begin(), coefficient_list.end(), coefficient) - coefficient_list.begin(), prefactor));
                    // NB: Eigen uses zero-based indices (contrast MATLAB, Mathematica)
            }
            ++idx;
        }

        matrix.setFromTriplets(tripletList.begin(), tripletList.end());

        cerr << "Solving linear system (" << rows << " x " << cols << ") numerically...\n";

        Eigen::SparseQR< SparseMatrix, Eigen::COLAMDOrdering<int> > qr(matrix);
        Eigen::VectorXd x = qr.solve(b);

        cerr << "Residual norm = " << (matrix * x - b).squaredNorm() << "\n";

        cerr << "Rounding...\n";
        x = x.unaryExpr([](double elem) { return fabs(elem) < threshold ? 0.0 : elem; });

        double residual_norm = (matrix * x - b).squaredNorm();
        cerr << "Still a solution? Residual norm = " << residual_norm << "\n";

        if (!isnan(residual_norm) && residual_norm < 1.0)
        {
            cerr << "Approximating numerical solution by rational solution...\n";

            lst zero_substitution;
            lst solution_substitution;
            for (int i = 0; i != x.size(); i++)
            {
                ex result = best_rational_approximation(x.coeff(i), threshold);
                if (result == 0)
                    zero_substitution.append(coefficient_list[i] == 0);
                else
                    solution_substitution.append(coefficient_list[i] == result);
            }

            cerr << "Substituting zeros...\n";

            KontsevichGraphSeries<ex> leibniz_graph_series_copy = leibniz_graph_series; // TODO: inefficient?

            for (auto& order: leibniz_graph_series_copy)
                for (auto& term : leibniz_graph_series_copy[order.first])
                    term.first = term.first.subs(zero_substitution);

            cerr << "Reducing zeros...\n";

            leibniz_graph_series_copy.reduce();

            for (size_t n = 0; n <= leibniz_graph_series_copy.precision(); ++n)
            {
                cout << "h^" << n << ":\n";
                for (auto& term : leibniz_graph_series_copy[n])
                {
                    cout << term.second.encoding() << "    " << term.first << "\n";
                }
            }

            cerr << "Verifying solution...\n";

            for (auto& order: leibniz_graph_series_copy)
                for (auto& term : leibniz_graph_series_copy[order.first])
                    term.first = term.first.subs(solution_substitution);

            leibniz_graph_series_copy.reduce();

            cout << "Do we really have a solution? " << (leibniz_graph_series_copy == 0 ? "Yes" : "No") << "\n";

            if (leibniz_graph_series_copy == 0)
            {
                for (auto pair : kontsevich_jacobi_leibniz_graphs)
                    if (pair.second != ex(pair.second).subs(solution_substitution))
                        cout << pair.first.first.encoding() << "    " << pair.second << "==" << ex(pair.second).subs(solution_substitution) << "\n";
                /*
                char yesno;
                cout << "Accept this solution? (Y/N) ";
                cin >> yesno;
                if (yesno == 'Y')
                    break;
                */
                break;
            }
        }

        // TODO: the number of graphs in the reduced sum will stabilize; can check this.

        graph_series = leibniz_graph_series;
    }
}
<commit_msg>Prepare reduce_mod_jacobi_iterative for interactive run.<commit_after>#include "../kontsevich_graph_series.hpp"
#include <ginac/ginac.h>
#include <iostream>
#include <fstream>
#include <limits>
#include "../util/continued_fraction.hpp"
#include <Eigen/Dense>
#include <Eigen/SparseCore>
#include <Eigen/SparseQR>
#include <Eigen/OrderingMethods>
using namespace std;
using namespace GiNaC;

typedef Eigen::Triplet<double> Triplet;
typedef Eigen::SparseMatrix<double> SparseMatrix;

double threshold = 1e-5;

int main(int argc, char* argv[])
{
    if (argc != 2 && argc != 3 && argc != 4)
    {
        cout << "Usage: " << argv[0] << " <graph-series-filename> [max-jac-indegree] [--solve]\n\n"
             << "Accepts only homogeneous power series: graphs with n internal vertices at order n.\n"
             << "The optional arguments [max-jacobiators] and [max-jac-indegree] restrict the types of differential consequences of Jacobi taken into account:\n"
             << "- [max-jacobiators] restricts the number of Jacobiators per differential consequence, while\n"
             << "- [max-jac-indegree] restricts the number of arrows falling on Jacobiators.\n"
             << "When the optional argument [--solve] is specified, the undetermined variables in the input are added to the linear system to-be-solved.\n";
        return 1;
    }

    size_t max_jac_indegree = numeric_limits<size_t>::max();
    if (argc == 3 || argc == 4)
        max_jac_indegree = stoi(argv[2]);

    // Reading in graph series
    string graph_series_filename(argv[1]);
    ifstream graph_series_file(graph_series_filename);
    parser coefficient_reader;
    bool homogeneous = true;
    map<size_t, set< vector<size_t> > > in_degrees;
    KontsevichGraphSeries<ex> graph_series = KontsevichGraphSeries<ex>::from_istream(graph_series_file,
        [&coefficient_reader](string s) -> ex { return coefficient_reader(s); },
        [&homogeneous, &in_degrees](KontsevichGraph graph, size_t order) -> bool
                                   {
                                       in_degrees[order].insert(graph.in_degrees());
                                       return homogeneous &= graph.internal() == order;
                                   }
    );
    size_t order = graph_series.precision();
    if (!homogeneous)
    {
        cerr << "Only accepting homogeneous power series: graphs with n internal vertices at order n.\n";
        return 1;
    }

    // Find number of external vertices
    // TODO: move to method in KontsevichGraphSum / KontsevichGraphSeries?
    size_t external = 0;
    for (size_t n = 0; n <= order; ++n)
    {
        if (graph_series[n].size() != 0)
        {
            external = graph_series[n].front().second.external();
            break;
        }
    }
    graph_series.reduce();

    size_t counter = 0;
    vector<symbol> coefficient_list;

    if (argc == 4 && string(argv[3]) == "--solve")
        for (auto namevar : coefficient_reader.get_syms())
            coefficient_list.push_back(ex_to<symbol>(namevar.second));

    map< pair<KontsevichGraph, KontsevichGraph::VertexPair>, symbol> kontsevich_jacobi_leibniz_graphs;

    KontsevichGraphSeries<ex> leibniz_graph_series = graph_series;

    while (true)
    {
        for (size_t n = 0; n <= order; ++n)
        {
            for (auto& term : graph_series[n])
            {
                KontsevichGraph& graph = term.second;
                // Note: we ignore the coefficient and sign of the graph
                for (KontsevichGraph::Vertex v : graph.internal_vertices())
                {
                    for (KontsevichGraph::Vertex w : graph.neighbors_in(v))
                    {
                        vector<KontsevichGraph::VertexPair> targets_template = graph.targets();
                        KontsevichGraph::VertexPair& target_pair_v = targets_template[(size_t)v - external];
                        // Check that there is no loop between v and w
                        if (target_pair_v.first == w || target_pair_v.second == w)
                            continue;
                        KontsevichGraph::VertexPair& target_pair_w = targets_template[(size_t)w - external];
                        // Check that the "Jacobiator" consisting of v and w falls on 3 distinct targets
                        KontsevichGraph::Vertex& a = target_pair_v.first;
                        KontsevichGraph::Vertex& b = target_pair_v.second;
                        KontsevichGraph::Vertex& c = (target_pair_w.first == v) ? target_pair_w.second : target_pair_w.first;
                        if (c == a || c == b)
                            continue;

                        // Build the list of references to bad targets (incoming edges on v or w, except the edge w -> v)
                        set<KontsevichGraph::Vertex*> bad_targets;
                        for (KontsevichGraph::Vertex u : graph.internal_vertices())
                        {
                            if (u == w)
                                continue;
                            KontsevichGraph::VertexPair& target_pair = targets_template[(size_t)u - external];
                            if (target_pair.first == v || target_pair.first == w)
                                bad_targets.insert(&target_pair.first);
                            if (target_pair.second == v || target_pair.second == w)
                                bad_targets.insert(&target_pair.second);
                        }
                        if (bad_targets.size() > max_jac_indegree)
                            continue;

                        symbol coefficient("c_" + to_string(counter));

                        // Normal form of Leibniz graph (three permutations of Jacobi, take minimal encoding, remember where Jacobiator is)
                        for (auto& bad_target : bad_targets)
                            *bad_target = v;
                        vector< vector<KontsevichGraph::Vertex> > jacobi_targets_choices({ { a, b, c },
                                                                                { b, c, a },
                                                                                { c, a, b } });
                        vector< pair<KontsevichGraph, KontsevichGraph::VertexPair> > leibniz_graphs;
                        for (auto jacobi_targets_choice : jacobi_targets_choices)
                        {
                            // Set Jacobiator targets to one of the three permutatations
                            a = jacobi_targets_choice[0];
                            b = jacobi_targets_choice[1];
                            c = jacobi_targets_choice[2];

                            vector<KontsevichGraph::VertexPair> d_targets = targets_template;

                            // Find permutation of vertex labels such that the list of targets is minimal with respect to the defined ordering
                            std::vector<KontsevichGraph::VertexPair> global_minimum = d_targets;
                            sort_pairs(global_minimum.begin(), global_minimum.end());

                            size_t d_internal = graph.internal();
                            size_t d_external = graph.external();

                            KontsevichGraph::VertexPair new_vw = {v, w};
                            std::vector<KontsevichGraph::Vertex> vertices(d_external + d_internal);
                            std::iota(vertices.begin(), vertices.end(), 0);
                            while (std::next_permutation(vertices.begin() + d_external, vertices.end()))
                            {
                                std::vector<KontsevichGraph::VertexPair> local_minimum = d_targets;
                                apply_permutation(d_internal, d_external, local_minimum, vertices);
                                if (local_minimum < global_minimum)
                                {
                                    global_minimum = local_minimum;
                                    // Find where Jacobiator is
                                    new_vw = { vertices[(size_t)v], vertices[(size_t)w] };
                                }
                            }
                            d_targets = global_minimum;

                            KontsevichGraph leibniz_graph(d_targets.size(), d_external, d_targets, 1, true);
                            leibniz_graphs.push_back({ leibniz_graph, new_vw });
                        }
                        pair< KontsevichGraph, KontsevichGraph::VertexPair> leibniz_normal_form = *min_element(leibniz_graphs.begin(), leibniz_graphs.end());

                        if (kontsevich_jacobi_leibniz_graphs.find(leibniz_normal_form) != kontsevich_jacobi_leibniz_graphs.end())
                            continue;

                        KontsevichGraphSum<ex> graph_sum;

                        // Replace bad targets by Leibniz rule:
                        vector<size_t> leibniz_sizes(bad_targets.size(), 2);
                        CartesianProduct leibniz_indices(leibniz_sizes);
                        for (auto leibniz_index = leibniz_indices.begin(); leibniz_index != leibniz_indices.end(); ++leibniz_index)
                        {
                            size_t idx = 0;
                            for (auto& bad_target : bad_targets)
                                *bad_target = (*leibniz_index)[idx++] == 0 ? v : w;
                            for (auto jacobi_targets_choice : jacobi_targets_choices)
                            {
                                // Set Jacobiator targets to one of the three permutatations
                                a = jacobi_targets_choice[0];
                                b = jacobi_targets_choice[1];
                                c = jacobi_targets_choice[2];

                                KontsevichGraph new_graph(targets_template.size(), external, targets_template, graph.sign());

                                graph_sum += KontsevichGraphSum<ex>({ { coefficient, new_graph } });
                            }
                        }

                        graph_sum.reduce();
                        if (graph_sum.size() != 0)
                        {
                            cerr << "\r" << ++counter;
                            coefficient_list.push_back(coefficient);
                            kontsevich_jacobi_leibniz_graphs[leibniz_normal_form] = coefficient;
                        }
                        leibniz_graph_series[n] -= graph_sum;
                    }
                }
            }
        }

        cout << "\nNumber of Leibniz graphs: " << kontsevich_jacobi_leibniz_graphs.size() << "\n";
        cout << "\nNumber of terms: " << leibniz_graph_series[order].size() << "\n";

        cout.flush();

        cerr << "\nReducing...\n";
        leibniz_graph_series.reduce();

        //lst equations;

        for (size_t n = 0; n <= order; ++n)
            for (auto& term : leibniz_graph_series[n])
            {
                cerr << term.second.encoding() << "    " << term.first << "==0\n";
                //equations.append(term.first);
            }

        // TODO: print Leibniz graphs at end (unconditionally)
        // TODO: don't re-do old graphs
        // TODO: first Jacobi, then normal form, then Leibniz rule

        /*
        // Set up sparse matrix linear system

        cerr << "Setting up linear system for numerical solution...\n";
        size_t rows = equations.nops();
        size_t cols = coefficient_list.size();

        Eigen::VectorXd b(rows);
        SparseMatrix matrix(rows,cols);

        vector<Triplet> tripletList;
        size_t idx = 0;
        for (ex equation : equations)
        {
            if (!is_a<add>(equation))
                equation = lst(equation);
            for (ex term : equation)
            {
                if (!is_a<mul>(term))
                    term = lst(term);
                double prefactor = 1;
                symbol coefficient("one");
                for (ex factor : term)
                {
                    if (is_a<numeric>(factor))
                        prefactor *= ex_to<numeric>(factor).to_double();
                    else if (is_a<symbol>(factor))
                        coefficient = ex_to<symbol>(factor);
                }
                if (coefficient.get_name() == "one") // constant term
                    b(idx) = -prefactor;
                else
                    tripletList.push_back(Triplet(idx,find(coefficient_list.begin(), coefficient_list.end(), coefficient) - coefficient_list.begin(), prefactor));
                    // NB: Eigen uses zero-based indices (contrast MATLAB, Mathematica)
            }
            ++idx;
        }

        matrix.setFromTriplets(tripletList.begin(), tripletList.end());

        cerr << "Solving linear system (" << rows << " x " << cols << ") numerically...\n";

        Eigen::SparseQR< SparseMatrix, Eigen::COLAMDOrdering<int> > qr(matrix);
        Eigen::VectorXd x = qr.solve(b);

        cerr << "Residual norm = " << (matrix * x - b).squaredNorm() << "\n";

        cerr << "Rounding...\n";
        x = x.unaryExpr([](double elem) { return fabs(elem) < threshold ? 0.0 : elem; });

        double residual_norm = (matrix * x - b).squaredNorm();
        cerr << "Still a solution? Residual norm = " << residual_norm << "\n";

        if (!isnan(residual_norm) && residual_norm < 1.0)
        {
            cerr << "Approximating numerical solution by rational solution...\n";

            lst zero_substitution;
            lst solution_substitution;
            for (int i = 0; i != x.size(); i++)
            {
                ex result = best_rational_approximation(x.coeff(i), threshold);
                if (result == 0)
                    zero_substitution.append(coefficient_list[i] == 0);
                else
                    solution_substitution.append(coefficient_list[i] == result);
            }

            cerr << "Substituting zeros...\n";

            KontsevichGraphSeries<ex> leibniz_graph_series_copy = leibniz_graph_series; // TODO: inefficient?

            for (auto& order: leibniz_graph_series_copy)
                for (auto& term : leibniz_graph_series_copy[order.first])
                    term.first = term.first.subs(zero_substitution);

            cerr << "Reducing zeros...\n";

            leibniz_graph_series_copy.reduce();

            for (size_t n = 0; n <= leibniz_graph_series_copy.precision(); ++n)
            {
                cout << "h^" << n << ":\n";
                for (auto& term : leibniz_graph_series_copy[n])
                {
                    cout << term.second.encoding() << "    " << term.first << "\n";
                }
            }

            cerr << "Verifying solution...\n";

            for (auto& order: leibniz_graph_series_copy)
                for (auto& term : leibniz_graph_series_copy[order.first])
                    term.first = term.first.subs(solution_substitution);

            leibniz_graph_series_copy.reduce();

            cout << "Do we really have a solution? " << (leibniz_graph_series_copy == 0 ? "Yes" : "No") << "\n";

            if (leibniz_graph_series_copy == 0)
            {
                for (auto pair : kontsevich_jacobi_leibniz_graphs)
                    if (pair.second != ex(pair.second).subs(solution_substitution))
                        cout << pair.first.first.encoding() << "    " << pair.second << "==" << ex(pair.second).subs(solution_substitution) << "\n";
                char yesno;
                cout << "Accept this solution? (Y/N) ";
                cin >> yesno;
                if (yesno == 'Y')
                    break;
                break;
            }
        }

        // TODO: the number of graphs in the reduced sum will stabilize; can check this.
        */

        char yesno;
        cout << "Next iteration? (Y/N) ";
        cin >> yesno;
        if (yesno != 'Y')
            break;

        graph_series = leibniz_graph_series;
    }
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <time.h>
#include "gtest/gtest.h"
#include "braincloud/BrainCloudClient.h"
#include "TestResult.h"
#include "json/json.h"
#include "TestBCSocialLeaderboard.h"

using namespace BrainCloud;

#define LB_ID "testLeaderboard"
#define SOCIAL_LB_ID "testSocialLeaderboard"
#define DYNAMIC_LB_ID "testDynamicLeaderboard"
#define REWARD_EVENT_ID "tournamentRewardId"
#define GROUP_LB_ID "testGroupLeaderboard"

TEST_F(TestBCSocialLeaderboard, GetSocialLeaderboard)
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->getSocialLeaderboard(LB_ID, true, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetSocialLeaderboardByVersion)
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->getSocialLeaderboardByVersion(LB_ID, true, 0, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetMultiSocialLeaderboard)
{
    // post a few scores first so we have some data
    PostScoreToNonDynamic();
    PostScoreToDynamic();

    TestResult tr;
    std::vector<std::string> lbIds;
    lbIds.push_back(LB_ID);
    lbIds.push_back(DYNAMIC_LB_ID);
    m_bc->getSocialLeaderboardService()->getMultiSocialLeaderboard(lbIds, 10, true, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, PostScore)
{
    PostScoreToNonDynamic();
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardVersions)
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardVersions(LB_ID, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardPageHigh)
{
    TestResult tr;
    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardPage(LB_ID, HIGH_TO_LOW, 0, 10, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardPageLow)
{
    TestResult tr;
    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardPage(LB_ID, LOW_TO_HIGH, 0, 10, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardViewHigh)
{
    TestResult tr;
    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardView(LB_ID, HIGH_TO_LOW, 4, 5, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardViewLow)
{
    TestResult tr;
    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardView(LB_ID, LOW_TO_HIGH, 4, 5, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalPageByVersion)
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardPageByVersion(LB_ID, HIGH_TO_LOW, 0, 10, 0, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalViewByVersion)
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardViewByVersion(LB_ID, HIGH_TO_LOW, 0, 10, 0, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, PostScoreToDynamic)
{
    PostScoreToDynamic();
}

TEST_F(TestBCSocialLeaderboard, PostScoreToDynamicNullRotationTime)
{
    TestResult tr;
    Json::FastWriter fw;
    Json::Value jsonData;
    jsonData["testKey"] = "TestValue";

    m_bc->getSocialLeaderboardService()->postScoreToDynamicLeaderboard(DYNAMIC_LB_ID, 100, fw.write(jsonData), HIGH_VALUE, NEVER, NULL, 2, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, PostScoreToDynamicDays)
{
	TestResult tr;
	Json::FastWriter fw;
	Json::Value jsonData;
	jsonData["testKey"] = "TestValue";

	m_bc->getSocialLeaderboardService()->postScoreToDynamicLeaderboardDays("TestDynamicDaysCpp", 100, fw.write(jsonData), HIGH_VALUE, NULL, 2, 3, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGroupSocialLeaderboard)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    m_bc->getSocialLeaderboardService()->getGroupSocialLeaderboard(SOCIAL_LB_ID, groupId.c_str(), &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGroupSocialLeaderboardByVersion)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    m_bc->getSocialLeaderboardService()->getGroupSocialLeaderboardByVersion(SOCIAL_LB_ID, groupId.c_str(), 0, &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetPlayersSocialLeaderboard)
{
	TestResult tr;

	std::vector<std::string> profileIds;
	profileIds.push_back(GetUser(UserA)->m_profileId);
	profileIds.push_back(GetUser(UserB)->m_profileId);

	m_bc->getSocialLeaderboardService()->getPlayersSocialLeaderboard(SOCIAL_LB_ID, profileIds, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetPlayersSocialLeaderboardByVersion)
{
	TestResult tr;

	std::vector<std::string> profileIds;
	profileIds.push_back(GetUser(UserA)->m_profileId);
	profileIds.push_back(GetUser(UserB)->m_profileId);

	m_bc->getSocialLeaderboardService()->getPlayersSocialLeaderboardByVersion(SOCIAL_LB_ID, profileIds, 0, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, ListAllLeaderboards)
{
	TestResult tr;

	m_bc->getSocialLeaderboardService()->listAllLeaderboards(&tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardEntryCount)
{
	TestResult tr;

	m_bc->getSocialLeaderboardService()->getGlobalLeaderboardEntryCount(LB_ID, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardEntryCountByVersion)
{
	TestResult tr;

	m_bc->getSocialLeaderboardService()->getGlobalLeaderboardEntryCountByVersion(LB_ID, 1, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, RemoveScore)
{
	PostScoreToNonDynamic();

	TestResult tr;
	m_bc->getSocialLeaderboardService()->removePlayerScore(LB_ID, -1, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetPlayerScore)
{
	PostScoreToNonDynamic();

	TestResult tr;
	m_bc->getSocialLeaderboardService()->getPlayerScore(LB_ID, -1, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetPlayerScoresFromLeaderboards)
{
	// post a few scores first so we have some data
	PostScoreToNonDynamic();
	PostScoreToDynamic();

	TestResult tr;
	std::vector<std::string> lbIds;
	lbIds.push_back(LB_ID);
	lbIds.push_back(DYNAMIC_LB_ID);
	m_bc->getSocialLeaderboardService()->getPlayerScoresFromLeaderboards(lbIds, &tr);
	tr.run(m_bc);
}

void TestBCSocialLeaderboard::PostScoreToDynamic()
{
	srand(time(NULL));

    TestResult tr;
    Json::FastWriter fw;
    Json::Value jsonData;
    jsonData["testKey"] = "TestValue";

    time_t t = time(0);
    struct tm * time = localtime(&t);
    time->tm_mday += 1;
    mktime(time);

	std::string name = DYNAMIC_LB_ID + std::to_string(rand());

    m_bc->getSocialLeaderboardService()->postScoreToDynamicLeaderboard(name.c_str(), 100, fw.write(jsonData), HIGH_VALUE, WEEKLY, time, 2, &tr);
    tr.run(m_bc);
}

void TestBCSocialLeaderboard::PostScoreToNonDynamic()
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->postScoreToLeaderboard(LB_ID, 100, "", &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, PostScoreToGroupLeaderboard)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    Json::FastWriter fw;
    Json::Value jsonData;
    jsonData["testKey"] = "TestValue";

    m_bc->getSocialLeaderboardService()->postScoreToGroupLeaderboard(GROUP_LB_ID, groupId.c_str(), 0, fw.write(jsonData), &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, RemoveGroupScore)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    Json::FastWriter fw;
    Json::Value jsonData;
    jsonData["testKey"] = "TestValue";

    m_bc->getSocialLeaderboardService()->postScoreToGroupLeaderboard(GROUP_LB_ID, groupId.c_str(), 100, fw.write(jsonData), &tr);
    tr.run(m_bc);

    m_bc->getSocialLeaderboardService()->removeGroupScore(GROUP_LB_ID, groupId.c_str(), -1, &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGroupLeaderboardView)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    m_bc->getSocialLeaderboardService()->getGroupLeaderboardView(GROUP_LB_ID, groupId.c_str(), HIGH_TO_LOW, 5, 5, &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGroupLeaderboardViewByVersion)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    m_bc->getSocialLeaderboardService()->getGroupLeaderboardViewByVersion(GROUP_LB_ID, groupId.c_str(), 1, HIGH_TO_LOW, 5, 5, &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}<commit_msg>once again updating groupLeaderboardconfig<commit_after>#include <stdlib.h>
#include <time.h>
#include "gtest/gtest.h"
#include "braincloud/BrainCloudClient.h"
#include "TestResult.h"
#include "json/json.h"
#include "TestBCSocialLeaderboard.h"

using namespace BrainCloud;

#define LB_ID "testLeaderboard"
#define SOCIAL_LB_ID "testSocialLeaderboard"
#define DYNAMIC_LB_ID "testDynamicLeaderboard"
#define REWARD_EVENT_ID "tournamentRewardId"
#define GROUP_LB_ID "groupLeaderboardConfig"

TEST_F(TestBCSocialLeaderboard, GetSocialLeaderboard)
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->getSocialLeaderboard(LB_ID, true, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetSocialLeaderboardByVersion)
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->getSocialLeaderboardByVersion(LB_ID, true, 0, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetMultiSocialLeaderboard)
{
    // post a few scores first so we have some data
    PostScoreToNonDynamic();
    PostScoreToDynamic();

    TestResult tr;
    std::vector<std::string> lbIds;
    lbIds.push_back(LB_ID);
    lbIds.push_back(DYNAMIC_LB_ID);
    m_bc->getSocialLeaderboardService()->getMultiSocialLeaderboard(lbIds, 10, true, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, PostScore)
{
    PostScoreToNonDynamic();
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardVersions)
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardVersions(LB_ID, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardPageHigh)
{
    TestResult tr;
    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardPage(LB_ID, HIGH_TO_LOW, 0, 10, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardPageLow)
{
    TestResult tr;
    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardPage(LB_ID, LOW_TO_HIGH, 0, 10, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardViewHigh)
{
    TestResult tr;
    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardView(LB_ID, HIGH_TO_LOW, 4, 5, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardViewLow)
{
    TestResult tr;
    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardView(LB_ID, LOW_TO_HIGH, 4, 5, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalPageByVersion)
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardPageByVersion(LB_ID, HIGH_TO_LOW, 0, 10, 0, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalViewByVersion)
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->getGlobalLeaderboardViewByVersion(LB_ID, HIGH_TO_LOW, 0, 10, 0, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, PostScoreToDynamic)
{
    PostScoreToDynamic();
}

TEST_F(TestBCSocialLeaderboard, PostScoreToDynamicNullRotationTime)
{
    TestResult tr;
    Json::FastWriter fw;
    Json::Value jsonData;
    jsonData["testKey"] = "TestValue";

    m_bc->getSocialLeaderboardService()->postScoreToDynamicLeaderboard(DYNAMIC_LB_ID, 100, fw.write(jsonData), HIGH_VALUE, NEVER, NULL, 2, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, PostScoreToDynamicDays)
{
	TestResult tr;
	Json::FastWriter fw;
	Json::Value jsonData;
	jsonData["testKey"] = "TestValue";

	m_bc->getSocialLeaderboardService()->postScoreToDynamicLeaderboardDays("TestDynamicDaysCpp", 100, fw.write(jsonData), HIGH_VALUE, NULL, 2, 3, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGroupSocialLeaderboard)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    m_bc->getSocialLeaderboardService()->getGroupSocialLeaderboard(SOCIAL_LB_ID, groupId.c_str(), &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGroupSocialLeaderboardByVersion)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    m_bc->getSocialLeaderboardService()->getGroupSocialLeaderboardByVersion(SOCIAL_LB_ID, groupId.c_str(), 0, &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetPlayersSocialLeaderboard)
{
	TestResult tr;

	std::vector<std::string> profileIds;
	profileIds.push_back(GetUser(UserA)->m_profileId);
	profileIds.push_back(GetUser(UserB)->m_profileId);

	m_bc->getSocialLeaderboardService()->getPlayersSocialLeaderboard(SOCIAL_LB_ID, profileIds, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetPlayersSocialLeaderboardByVersion)
{
	TestResult tr;

	std::vector<std::string> profileIds;
	profileIds.push_back(GetUser(UserA)->m_profileId);
	profileIds.push_back(GetUser(UserB)->m_profileId);

	m_bc->getSocialLeaderboardService()->getPlayersSocialLeaderboardByVersion(SOCIAL_LB_ID, profileIds, 0, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, ListAllLeaderboards)
{
	TestResult tr;

	m_bc->getSocialLeaderboardService()->listAllLeaderboards(&tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardEntryCount)
{
	TestResult tr;

	m_bc->getSocialLeaderboardService()->getGlobalLeaderboardEntryCount(LB_ID, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGlobalLeaderboardEntryCountByVersion)
{
	TestResult tr;

	m_bc->getSocialLeaderboardService()->getGlobalLeaderboardEntryCountByVersion(LB_ID, 1, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, RemoveScore)
{
	PostScoreToNonDynamic();

	TestResult tr;
	m_bc->getSocialLeaderboardService()->removePlayerScore(LB_ID, -1, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetPlayerScore)
{
	PostScoreToNonDynamic();

	TestResult tr;
	m_bc->getSocialLeaderboardService()->getPlayerScore(LB_ID, -1, &tr);
	tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetPlayerScoresFromLeaderboards)
{
	// post a few scores first so we have some data
	PostScoreToNonDynamic();
	PostScoreToDynamic();

	TestResult tr;
	std::vector<std::string> lbIds;
	lbIds.push_back(LB_ID);
	lbIds.push_back(DYNAMIC_LB_ID);
	m_bc->getSocialLeaderboardService()->getPlayerScoresFromLeaderboards(lbIds, &tr);
	tr.run(m_bc);
}

void TestBCSocialLeaderboard::PostScoreToDynamic()
{
	srand(time(NULL));

    TestResult tr;
    Json::FastWriter fw;
    Json::Value jsonData;
    jsonData["testKey"] = "TestValue";

    time_t t = time(0);
    struct tm * time = localtime(&t);
    time->tm_mday += 1;
    mktime(time);

	std::string name = DYNAMIC_LB_ID + std::to_string(rand());

    m_bc->getSocialLeaderboardService()->postScoreToDynamicLeaderboard(name.c_str(), 100, fw.write(jsonData), HIGH_VALUE, WEEKLY, time, 2, &tr);
    tr.run(m_bc);
}

void TestBCSocialLeaderboard::PostScoreToNonDynamic()
{
    TestResult tr;

    m_bc->getSocialLeaderboardService()->postScoreToLeaderboard(LB_ID, 100, "", &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, PostScoreToGroupLeaderboard)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    Json::FastWriter fw;
    Json::Value jsonData;
    jsonData["testKey"] = "TestValue";

    m_bc->getSocialLeaderboardService()->postScoreToGroupLeaderboard(GROUP_LB_ID, groupId.c_str(), 0, fw.write(jsonData), &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, RemoveGroupScore)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    Json::FastWriter fw;
    Json::Value jsonData;
    jsonData["testKey"] = "TestValue";

    m_bc->getSocialLeaderboardService()->postScoreToGroupLeaderboard(GROUP_LB_ID, groupId.c_str(), 100, fw.write(jsonData), &tr);
    tr.run(m_bc);

    m_bc->getSocialLeaderboardService()->removeGroupScore(GROUP_LB_ID, groupId.c_str(), -1, &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGroupLeaderboardView)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    m_bc->getSocialLeaderboardService()->getGroupLeaderboardView(GROUP_LB_ID, groupId.c_str(), HIGH_TO_LOW, 5, 5, &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCSocialLeaderboard, GetGroupLeaderboardViewByVersion)
{
    TestResult tr;
    m_bc->getGroupService()->createGroup("testGroup", "test", false, "", "", "", "", &tr);
    tr.run(m_bc);

    std::string groupId = tr.m_response["data"]["groupId"].asString();

    m_bc->getSocialLeaderboardService()->getGroupLeaderboardViewByVersion(GROUP_LB_ID, groupId.c_str(), 1, HIGH_TO_LOW, 5, 5, &tr);
    tr.run(m_bc);

    m_bc->getGroupService()->deleteGroup(groupId.c_str(), -1, &tr);
    tr.run(m_bc);
}<|endoftext|>


<commit_before>/***********************************************************************
 load_jpeg.cpp - Example showing how to insert BLOB data into the
	database from a file.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "images.h"
#include "printdata.h"

#include <fstream>

using namespace std;
using namespace mysqlpp;

// This is just an implementation detail for the example.  Skip down to
// main() for the concept this example is trying to demonstrate.
static bool
is_jpeg(const char* img_data)
{
	const unsigned char* idp =
			reinterpret_cast<const unsigned char*>(img_data);
	return (idp[0] == 0xFF) && (idp[1] == 0xD8) &&
			((memcmp(idp + 6, "JFIF", 4) == 0) ||
			 (memcmp(idp + 6, "Exif", 4) == 0));
}

// Another implementation detail.  Skip to main().
static bool
load_jpeg_file(const mysqlpp::examples::CommandLine& cmdline,
		images& img, string& img_name)
{
	if (cmdline.extra_args().size() == 0) {
		// Nothing for us to do here.  Caller will insert NULL BLOB.
		return true;
	}

	// Got a file's name on the command line, so open it.
	img_name = cmdline.extra_args()[0];
	ifstream img_file(img_name.c_str(), ios::ate | ios::binary);
	if (img_file) {
		// File opened, so try to slurp its contents into RAM.  The key
		// thing to get from this function is that we're storing the
		// binary data in a mysqlpp::sql_blob value, which we assign from
		// a C++ string (stringstream::str()), thus not truncating the
		// string at the first embedded null character.
		stringstream sstr;
		sstr << img_file.rdbuf();
		img.data.data = sstr.str();

		// Check JPEG data for sanity.
		//
		// All these 'data's sure do look foolish, don't they?  Sorry,
		// we're not trying to be obscure here, it's just a coincidence
		// of naming.  The triple 'data' in the is_jpeg() call breaks
		// down like this:
		//
		// 1. We're accessing to the JPEG BLOB column, images.data.
		// 2. We then dig down to the mysqlpp::sql_blob object through
		//    its mysqlpp::Null<> wrapper, which we need to allow a
		//    "NULL JPEG" in the DB when the file doesn't exist.
		// 3. Finally, we need to pass a raw, unterminated char buffer
		//    pointer to is_jpeg(), which mysqlpp::sql_blob::data()
		//    returns, mirroring the C++'s std::string interface.
		if ((img.data.data.size() > 10) &&
				is_jpeg(img.data.data.data())) {
			return true;
		}
		else {
			cerr << '"' << img_file << "\" isn't a JPEG file!" << endl;
		}
	}

	cmdline.print_usage("[jpeg_file]");
	return false;
}

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Load the file named on the command line
		images img(mysqlpp::null, mysqlpp::null);
		string img_name("NULL");
		if (load_jpeg_file(cmdline, img, img_name)) {
			// Insert image data or SQL NULL into the images.data BLOB
			// column.  The key here is that we're holding the raw
			// binary data in a mysqlpp::sql_blob, which avoids data
			// conversion problems that can lead to treating BLOB data
			// as C strings, thus causing null-truncation.  The fact
			// that we're using SSQLS here is a side issue, simply
			// demonstrating that mysqlpp::Null<mysqlpp::sql_blob> is
			// now legal in SSQLS, as of MySQL++ 3.0.7.
			Query query = con.query();
			query.insert(img);
			SimpleResult res = query.execute();

			// Report successful insertion
			cout << "Inserted \"" << img_name <<
					"\" into images table, " << img.data.data.size() <<
					" bytes, ID " << res.insert_id() << endl;
		}
	}
	catch (const BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}
<commit_msg>Comment grammar fix<commit_after>/***********************************************************************
 load_jpeg.cpp - Example showing how to insert BLOB data into the
	database from a file.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "images.h"
#include "printdata.h"

#include <fstream>

using namespace std;
using namespace mysqlpp;

// This is just an implementation detail for the example.  Skip down to
// main() for the concept this example is trying to demonstrate.
static bool
is_jpeg(const char* img_data)
{
	const unsigned char* idp =
			reinterpret_cast<const unsigned char*>(img_data);
	return (idp[0] == 0xFF) && (idp[1] == 0xD8) &&
			((memcmp(idp + 6, "JFIF", 4) == 0) ||
			 (memcmp(idp + 6, "Exif", 4) == 0));
}

// Another implementation detail.  Skip to main().
static bool
load_jpeg_file(const mysqlpp::examples::CommandLine& cmdline,
		images& img, string& img_name)
{
	if (cmdline.extra_args().size() == 0) {
		// Nothing for us to do here.  Caller will insert NULL BLOB.
		return true;
	}

	// Got a file's name on the command line, so open it.
	img_name = cmdline.extra_args()[0];
	ifstream img_file(img_name.c_str(), ios::ate | ios::binary);
	if (img_file) {
		// File opened, so try to slurp its contents into RAM.  The key
		// thing to get from this function is that we're storing the
		// binary data in a mysqlpp::sql_blob value, which we assign from
		// a C++ string (stringstream::str()), thus not truncating the
		// string at the first embedded null character.
		stringstream sstr;
		sstr << img_file.rdbuf();
		img.data.data = sstr.str();

		// Check JPEG data for sanity.
		//
		// All these 'data's sure do look foolish, don't they?  Sorry,
		// we're not trying to be obscure here, it's just a coincidence
		// of naming.  The triple 'data' in the is_jpeg() call breaks
		// down like this:
		//
		// 1. We're accessing to the JPEG BLOB column, images.data.
		// 2. We then dig down to the mysqlpp::sql_blob object through
		//    its mysqlpp::Null<> wrapper, which we need to allow a
		//    "NULL JPEG" in the DB when the file doesn't exist.
		// 3. Finally, we need to pass a raw, unterminated char buffer
		//    pointer to is_jpeg(), which mysqlpp::sql_blob::data()
		//    returns, mirroring C++ std::string interface.
		if ((img.data.data.size() > 10) &&
				is_jpeg(img.data.data.data())) {
			return true;
		}
		else {
			cerr << '"' << img_file << "\" isn't a JPEG file!" << endl;
		}
	}

	cmdline.print_usage("[jpeg_file]");
	return false;
}

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Load the file named on the command line
		images img(mysqlpp::null, mysqlpp::null);
		string img_name("NULL");
		if (load_jpeg_file(cmdline, img, img_name)) {
			// Insert image data or SQL NULL into the images.data BLOB
			// column.  The key here is that we're holding the raw
			// binary data in a mysqlpp::sql_blob, which avoids data
			// conversion problems that can lead to treating BLOB data
			// as C strings, thus causing null-truncation.  The fact
			// that we're using SSQLS here is a side issue, simply
			// demonstrating that mysqlpp::Null<mysqlpp::sql_blob> is
			// now legal in SSQLS, as of MySQL++ 3.0.7.
			Query query = con.query();
			query.insert(img);
			SimpleResult res = query.execute();

			// Report successful insertion
			cout << "Inserted \"" << img_name <<
					"\" into images table, " << img.data.data.size() <<
					" bytes, ID " << res.insert_id() << endl;
		}
	}
	catch (const BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}
<|endoftext|>


<commit_before>#include "glfw.h"

#include <Vortex2D/Vortex2D.h>
#include <Vortex2D/Renderer/Device.h>
#include <Vortex2D/Renderer/RenderWindow.h>

#include "RenderExample.h"
#include "SmokeExample.h"

#include <iostream>
#include <memory>
#include <functional>
#include <chrono>

using namespace Vortex2D;

glm::vec4 green = glm::vec4(35.0f, 163.0f, 143.0f, 255.0f)/glm::vec4(255.0f);
glm::vec4 gray = glm::vec4(182.0f,172.0f,164.0f, 255.0f)/glm::vec4(255.0f);
glm::vec4 blue = glm::vec4(99.0f, 155.0f, 188.0f, 255.0f)/glm::vec4(255.0f);

glm::ivec2 size = {1000,1000};
float scale = 4;

Vortex2D::Renderer::Device* device;
Vortex2D::Renderer::RenderTarget* target;

std::unique_ptr<Example> example;

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (action != GLFW_PRESS) return;

    switch (key)
    {
        case GLFW_KEY_1:
            //example.reset(new RenderExample(*device, size));
            break;
        case GLFW_KEY_2:
            example.reset(new SmokeExample(*device, {size, scale}, 0.033f));
            break;
        case GLFW_KEY_3:
            //example.reset(new ObstacleSmokeExample(size, 0.033f));
            break;
        case GLFW_KEY_4:
            //example.reset(new WaterExample(size, 0.033f));
            break;
        case GLFW_KEY_5:
            //example.reset(new ScaleWaterExample(size, 0.033f));
        default:
            break;
    }

    Vortex2D::Renderer::RenderState t(*target);
    t.ColorBlend
            .setBlendEnable(true)
            .setAlphaBlendOp(vk::BlendOp::eAdd)
            .setColorBlendOp(vk::BlendOp::eAdd)
            .setSrcColorBlendFactor(vk::BlendFactor::eSrcAlpha)
            .setSrcAlphaBlendFactor(vk::BlendFactor::eOne)
            .setDstColorBlendFactor(vk::BlendFactor::eOneMinusSrcAlpha)
            .setDstAlphaBlendFactor(vk::BlendFactor::eZero);

    example->Initialize(t);

    target->Record([&](vk::CommandBuffer commandBuffer)
    {
        Renderer::Clear(size.x, size.y, {0.5f, 0.5f, 0.5f, 1.0f}).Draw(commandBuffer);
        example->Draw(commandBuffer, t);
    });
}

int main()
{
    try
    {
        auto colour = glm::vec4{99.0f,96.0f,93.0f,255.0f} / glm::vec4(255.0f);

        GLFWApp mainWindow(size.x, size.y);

        glfwSetKeyCallback(mainWindow.GetWindow(), key_callback);

        Renderer::Device device_(mainWindow.GetPhysicalDevice(),
                                 mainWindow.GetSurface());
        device = &device_;

        Renderer::RenderWindow window(device_, mainWindow.GetSurface(), size.x, size.y);
        target = &window;

        example.reset(new SmokeExample(device_, {size, scale}, 0.033f));

        Vortex2D::Renderer::RenderState t(window);
        t.ColorBlend
                .setBlendEnable(true)
                .setAlphaBlendOp(vk::BlendOp::eAdd)
                .setColorBlendOp(vk::BlendOp::eAdd)
                .setSrcColorBlendFactor(vk::BlendFactor::eSrcAlpha)
                .setSrcAlphaBlendFactor(vk::BlendFactor::eOne)
                .setDstColorBlendFactor(vk::BlendFactor::eOneMinusSrcAlpha)
                .setDstAlphaBlendFactor(vk::BlendFactor::eZero);

        example->Initialize(t);

        window.Record([&](vk::CommandBuffer commandBuffer)
        {
            Renderer::Clear(size.x, size.y, {0.5f, 0.5f, 0.5f, 1.0f}).Draw(commandBuffer);
            example->Draw(commandBuffer, t);
        });

        while(!mainWindow.ShoudCloseWindow())
        {
            glfwPollEvents();

            auto start = std::chrono::system_clock::now();

            example->Update(window.Orth, glm::mat4());
            window.Submit({example->Semaphore()});

            auto end = std::chrono::system_clock::now();
            auto duration = end - start;
            auto title = std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count()) + "ms";
            glfwSetWindowTitle(mainWindow.GetWindow(), title.c_str());
        }

        device_.Handle().waitIdle();

        example.reset();
    }
    catch (const std::exception& error)
    {
        std::cout << "exception: " << error.what() << std::endl;
    }
}
<commit_msg>simplify slightly main examples<commit_after>#include "glfw.h"

#include <Vortex2D/Vortex2D.h>
#include <Vortex2D/Renderer/Device.h>
#include <Vortex2D/Renderer/RenderWindow.h>

#include "RenderExample.h"
#include "SmokeExample.h"

#include <iostream>
#include <memory>
#include <functional>
#include <chrono>

using namespace Vortex2D;

glm::vec4 green = glm::vec4(35.0f, 163.0f, 143.0f, 255.0f)/glm::vec4(255.0f);
glm::vec4 gray = glm::vec4(182.0f,172.0f,164.0f, 255.0f)/glm::vec4(255.0f);
glm::vec4 blue = glm::vec4(99.0f, 155.0f, 188.0f, 255.0f)/glm::vec4(255.0f);
glm::vec4 colour = glm::vec4{99.0f,96.0f,93.0f,255.0f} / glm::vec4(255.0f);

glm::ivec2 size = {1000,1000};
float scale = 4;

Vortex2D::Renderer::Device* device;
Vortex2D::Renderer::RenderTarget* target;

std::unique_ptr<Vortex2D::Renderer::Drawable> example;

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (action != GLFW_PRESS) return;

    switch (key)
    {
        case GLFW_KEY_1:
            example.reset(new RenderExample(*device, size));
            break;
        case GLFW_KEY_2:
            example.reset(new SmokeExample(*device, {size, scale}, 0.033f));
            break;
        case GLFW_KEY_3:
            //example.reset(new ObstacleSmokeExample(size, 0.033f));
            break;
        case GLFW_KEY_4:
            //example.reset(new WaterExample(size, 0.033f));
            break;
        case GLFW_KEY_5:
            //example.reset(new ScaleWaterExample(size, 0.033f));
        default:
            break;
    }

    Vortex2D::Renderer::RenderState t(*target);
    t.ColorBlend
            .setBlendEnable(true)
            .setAlphaBlendOp(vk::BlendOp::eAdd)
            .setColorBlendOp(vk::BlendOp::eAdd)
            .setSrcColorBlendFactor(vk::BlendFactor::eSrcAlpha)
            .setSrcAlphaBlendFactor(vk::BlendFactor::eOne)
            .setDstColorBlendFactor(vk::BlendFactor::eOneMinusSrcAlpha)
            .setDstAlphaBlendFactor(vk::BlendFactor::eZero);

    example->Initialize(t);

    target->Record([&](vk::CommandBuffer commandBuffer)
    {
        Renderer::Clear(size.x, size.y, {0.5f, 0.5f, 0.5f, 1.0f}).Draw(commandBuffer);
        example->Draw(commandBuffer, t);
    });
}

int main()
{
    try
    {
        GLFWApp mainWindow(size.x, size.y);

        glfwSetKeyCallback(mainWindow.GetWindow(), key_callback);

        Renderer::Device device_(mainWindow.GetPhysicalDevice(),
                                 mainWindow.GetSurface());
        device = &device_;

        Renderer::RenderWindow window(device_, mainWindow.GetSurface(), size.x, size.y);
        target = &window;

        target->Record([&](vk::CommandBuffer commandBuffer)
        {
            Renderer::Clear(size.x, size.y, {0.5f, 0.5f, 0.5f, 1.0f}).Draw(commandBuffer);
        });

        while(!mainWindow.ShoudCloseWindow())
        {
            glfwPollEvents();

            auto start = std::chrono::system_clock::now();

            if (example) example->Update(window.Orth, glm::mat4());
            window.Submit();

            auto end = std::chrono::system_clock::now();
            auto duration = end - start;
            auto title = std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count()) + "ms";
            glfwSetWindowTitle(mainWindow.GetWindow(), title.c_str());
        }

        device_.Handle().waitIdle();

        example.reset();
    }
    catch (const std::exception& error)
    {
        std::cout << "exception: " << error.what() << std::endl;
    }
}
<|endoftext|>


<commit_before>#include <bulk.hpp>
#include <iostream>

int main() {
    bulk::spawn(bulk::available_processors(), [](int s, int p) {
        for (int t = 0; t < p; ++t) {
            bulk::send<int, int>(t, s, s);
        }

        bulk::sync();

        if (s == 0) {
            for (auto message : bulk::messages<int, int>()) {
                std::cout << message.tag << ", " << message.content << std::endl;
            }
        }
    });

    return 0;
}
<commit_msg>Update syntax for message passing example<commit_after>#include <bulk.hpp>
#include <iostream>

int main() {
    auto center = bulk::center();
    center.spawn(center.available_processors(), [&center](int s, int p) {
        for (int t = 0; t < p; ++t) {
            center.send<int, int>(t, s, s);
        }

        center.sync();

        if (s == 0) {
            for (auto message : center.messages<int, int>()) {
                std::cout << message.tag << ", " << message.content << std::endl;
            }
        }
    });

    return 0;
}
<|endoftext|>


<commit_before>/*
Author: vpetrigo
Task:
   a, b, c, d, e, f.

   -   .

       .

    ,       0.

     ,      y=kx+b,      1,    k  b.

     (x0, y0),      2,    x0  y0.

       x=x0, y  ,      3,    x0.

       y=y0, x  ,      4,    y0.

    (x, y)   ,      5.
Sample Input 1:
1
0
0
1
3
3
Sample Output 1:
2 3 3

Sample Input 2:
1
1
2
2
1
2
Sample Output 2:
1 -1 1

Sample Input 3:
0
2
0
4
1
2
Sample Output 3:
4 0.5

Sample Input 4:
2
3
4
6
1
2
Sample Output 4:
1 -0.666667 0.333333

Sample Input 5:
0
1
0
3
5
15
Sample Output 5:
4 5

Sample Input 6:
1
0
1
0
3
3

Sample Output 6:
3 3

*/

#include <iostream>

using namespace std;

int main() {
    double a, b, c, d, e, f;
    double x, y;
    const int no_roots = 0;
    const int kx_roots = 1;
    const int one_xy_root = 2;
    const int one_x = 3;
    const int one_y = 4;
    const int inf_roots = 5;

    cin >> a >> b >> c >> d >> e >> f;

    double det = a * d - b * c;
    double det_x = (e * d - b * f);
    double det_y = (a * f - e * c);

    if (det != 0) {
        x = det_x / det;
        y = det_y / det;
        cout << one_xy_root << ' ' << x << ' ' << y;
    }
    else {
        if (a == 0 && b == 0 && c == 0 && d == 0) {
            if (e != 0 || f != 0) {
                cout << no_roots;
            }
            else {
                cout << inf_roots;
            }
        }
        else {
            if (det_x != 0 || det_y != 0) {
                cout << no_roots;
            }
            else if (b == 0) {
                x = e / a;
                cout << one_x << ' ' << x;
            }
            else if (a == 0) {
                y = e / b;
                cout << one_y  << ' ' << y;
            }
            else {
                double k = -a / b;
                double bi = e / b;

                cout << kx_roots << ' ' << k << ' ' << bi;
            }
        }
    }

    return 0;
}<commit_msg>Solution for week 4, task 12<commit_after>/*
Author: vpetrigo
Task:
   a, b, c, d, e, f.

   -   .

       .

    ,       0.

     ,      y=kx+b,      1,    k  b.

     (x0, y0),      2,    x0  y0.

       x=x0, y  ,      3,    x0.

       y=y0, x  ,      4,    y0.

    (x, y)   ,      5.
Sample Input 1:
1
0
0
1
3
3
Sample Output 1:
2 3 3

Sample Input 2:
1
1
2
2
1
2
Sample Output 2:
1 -1 1

Sample Input 3:
0
2
0
4
1
2
Sample Output 3:
4 0.5

Sample Input 4:
2
3
4
6
1
2
Sample Output 4:
1 -0.666667 0.333333

Sample Input 5:
0
1
0
3
5
15
Sample Output 5:
4 5

Sample Input 6:
1
0
1
0
3
3

Sample Output 6:
3 3

*/

#include <iostream>

using namespace std;

int main() {
    double a, b, c, d, e, f;
    double x, y;
    const int no_roots = 0;
    const int kx_roots = 1;
    const int one_xy_root = 2;
    const int one_x = 3;
    const int one_y = 4;
    const int inf_roots = 5;

    cin >> a >> b >> c >> d >> e >> f;

    double det = a * d - b * c;
    double det_x = (e * d - b * f);
    double det_y = (a * f - e * c);
    bool x_null = a == 0 && c == 0;
    bool y_null = b == 0 && d == 0;

    if (det != 0) {
        x = det_x / det;
        y = det_y / det;
        cout << one_xy_root << ' ' << x << ' ' << y;
    }
    else {
        if (det_x == 0 && det_y == 0) {
            if (x_null && y_null) {
                if (e != 0 || f != 0) {
                    cout << no_roots;
                }
                else {
                    cout << inf_roots;
                }
            }
            else if (x_null) {
                if (b != 0) {
                    y = e / b;
                }
                else {
                    y = f / d;
                }

                cout << one_y << ' ' << y;
            }
            else if (y_null) {
                if (a != 0) {
                    x = e / a;
                }
                else {
                    x = f / c;
                }

                cout << one_x << ' ' << x;
            }
            else {
                double bi, k;

                if (b != 0) {
                    bi = e / b;
                    k = -a / b;
                }
                else {
                    bi = f / d;
                    k = -c / d;
                }

                cout << kx_roots << ' ' << k << ' ' << bi;
            }
        }
        else {
            cout << no_roots;
        }
    }

    return 0;
}<|endoftext|>


<commit_before>#pragma once

#include <array>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

#include <boost/algorithm/string.hpp>
#include <boost/optional.hpp>
#include <boost/variant.hpp>

#include <blackhole/detail/config/noexcept.hpp>

namespace blackhole {

namespace formatter {

namespace string {

namespace parser {

class error_t : public std::runtime_error {
    const uint pos;
    const std::string inspect;

public:
    error_t(uint pos, const std::string& pattern, const std::string& reason) :
        std::runtime_error("parser error: " + reason),
        pos(pos),
        inspect(
            "parser error: " +  reason + "\n" +
            pattern + "\n" +
            std::string(pos, '~') + "^"
        )
    {}

    ~error_t() BLACKHOLE_NOEXCEPT {}

    std::string detail() const {
        return inspect;
    }
};

class broken_t : public error_t {
public:
    broken_t(uint pos, const std::string& pattern) :
        error_t(pos, pattern, "broken parser")
    {}
};

class exhausted_t : public error_t {
public:
    exhausted_t(uint pos, const std::string& pattern) :
        error_t(pos, pattern, "exhausted state")
    {}
};

class illformed_t : public error_t {
public:
    illformed_t(uint pos, const std::string& pattern) :
        error_t(pos, pattern, "illformed pattern")
    {}
};

class invalid_placeholder_t : public error_t {
public:
    invalid_placeholder_t(uint pos, const std::string& pattern) :
        error_t(pos, pattern, "invalid placeholder name (only [a-zA-Z0-9] allowed)")
    {}
};

}

struct literal_t {
    std::string value;
};

namespace placeholder {

struct required_t {
    std::string name;
};

struct optional_t {
    std::string name;
    std::string prefix;
    std::string suffix;
};

struct variadic_t {
    struct key_t {};
    struct value_t {};

    typedef boost::variant<
        literal_t,
        key_t,
        value_t
    > pattern_t;

    std::string prefix;
    std::string suffix;
    std::vector<pattern_t> pattern;
    std::string separator;

    variadic_t() :
        pattern(default_pattern()),
        separator(", ")
    {}

private:
    static
    std::vector<pattern_t>
    default_pattern() {
        return { key_t(), literal_t{ ": " }, value_t() };
    }
};

}

typedef boost::variant<
    literal_t,
    placeholder::required_t,
    placeholder::optional_t,
    placeholder::variadic_t
> token_t;

static const std::array<char, 2> PH_BEGIN = {{ '%', '(' }};
static const std::array<char, 2> PH_END   = {{ ')', 's' }};
static const std::array<char, 3> PH_VARIADIC = {{ '.', '.', '.' }};

class parser_t {
    enum state_t {
        whatever,
        literal,
        placeholder,
        broken
    };

    std::string pattern;
    std::string::const_iterator pos;
    const std::string::const_iterator begin;
    const std::string::const_iterator end;
    state_t state;

public:
    parser_t(std::string pattern) :
        pattern(std::move(pattern)),
        pos(this->pattern.begin()),
        begin(this->pattern.begin()),
        end(this->pattern.end()),
        state(whatever)
    {}

    boost::optional<token_t>
    next() {
        if (state == broken) {
            throw_<parser::broken_t>();
        }

        if (pos == end) {
            return boost::optional<token_t>();
        }

        switch (state) {
        case whatever:
            return parse_whatever();
        case literal:
            return parse_literal();
        case placeholder:
            return parse_placeholder();
        case broken:
            throw_<parser::broken_t>();
        default:
            BOOST_ASSERT(false);
        }
    }

private:
    boost::optional<token_t>
    parse_whatever() {
        if (starts_with(pos, end, PH_BEGIN)) {
            pos += PH_BEGIN.size();
            state = placeholder;
        } else {
            state = literal;
        }

        return next();
    }

    token_t
    parse_literal() {
        literal_t literal;

        while (pos != end) {
            if (starts_with(pos, end, PH_BEGIN)) {
                pos += PH_BEGIN.size();
                state = placeholder;
                return literal;
            }

            literal.value.push_back(*pos);
            pos++;
        }

        return literal;
    }

    token_t
    parse_placeholder() {
        if (starts_with(pos, end, PH_VARIADIC)) {
            pos += PH_VARIADIC.size();
            return parse_variadic();
        }

        std::string name;
        while (pos != end) {
            const char ch = *pos;

            if (std::isalpha(ch) || std::isdigit(ch)) {
                name.push_back(ch);
            } else {
                if (ch == ':') {
                    pos++;
                    return parse_optional(name);
                } else if (starts_with(pos, end, PH_END)) {
                    pos += PH_END.size();
                    state = whatever;
                    return placeholder::required_t { name };
                } else if (ch == ')' && std::next(pos) == end) {
                    throw_<parser::illformed_t>();
                } else {
                    throw_<parser::invalid_placeholder_t>();
                }
            }

            pos++;
        }

        throw_<parser::illformed_t>();
    }

    placeholder::optional_t
    parse_optional(std::string name) {
        placeholder::optional_t ph { std::move(name), "", "" };
        std::tie(ph.prefix, std::ignore) = parse({ ":" });
        std::tie(ph.suffix, std::ignore) = parse({ ")s" });
        state = whatever;
        return ph;
    }

    placeholder::variadic_t
    parse_variadic() {
        if (pos == end) {
            throw_<parser::illformed_t>();
        } else {
            placeholder::variadic_t ph;
            if (*pos == '[') {
                pos++;

                std::string pattern;
                std::tie(pattern, std::ignore) = parse({ "]" });
                parse_variadic_pattern(ph, pattern);
                if (starts_with(pos, end, PH_END)) {
                    pos += PH_END.size();
                    state = whatever;
                    return ph;
                } else if (*pos == ':') {
                    pos++;
                    parse_variadic_options(ph);
                    state = whatever;
                    return ph;
                } else {
                    throw_<parser::illformed_t>();
                }
            } else if (*pos == ':') {
                pos++;
                placeholder::variadic_t ph;
                parse_variadic_options(ph);
                state = whatever;
                return ph;
            } else if (starts_with(pos, end, PH_END)) {
                pos += PH_END.size();
                state = whatever;
                return placeholder::variadic_t();
            } else if (is_variadic_legacy(*pos)) {
                std::cout << "Warning: using legacy '"
                          << *pos
                          << "' character in variadic placeholder is deprecated"
                          << std::endl;

                while (is_variadic_legacy(*pos)) {
                    pos++;
                }

                if (starts_with(pos, end, PH_END)) {
                    pos += PH_END.size();
                    parse_variadic_pattern(ph, "'%k': %v");
                    state = whatever;
                    return ph;
                } else {
                    throw_<parser::illformed_t>();
                }
            }
        }

        throw_<parser::illformed_t>();
    }

    static
    bool
    is_variadic_legacy(char ch) {
        return ch == 'L' || ch == 'E' || ch == 'G' || ch == 'T' || ch == 'U';
    }

    static
    void
    parse_variadic_pattern(placeholder::variadic_t& ph, const std::string& pattern) {
        ph.pattern.clear();

        std::string literal;
        auto it = pattern.begin();
        auto end = pattern.end();
        for (; it != end; ++it) {
            if (starts_with(it, end, "%k")) {
                it++;

                if (!literal.empty()) {
                    ph.pattern.push_back(literal_t{ literal });
                    literal.clear();
                }
                ph.pattern.push_back(placeholder::variadic_t::key_t());
                continue;
            } else if (starts_with(it, end, "%v")) {
                it++;

                if (!literal.empty()) {
                    ph.pattern.push_back(literal_t{ literal });
                    literal.clear();
                }
                ph.pattern.push_back(placeholder::variadic_t::value_t());
                continue;
            }
            literal.push_back(*it);
        }

        if (!literal.empty()) {
            ph.pattern.push_back(literal_t{ literal });
        }
    }

    void
    parse_variadic_options(placeholder::variadic_t& ph) {
        std::tie(ph.prefix, std::ignore) = parse({ ":" });
        std::string breaker;
        std::tie(ph.suffix, breaker) = parse({ ":", ")s" });
        if (breaker == ":") {
            std::tie(ph.separator, std::ignore) = parse({ ")s" });
        }
    }

    std::tuple<std::string, std::string>
    parse(std::initializer_list<std::string> breakers,
          std::function<int(int)> match = ::isprint) {
        std::string result;
        bool escaped = false;
        while (pos != end) {
            const char ch = *pos;
            if (!match(ch)) {
                throw_<parser::illformed_t>();
            }

            if (ch == '\\') {
                pos++;
                escaped = true;
                continue;
            }

            bool matched = false;
            std::string breaker;
            for (auto it = breakers.begin(); it != breakers.end(); ++it) {
                if (starts_with(pos, end, *it)) {
                    matched = true;
                    breaker = *it;
                    break;
                }
            }

            if (matched && !escaped) {
                pos += breaker.size();
                return std::make_tuple(result, breaker);
            }

            result.push_back(ch);
            escaped = false;
            pos++;
        }

        throw_<parser::illformed_t>();
    }

private:
    template<class Exception, class... Args>
    __attribute__((noreturn))
    void throw_(Args&&... args) {
        state = broken;
        throw Exception(
            std::distance(begin, pos),
            std::string(begin, end),
            std::forward<Args>(args)...
        );
    }

    template<typename Iterator, class Range>
    static
    inline
    bool
    starts_with(Iterator first, Iterator last, const Range& range) {
        return boost::starts_with(
            boost::make_iterator_range(first, last),
            range
        );
    }
};

} // namespace string

} // namespace formatter

} // namespace blackhole
<commit_msg>[GCC 4.4] Compatibility.<commit_after>#pragma once

#include <array>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

#include <boost/algorithm/string.hpp>
#include <boost/optional.hpp>
#include <boost/variant.hpp>

#include <blackhole/detail/config/noexcept.hpp>

namespace blackhole {

namespace formatter {

namespace string {

namespace parser {

class error_t : public std::runtime_error {
    const uint pos;
    const std::string inspect;

public:
    error_t(uint pos, const std::string& pattern, const std::string& reason) :
        std::runtime_error("parser error: " + reason),
        pos(pos),
        inspect(
            "parser error: " +  reason + "\n" +
            pattern + "\n" +
            std::string(pos, '~') + "^"
        )
    {}

    ~error_t() BLACKHOLE_NOEXCEPT {}

    std::string detail() const {
        return inspect;
    }
};

class broken_t : public error_t {
public:
    broken_t(uint pos, const std::string& pattern) :
        error_t(pos, pattern, "broken parser")
    {}
};

class exhausted_t : public error_t {
public:
    exhausted_t(uint pos, const std::string& pattern) :
        error_t(pos, pattern, "exhausted state")
    {}
};

class illformed_t : public error_t {
public:
    illformed_t(uint pos, const std::string& pattern) :
        error_t(pos, pattern, "illformed pattern")
    {}
};

class invalid_placeholder_t : public error_t {
public:
    invalid_placeholder_t(uint pos, const std::string& pattern) :
        error_t(pos, pattern, "invalid placeholder name (only [a-zA-Z0-9] allowed)")
    {}
};

}

struct literal_t {
    std::string value;
};

namespace placeholder {

struct required_t {
    std::string name;
};

struct optional_t {
    std::string name;
    std::string prefix;
    std::string suffix;
};

struct variadic_t {
    struct key_t {};
    struct value_t {};

    typedef boost::variant<
        literal_t,
        key_t,
        value_t
    > pattern_t;

    std::string prefix;
    std::string suffix;
    std::vector<pattern_t> pattern;
    std::string separator;

    variadic_t() :
        pattern(default_pattern()),
        separator(", ")
    {}

private:
    static
    std::vector<pattern_t>
    default_pattern() {
        return std::vector<pattern_t>({ key_t(), literal_t{ ": " }, value_t() });
    }
};

}

typedef boost::variant<
    literal_t,
    placeholder::required_t,
    placeholder::optional_t,
    placeholder::variadic_t
> token_t;

static const std::array<char, 2> PH_BEGIN = {{ '%', '(' }};
static const std::array<char, 2> PH_END   = {{ ')', 's' }};
static const std::array<char, 3> PH_VARIADIC = {{ '.', '.', '.' }};

class parser_t {
    enum state_t {
        whatever,
        literal,
        placeholder,
        broken
    };

    std::string pattern;
    std::string::const_iterator pos;
    const std::string::const_iterator begin;
    const std::string::const_iterator end;
    state_t state;

public:
    parser_t(std::string pattern) :
        pattern(std::move(pattern)),
        pos(this->pattern.begin()),
        begin(this->pattern.begin()),
        end(this->pattern.end()),
        state(whatever)
    {}

    boost::optional<token_t>
    next() {
        if (state == broken) {
            throw_<parser::broken_t>();
        }

        if (pos == end) {
            return boost::optional<token_t>();
        }

        switch (state) {
        case whatever:
            return parse_whatever();
        case literal:
            return parse_literal();
        case placeholder:
            return parse_placeholder();
        case broken:
            throw_<parser::broken_t>();
        default:
            BOOST_ASSERT(false);
        }
    }

private:
    boost::optional<token_t>
    parse_whatever() {
        if (starts_with(pos, end, PH_BEGIN)) {
            pos += PH_BEGIN.size();
            state = placeholder;
        } else {
            state = literal;
        }

        return next();
    }

    token_t
    parse_literal() {
        literal_t literal;

        while (pos != end) {
            if (starts_with(pos, end, PH_BEGIN)) {
                pos += PH_BEGIN.size();
                state = placeholder;
                return literal;
            }

            literal.value.push_back(*pos);
            pos++;
        }

        return literal;
    }

    token_t
    parse_placeholder() {
        if (starts_with(pos, end, PH_VARIADIC)) {
            pos += PH_VARIADIC.size();
            return parse_variadic();
        }

        std::string name;
        while (pos != end) {
            const char ch = *pos;

            if (std::isalpha(ch) || std::isdigit(ch)) {
                name.push_back(ch);
            } else {
                if (ch == ':') {
                    pos++;
                    return parse_optional(name);
                } else if (starts_with(pos, end, PH_END)) {
                    pos += PH_END.size();
                    state = whatever;
                    return placeholder::required_t { name };
                } else if (ch == ')' && std::next(pos) == end) {
                    throw_<parser::illformed_t>();
                } else {
                    throw_<parser::invalid_placeholder_t>();
                }
            }

            pos++;
        }

        throw_<parser::illformed_t>();
    }

    placeholder::optional_t
    parse_optional(std::string name) {
        placeholder::optional_t ph { std::move(name), "", "" };
        std::tie(ph.prefix, std::ignore) = parse({ ":" });
        std::tie(ph.suffix, std::ignore) = parse({ ")s" });
        state = whatever;
        return ph;
    }

    placeholder::variadic_t
    parse_variadic() {
        if (pos == end) {
            throw_<parser::illformed_t>();
        } else {
            placeholder::variadic_t ph;
            if (*pos == '[') {
                pos++;

                std::string pattern;
                std::tie(pattern, std::ignore) = parse({ "]" });
                parse_variadic_pattern(ph, pattern);
                if (starts_with(pos, end, PH_END)) {
                    pos += PH_END.size();
                    state = whatever;
                    return ph;
                } else if (*pos == ':') {
                    pos++;
                    parse_variadic_options(ph);
                    state = whatever;
                    return ph;
                } else {
                    throw_<parser::illformed_t>();
                }
            } else if (*pos == ':') {
                pos++;
                placeholder::variadic_t ph;
                parse_variadic_options(ph);
                state = whatever;
                return ph;
            } else if (starts_with(pos, end, PH_END)) {
                pos += PH_END.size();
                state = whatever;
                return placeholder::variadic_t();
            } else if (is_variadic_legacy(*pos)) {
                std::cout << "Warning: using legacy '"
                          << *pos
                          << "' character in variadic placeholder is deprecated"
                          << std::endl;

                while (is_variadic_legacy(*pos)) {
                    pos++;
                }

                if (starts_with(pos, end, PH_END)) {
                    pos += PH_END.size();
                    parse_variadic_pattern(ph, "'%k': %v");
                    state = whatever;
                    return ph;
                } else {
                    throw_<parser::illformed_t>();
                }
            }
        }

        throw_<parser::illformed_t>();
    }

    static
    bool
    is_variadic_legacy(char ch) {
        return ch == 'L' || ch == 'E' || ch == 'G' || ch == 'T' || ch == 'U';
    }

    static
    void
    parse_variadic_pattern(placeholder::variadic_t& ph, const std::string& pattern) {
        ph.pattern.clear();

        std::string literal;
        auto it = pattern.begin();
        auto end = pattern.end();
        for (; it != end; ++it) {
            if (starts_with(it, end, "%k")) {
                it++;

                if (!literal.empty()) {
                    ph.pattern.push_back(literal_t{ literal });
                    literal.clear();
                }
                ph.pattern.push_back(placeholder::variadic_t::key_t());
                continue;
            } else if (starts_with(it, end, "%v")) {
                it++;

                if (!literal.empty()) {
                    ph.pattern.push_back(literal_t{ literal });
                    literal.clear();
                }
                ph.pattern.push_back(placeholder::variadic_t::value_t());
                continue;
            }
            literal.push_back(*it);
        }

        if (!literal.empty()) {
            ph.pattern.push_back(literal_t{ literal });
        }
    }

    void
    parse_variadic_options(placeholder::variadic_t& ph) {
        std::tie(ph.prefix, std::ignore) = parse({ ":" });
        std::string breaker;
        std::tie(ph.suffix, breaker) = parse({ ":", ")s" });
        if (breaker == ":") {
            std::tie(ph.separator, std::ignore) = parse({ ")s" });
        }
    }

    std::tuple<std::string, std::string>
    parse(std::initializer_list<std::string> breakers,
          std::function<int(int)> match = ::isprint) {
        std::string result;
        bool escaped = false;
        while (pos != end) {
            const char ch = *pos;
            if (!match(ch)) {
                throw_<parser::illformed_t>();
            }

            if (ch == '\\') {
                pos++;
                escaped = true;
                continue;
            }

            bool matched = false;
            std::string breaker;
            for (auto it = breakers.begin(); it != breakers.end(); ++it) {
                if (starts_with(pos, end, *it)) {
                    matched = true;
                    breaker = *it;
                    break;
                }
            }

            if (matched && !escaped) {
                pos += breaker.size();
                return std::make_tuple(result, breaker);
            }

            result.push_back(ch);
            escaped = false;
            pos++;
        }

        throw_<parser::illformed_t>();
    }

private:
    template<class Exception, class... Args>
    __attribute__((noreturn))
    void throw_(Args&&... args) {
        state = broken;
        throw Exception(
            std::distance(begin, pos),
            std::string(begin, end),
            std::forward<Args>(args)...
        );
    }

    template<typename Iterator, class Range>
    static
    inline
    bool
    starts_with(Iterator first, Iterator last, const Range& range) {
        return boost::starts_with(
            boost::make_iterator_range(first, last),
            range
        );
    }
};

} // namespace string

} // namespace formatter

} // namespace blackhole
<|endoftext|>