#include <vector>
#include <string>
#include <numeric>
#include <algorithm>
#include <iostream>
#include <iomanip>

template <typename T, typename U, typename V>
void print_parallel(const T& a, const U& b, const V& idx)
{
    for (unsigned i = 0; i < a.size(); ++i)
    {
        std::cout << std::left << std::setw(10) << a[idx[i]];
        std::cout << std::right << std::setw(10) << b[idx[i]] << '\n';
    }
}

int main()
{
    std::vector<std::string>  aminals = { "dog", "cat", "giraffe", "rabbit", "snake" };
    std::vector<double> values = { 2.3, 19.0, 5.67, 4, 1.004 };

    auto by_aminal = [&](unsigned i, unsigned j) { return aminals[i] < aminals[j]; };
    auto by_value = [&](unsigned i, unsigned j) { return values[i] < values[j]; };

    std::vector<unsigned> indices(aminals.size());
    std::iota(indices.begin(), indices.end(), 0);

    std::cout << "Before sort by value:\n";
    print_parallel(aminals, values, indices);

    std::sort(indices.begin(), indices.end(), by_value);

    std::cout << "\nAfter sort by value:\n";
    print_parallel(aminals, values, indices);

    std::sort(indices.begin(), indices.end(), by_aminal);

    std::cout << "\nAfter sort by aminal:\n";
    print_parallel(aminals, values, indices);
}
