std::random_shuffle not being seeded - c++

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
int main() {
std::vector<short> a(256);
for (short x = 0; x != 256; ++x) {
a[x] = x;
}
for (auto x : a) { std::cout << x << ' '; } std::cout << std::endl;
std::cout << std::endl;
std::srand(11);
std::random_shuffle(a.begin(), a.end());
for (auto x : a) { std::cout << x << ' '; } std::cout << std::endl;
std::cout << std::endl;
for (short x = 0; x != 256; ++x) {
a[x] = x;
}
for (auto x : a) { std::cout << x << ' '; } std::cout << std::endl;
std::cout << std::endl;
std::srand(11);
std::random_shuffle(a.begin(), a.end());
for (auto x : a) { std::cout << x << ' '; } std::cout << std::endl;
}
So, here is my code. What I expect is, obviously, the same shuffle both times. What I get is, while the shuffles are consistent between launches, they are different and seem to ignore srand! What am I doing wrong here?

Note that for std::random_shuffle what random number generator is used is implementation-defined, it's not guaranteed to use std::rand.
You could use std::shuffle instead and pass it a random number generator:
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(a.begin(), a.end(), g);
LIVE

First note that the version of std::random_shuffle you use has been deprecated.
Also note (from the previous reference link)
...the function std::rand is often used.
The keyword here being often and not always.
If you want to make sure the same sequence is always created, then you should use one of the alternatives, passing either a specific random-number function, or use the std::shuffle function passing a generator (from the C++11 "new" PRNG classes).

Related

std::reduce with a lambda returning a pair

#HTNW noted in this question that op's code use std::reduce if the provided lambda was defined with more overloads. Can someone please provide an example implementing this idea?
I am in a virtually identical situation and would like to take advantage of std::reduce's parallel policies instead of std::accumulate.
I attempted to create 4 versions of my function with each required argument types, but I do not see how to pass all 4 of these to std::reduce. I also tried giving std::visit 4 lambdas but this also did not compile.
For example, I'm not sure how to make the following code compile:
#include <algorithm>
#include <execution>
#include <iostream>
#include <random>
#define N 100
#define seed 1
auto baz(std::pair<double,double> se, double vi){
se.first += vi;
se.second *= 1+vi;
return se;
}
auto baz(double vi, std::pair<double,double> se){
return baz(se, vi);
}
auto baz(double vj, double vi){
return std::pair(vi+vj,1.0);
}
auto baz(std::pair<double,double> se1, std::pair<double,double> se2){
se1.first += se2.first;
se1.second *= se2.second;
return se1;
}
int main(){
std::mt19937 rng(seed);
std::uniform_real_distribution<double> dist(0,1);
std::vector<double> v(N);
std::for_each(std::execution::par_unseq, v.begin(), v.end(), [&dist,&rng](double& c){ c = dist(rng); });
for(auto x : v)
std::cout << x << ", ";
std::cout << "\n";
// working accumulate code
auto foo = std::accumulate(v.begin(), v.end(), std::pair(0.0,1.0),
[](std::pair<double,double> se, double vi){
se.first += vi;
se.second *= 1+vi;
return se;
});
std::cout << foo.first << " " << foo.second << "\n";
auto bar = std::reduce(v.begin(), v.end(), std::pair(0.0,1.0), baz)
std::cout << bar.first << " " << bar.second << "\n";
}
You need to build an object that can be called with all 4 specified signatures. There are various ways to do this, but a simple technique is to use a polymorphic lambda:
[](auto x, auto y) { return baz(x, y); }
Example.

Get the state (seed) of a distribution of random numbers

See the following program for g++.
#define seed1 0
#include <iostream>
#include <random>
int main()
{
double mean = 0.0;
double stddev = 1.0;
std::mt19937 generator1 (seed1);
std::normal_distribution<double> normal(mean, stddev);
std::cerr << "Normal: " << normal(generator1) << std::endl;
}
I want to get the state of generator1 (as a seed) and remove generator1 for later
instantiate again the distribution with the new seed and go on in the place I left I want to put this code in a function and call it to generate Gaussian points in the start state I want. And at the end of the function save the state as a seed.
save the state as a seed
That will never happen, the state of a generator is much more than its seed.
However, generators (and distributions, which you ignored in your question) do provide functionality to store and retrieve their state through the << / >> operators respectively on streams:
stream << generator1 << normal;
And later:
mt19937 generator;
stream >> generator;
normal_distribution<double> distribution;
stream >> distribution;
Let me also add, that generators and distributions are also constructible and copyable from itself, if there is a need to reuse it later.
#define seed1 0
#include <iostream>
#include <random>
int main()
{
double mean = 0.0;
double stddev = 1.0;
std::mt19937 generator1 (seed1);
std::normal_distribution<double> normal(mean, stddev);
std::cerr << "Normal: " << normal(generator1) << std::endl;
std::mt19937 generator2 = generator1;
std::normal_distribution<double> normal2 = normal;
std::cerr << "Normal: " << normal(generator1) << std::endl;
std::cerr << "Normal2: " << normal2(generator2) << std::endl;
// I want to get the state of generator1 (as a seed) and remove generator1 for later
//instantiate again the distribution with the new seed and go on in the place I left
// I want to put this code in a function and call it to generate Gaussian points in
// the start state I want. And at the end of the function save the state as a seed.
}
So last lines print the same result, as states were initialized to equal values.
There is one way you could try. This involves saving the original seed, and counting how many times the generator is called. To restore the state, seed with the original seed and then call std::mt19937::discard()
Example:
#define seed1 0
#include <cassert>
#include <iostream>
#include <random>
// spoof a generator that counts the number of calls
class my_mt19937 : public std::mt19937 {
public:
result_type operator()() {
++call_count_;
return std::mt19937::operator()();
}
void seed(result_type value = default_seed) {
original_seed_ = value;
std::mt19937::seed(value);
}
void discard(unsigned long long z) {
call_count_ += z;
std::mt19937::discard(z);
}
unsigned long long call_count() const noexcept { return call_count_; }
result_type original_seed() const noexcept { return original_seed_; }
private:
result_type original_seed_ = default_seed;
unsigned long long call_count_ = 0;
};
int main() {
double mean = 0.0;
double stddev = 1.0;
my_mt19937 gen1;
gen1.seed(seed1);
const size_t N = 10'000;
for (size_t i = 0; i < N; ++i) {
my_mt19937 gen2;
gen2.seed(gen1.original_seed());
gen2.discard(gen1.call_count());
if (gen2() != gen1()) {
std::cout << "failed for i = " << i << "\n";
return 1;
}
}
// this extneds to distribution objects that
// use the generators
std::normal_distribution<double> normal1;
std::normal_distribution<double> normal2;
for (size_t i = 0; i < N; ++i) {
my_mt19937 gen2;
gen2.seed(gen1.original_seed());
gen2.discard(gen1.call_count());
if (normal1(gen1) != normal2(gen2)) {
std::cout << "failed for i = " << i << "\n";
return 1;
}
}
std::cout << "Success! Tested " << N << " values\n";
return 0;
}
You can play further with the code on godbolt: https://godbolt.org/z/8j9onsezs

C++ Displaying a vector

I'm learning C++ so my question might seem a bit stupid. I wanted to build a function that print every element in a vector. I come up with that but it seems to display the address of every element. I google it and find a nice solution but i wanted to do it this way so if anyone can explain me where i'm doing something wrong.
My code :
void display_vector(std::vector<int>& to_display);
int main()
{
std::vector<int> vector_to_sort = { 2,6,7,2,1,80,2,59,8,9 };
display_vector(vector_to_sort);
}
void display_vector(std::vector<int> &to_display)
{
for (int i = 0; i < to_display.size(); i++)
{
std::cout << to_display[i] << ', ';
}
std::cout << '\n';
}
The solution i found on internet :
#include <iterator>
void display_vector(const vector<int> &v)
{
std::copy(v.begin(), v.end(),
std::ostream_iterator<int>(std::cout, " "));
}
Output of my code :
21129661129671129621129611129680112962112965911296811296911296
You use ", " instead of ', '.
You can use any of the following print mechanism in the display() function:
void display_vector(std::vector<int> &to_display)
{
//by using Normal for loop
for (auto i = to_display.begin(); i != to_display.end(); ++i) {
cout << *i << " ";
}
cout << endl;
//by using Range based for loop
for (int & i : to_display) {
cout << i << " ";
}
std::cout << '\n';
}
In this statement
std::cout << to_display[i] << ', ';
^^^^^^
you are using a multybyte character literal that has an implementation defined value.
Substitute it for string literal ", ".
As for the function then for starters if the vector is not being changed in the function then the parameter should be a constant reference.
You can use the range-based for loop to outfput elements of the vector like for example
#include <iostream>
#include <vector>
std::ostream & display_vector( const std::vector<int> &to_display, std::ostream &os = std::cout );
int main()
{
std::vector<int> vector_to_sort = { 2,6,7,2,1,80,2,59,8,9 };
display_vector(vector_to_sort) << '\n';
}
std::ostream & display_vector( const std::vector<int> &to_display, std::ostream &os )
{
for ( const auto &item : to_display )
{
os << item << ", ";
}
return os;
}
Using such a function you can for example output the vector in a text file.
Just replace below line
std::cout << to_display[i] << ', ';
with
std::cout << to_display[i] << ", ";
Also note that if you just want to display vector in function then declare parameter as const reference as shown below
void display_vector(const std::vector<int> &to_display);
The debuggers make it easy to examine vectors but I include a simple template to print out vectors of standard types and often use it when debugging data that I wish to look at with other tools.
template<class T>
void print(const std::vector<T>& v){
for (auto x: v)
std::cout << x << std::endl;
}

I want to reverse the values of map and print it using range based for loop.

I have done the programming but it is not reversing. I have used a different map to put the values in reverse order,but it still shows the same. My main question was to traverse backward and print the values using range based loop.
#include "stdafx.h"
#include <iostream>
#include<conio.h>
#include <stdio.h>
#include<vector>
#include<map>
#include<utility>
#include<set>
map<int, int>m1;
for (int i = 1; i <= 100; ++i)
{
m1.insert({ i,i });
}
for (const auto &y :m1)
{
cout <<"("<< y.first << " "<<y.second << ")" <<" " ;
}
cout << endl << endl;
map<int, int>m2;
map<int, int>::reverse_iterator iter;
for (auto iter = m1.rbegin(); iter != m1.rend(); ++iter)
{
m2.insert({ iter->first,iter->second });
}
for (const auto &y : m2)
{
cout << "(" << y.first << " " << y.second << ")" << " ";
}
As Some Programmer Dude pointed out, but for the completeness of my answer, a std::map is sorted on the key, no matter what order you insert the elements. One option would be to create a new map with the opposite sorting, but that doesn't seem to be what you really want.
It seems you know how about reverse iterators, but not how to get at them when using range-based for. Since it operates on a range, i.e. some type that provides begin and end iterators, you need to create some wrapper around your map that provides this.
Here's a general one I just put together than works in C++11. It won't cover every possible case, and can be made a bit neater in C++14, but it will work for you.
#include <iostream>
#include <iterator>
// The wrapper type that does reversal
template <typename Range>
class Reverser {
Range& r_;
public:
using iterator_type = std::reverse_iterator<decltype(std::begin(r_))>;
Reverser(Range& r) : r_(r) {}
iterator_type begin() { return iterator_type(std::end(r_)); }
iterator_type end() { return iterator_type(std::begin(r_)); }
};
// Helper creation function
template <typename Range>
Reverser<Range> reverse(Range& r)
{
return Reverser<Range>(r);
}
int main()
{
int vals[] = {1, 2, 3, 4, 5};
for (auto i : reverse(vals))
std::cout << i << '\n';
}
This outputs:
$ ./reverse
5
4
3
2
1
(You may also find libraries that provide a similar adapter; Eric Niebler is working on a ranges library for The Standard.)
Also, please reconsider your use of what are often considered bad practices: using namespace std; and endl (those are links to explanations).
Here's an example of iterating backward through a std::map:
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<int, int> m;
m[1] = 1;
m[2] = 2;
m[3] = 3;
for (auto iter = m.rbegin(); iter != m.rend(); ++iter) {
std::cout << iter->first << ": " << iter->second << std::endl;
}
}
If you are pre-C++11, you'll just need to spell out auto, which is:
std::map<int, int>::reverse_iterator
If you're using boost, you can use a range-based for loop with a reverse adapter:
#include <boost/range/adaptor/reversed.hpp>
for (auto& iter : boost::adaptors::reverse(m)) {
std::cout << iter.first << ": " << iter.second << std::endl;
}
If you only need to print the elements in the map in reverse order,you don't need another map for it,you can do this:
std::map<int, int>::reverse_iterator iter;
for (iter = m1.rbegin(); iter != m1.rend(); ++iter)
{
std::cout << "(" << iter->first << " " << iter->second << ")" << " ";
}

How sort double vector according to changes in first vector?

I would like to implement something like DoubleVector.
In this class I would also like to implement sort method, which sort v1_ and according to changes in v1_ the order in v2_ will also change.
The code is below:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class DoubleVector
{
vector<int> v1_;
vector<char> v2_;
public:
void sort()
{
//sort v1_ and also change order in v2_ according to changes in v1_
std::sort(v1_.begin(), v1_.end() /*, lambda ?*/);
}
void add(int value_v1, char value_v2)
{
v1_.push_back(value_v1);
v2_.push_back(value_v2);
}
void print()
{
const auto size = v1_.size();
for (size_t i=0;i<size;++i)
{
cout << v1_[i] << " " << v2_[i] << endl;
}
}
};
int main()
{
DoubleVector dv;
dv.add(6, 'g');
dv.add(2, 'r');
dv.add(3, 'y');
dv.add(4, 'a');
cout << "Before sort:" << endl;
dv.print();
dv.sort();
cout << "After sort:" << endl;
dv.print();//the values in v2_ are in the same order they don't change order according to v1_ changes
return 0;
}
As you can see DoubleVector before sort contains:
6 g
2 r
3 y
4 a
And after sort contains:
2 g
3 r
4 y
6 a
I would like to get:
2 r
3 y
4 a
6 g
So the first vector v1_ has been sorted, but the second still has got the same order and I would like to change order of elements in second v2_ vector according to changes in v1_.
I can write it, but I would like to do it in a fast and clean way, maybe using lambda as third argument in std::sort function? Vectors v1_ and v2_ in class DoubleVector must stay as they are.
Thank you very much.
Make a vector of std::pair<int,char> instead. Since operator < on the pair compares first and decides ties on the second, sorting std::vector<std::pair<int,char>> will produce the exact effect that you want:
vector<pair<int,char>> v;
v.push_back(make_pair(6, 'g'));
v.push_back(make_pair(2, 'r'));
v.push_back(make_pair(3, 'y'));
v.push_back(make_pair(4, 'a'));
sort(v.begin(), v.end());
for (int i = 0 ; i != v.size() ; i++) {
cout << v[i].first << " " << v[i].second << endl;
}
Demo.
You can do something like this:-
vector< pair<int,char> >v;
//do what you want
sort(v.begin(),v.end())
The sort function by default sorts according to first value but you can always define according to which criteria should the sort work
C++ STL - How does the third argument of the STL sort() work?
Try the following.
The way it works is to sort the position key pair based on the int vector value only and then use this ordering to extract values.
#include <iostream>
#include <algorithm>
#include <vector>
class dv
{
std::vector<int> _v1;
std::vector<char> _v2;
std::vector<std::pair<int, int> > _order;
public:
inline bool operator() (const std::pair<int, int>& v1_index_1,
const std::pair<int, int>& v1_index_2) const {
return _v1[v1_index_1.first] < _v1[v1_index_2.first];
}
void sort() {
std::sort(_order.begin(), _order.end(), *this);
}
void add(int value_v1, char value_v2) {
_order.push_back(std::pair<int, int>(_v1.size(), _v2.size()));
_v1.push_back(value_v1);
_v2.push_back(value_v2);
}
void print() {
const auto size(_v1.size());
for (size_t i=0; i<size; ++i) {
std::cout << _v1[_order[i].first]
<< " "
<< _v2[_order[i].second]
<< std::endl;
}
}
};
int main() {
dv dv;
dv.add(6, 'g');
dv.add(2, 'r');
dv.add(3, 'y');
dv.add(4, 'a');
std::cout << "before sort: " << std::endl;
dv.print();
std::cout << "sorting: " << std::endl;
dv.sort();
std::cout << "after sort: " << std::endl;
dv.print();
return 0;
}