C++ STL std::random_shuffle cannot pass custom random number generator - c++

I want to random_shuffle a vector (I know that random_shuffle is depreciated), but I get a compile error when I pass my custom random function which I copied from another thread on here. Can someone show me how to call random_shuffle using the random number generator posted below?
random_shuffle(defects.begin(), defects.end(), xorshf96);
static unsigned int x=123456789, y=362436069, z=521288629;
unsigned int xorshf96(void) { //period 2^96-1
unsigned int t;
x ^= x << 16;
x ^= x >> 5;
x ^= x << 1;
t = x;
x = y;
y = z;
z = t ^ x ^ y;
return z;
}

xorshf96 does not meet the requirements of the RandomFunc argument to std::random_shuffle:
r - function object returning a randomly chosen value of type convertible to std::iterator_traits<RandomIt>::difference_type in the interval [0,n) if invoked as r(n)
It must take an argument and return a random number less than it. The function is in implementation of the Knuth Shuffle and that is how that algorithm works.
As a sample fix, you could provide:
unsigned int xorshf96_fixed(int n)
{
return xorshf96() % n;
}
random_shuffle(defects.begin(), defects.end(), xorshf96_fixed);

Related

Find the number of even parity numbers between two integers

I want to find the number of even parity numbers between two integers. Here is what I've written so far:
#include <bits/stdc++.h>
using namespace std;
#define fastio \
ios_base::sync_with_stdio(false); \
cin.tie(NULL)
#define ll long long int
bool findParity(ll x)
{
ll y = x ^ (x >> 1);
y = y ^ (y >> 2);
y = y ^ (y >> 4);
y = y ^ (y >> 8);
y = y ^ (y >> 16);
if (y & 1)
return 1;
return 0;
}
void solve()
{
ll a,b; cin >> a >> b;
ll evenparity = 0;
for(ll i = a; i <= b; ++i){
if(findParity(i)==0) evenparity++;
}
cout << evenparity;
}
signed main()
{
fastio;
solve();
return 0;
}
This works fine. However, the difference between the two integers a and b can be as high as 10^11, which means that an O(n) solution like this would not work. Is there a more efficient i.e O(1) solution to this problem?
All you need is a function which calculates the even parity numbers from [0-x] interval, let's call it sumParity, then simply return sumParity(b)-sumParity(a-1). (If I understood properly you are looking for the [a,b] closed interval.)
If start counting the parity from zero, and pair the numbers, (0-1), (2,3), (4,5) then each of these pairs has exactly 1 even and 1 odd parity. (These pairs only differ in the lowest bit).
So, if x is odd, then sumParity(x) = (x+1)/2, otherwise x/2 + parity(x).
(You already has the parity(x) function)
f(a,b) = sumParity(b)-sumParity(a-1)
It works only for positive integers, but you can easily extends the logic to negative numbers too.
Every even/odd pair of integers contains exactly one even parity number.
So it suffices to check if a and b are even parity numbers and see if they contribute to their own even/odd pair, and count the intermediate pairs. This is O(1).

Writing a monte carlo integration program and I don't why im getting certain errors

I am writing a monte carlo program to do a 10D integral. But what I have started off with is trying to get the full method to work in a lower dimension before moving up to the higher level. Anyways I have this program and it is using the the struct random number generator given in Numerical Recipes. Now when I run a program and just outputs the the random number it works fine, and the same when I use the built in rand function for the actual integration as well. The problem is that when I combine the two I get that the way I call the RNG struct it says that I am using 'of undeclared identifier' for both instances that I am trying to call this struct. I honestly have no idea why its throwing this error and how to fix it. Any suggestions would be greatly appreciated. The code that I am referencing is here and the error is stated as
Montetest.cpp:50:17: error: use of undeclared identifier 'rndvar'
double u1 = rndvar.int64();
Montetest.cpp:51:17: error: use of undeclared identifier 'rndvar'
double u2 = rndvar.int64();"
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
using namespace std;
struct Ran {
/*
Implementation of the highest quality recommended generator. The constructor
is called with
an integer seed and creates an instance of the generator. The member
functions int64, doub,
and int32 return the next values in the random sequence, as a variable type
indicated by
their names. The period of the generator is roughly 3.138 x 10^57.
*/
unsigned long u,v,w;
Ran(unsigned long j) : v(4101842887655102017LL), w(1) {
// Constructor. Call with any integer seed (except value of v above).
u = j ^ v; int64();
v = u; int64();
w = v; int64();
}
inline unsigned long int64() {
// Return 64-bit random integer.
u = u * 2862933555777941757LL + 7046029254386353087LL;
v ^= v >> 17; v ^= v << 31; v ^= v >> 8;
w = 4294957665U*(w & 0xffffffff) + (w >> 32);
unsigned long x = u ^ (u << 21); x ^= x >> 35; x ^= x << 4;
return (x + v) ^ w;
}
inline double doub() { return 5.42101086242752217E-20 * int64(); }
// Return random double-precision floating value in the range 0. to 1.
inline unsigned int int32() { return (unsigned int)int64(); }
// Return 32-bit random integer.
};
//int count;
double total, inBox;
// user defined function below
double f (double x){
return exp(cos(x));
}
//
//function to calculate a definite integral given bounds of integration
(xmin/max) & bounds of function (ymin/ymax)
double integral (double (*f)(double), double xmin, double xmax, double ymin,
double ymax,int n){
for (int count=0; count < n; count++){
double u1 = rndvar.int64();
double u2 = rndvar.int64();
double xcoord = ((xmax - xmin)*u1) + xmin;
double ycoord = ((ymax - ymin)*u2) + ymin;
double val = f(xcoord);
total++;
if (val > ycoord){
inBox++;
}
}
double density = inBox/total;
std::cout<<(xmax - xmin)*(ymax - ymin)*density<<std::endl;
}
int main (int argc, char **argv)
{
if(argc != 3) {
printf("Need 2 arguments: seed n\n");
exit(0);
}
unsigned long iseed=atol(argv[1]);
int n=atoi(argv[2]); // number of steps
vector <int> test;
Ran rndvar(iseed);
cout<< "RESULT: " <<endl;
integral(f,-2,2,0,4,n);
}
rndvar is declared in main but used in integral function.
Pass rndvar to integral function, or declare it in integral function, or make it a global variable (generally not recommended).
In C++11 you do not need to implement your own pseudo-random number generators. You can use the standard ones, see the example in pseudo-random number generation.
Correct me if I am wrong but I think the problem is that your rndvar is declared and initialized outside of your integral function. This means that integral() has no knowledge of rndvar because it is outside of integral()'s scope.
Try passing in rndvar as a parameter to integral() I believe that will fix your issue.

Returning the actual value of maximum of absolutes of variables

I want to find the maximum of the absolute of two variables, and return the actual value of that variable, rather than the absolute value of that variable.
For example:
int x = 3;
int y = -5;
int z = max(abs(x), abs(y))
Will just set z to 5, whereas I want it to return -5. Is there a C++ function to perform this?
If you're using C++11, with the STL you could use a vector of int, max_element and a lambda Compare
std::vector<int> values = {3, -5};
int largest_abs = *std::max_element(values.begin(), values.end(), [](const int& a, const int& b)
{
return abs(a) < abs(b);
});
This returns the iterator between the start and end of values, whose absolute value is the largest. (this is found through the comparator) The * is then used to convert the iterator (returned by std::max_element) to an int
It's not a commonly used function, but writing your own function is trivial.
int max_abs(int x, int y)
{
if (x == INT_MIN || y == INT_MIN)
return INT_MIN;
return (abs(x) > abs(y)) ? x : y;
}
int z = (max(abs(x), abs(y)) == abs(x)) ? x : y;
This is like an if-condition. Its equivalent to
int z = x;
if(max(abs(x), abs(y)) != abs(z))
z = y;
But much shorter.
There is no function in the STL to fit into your needs directly, so you need to make your own and this one could be one version.
A more handy one can be int z = (abs(y) < abs(x)) ? x : y thought.

C++ Bus error when using `^=` and `<<` on a class member `unsigned long`

I am trying to implement the random number generator defined in this answer. There is some ambiguity, at least from my knowledge, as to how the first line, static unsigned long x=123456789, y=362436069, z=521288629; should be implemented, since it is shown outside the function. I assumed that it was intended as a class member and implemented it thus:
class rng2{
public:
unsigned long x, y, z;
rng2() : x(123456789), y(362436069), z(521288629) {}
unsigned long xorshf96(void) { //period 2^96-1
//static unsigned long x=123456789, y=362436069, z=521288629;
unsigned long t;
x ^= x << 16; //BUS ERROR, debug mode
x ^= x >> 5;
x ^= x << 1;
t = x;
x = y; //SEG FAULT, release mode
y = z;
z = t ^ x ^ y;
return z;
}
};
int main ()
{
rng2 rand2;
rng2 * prand;
for(long d =0; d < 10000; d++)
cout << "\n" << (*prand).xorshf96();
}
For some reason, this gives me errors at the noted locations, depending on which mode I compile with. However, if I comment out the member variable and the constructor and use the static variable instead, everything works. If this is the correct code, I don't see why it was shown differently at the link, and either way, I don't know why the error is happening.
You're using *prand, but not initializing prand.
rng2 * prand;
Are you perfectly sure this is the real code? Considering you are not initializing this pointer and dereferencing it later, the error is pretty obvious.
prand is a wild pointer.
Change:
int main ()
{
rng2 rand2;
rng2 * prand;
for(long d =0; d < 10000; d++)
cout << "\n" << (*prand).xorshf96();
}
to:
int main ()
{
rng2 rand2;
rng2 * prand = &rand2;
for(long d =0; d < 10000; d++)
cout << "\n" << (*prand).xorshf96();
}
or better just:
int main ()
{
rng2 rand2;
for(long d =0; d < 10000; d++)
cout << "\n" << rand2.xorshf96();
}
This is because the prand pointer is never assigned but only used. When using a static the variable no datamember is accessed and that's why you do not get a bus error. You should definately assign your pointer a valid value in your main function. Like this
rng2 * prand = new rng2();

Reverse map a functional relation(c++)

I am using a simple function (y(x)), and I want to generate an x value from a certain y value. While typically reverse mapping does not give a single x value, I am using the maximum from my y values. This means that there will be a unique x value for the y value I input(the maximum). I don't understand how to code this in c++
If you don't need interpolation, only exact reverse lookup, then it's relatively straighforward:
std::map<YType, XType> lookup;
// (code to read the file goes here)
// for each x {
YType y = f(x);
if ((lookup.count(y) == 0) || (lookup[y] < x)) {
lookup[y] = x;
}
// }
Then your reverse lookup is just lookup[y], which will return 0 (or a default-constructed value where applicable) if y in fact was missing from the data.
Be aware that my code is a bit inefficient, it looks up y several times in the map, up to 3. You can optimize using iterators, but I'm concerned that obscures what's going on if you're not already familiar with them:
typedef std::map<YType, XType> maptype;
typedef std::pair<maptype::iterator, bool> resulttype;
resulttype result = lookup.insert(std::make_pair(y, x));
if (!result.second) {
// key already existed, so value was not inserted. Check for max.
maptype::iterator pos = result.first;
if ((*pos).second < x) {
(*pos).second = x;
}
}
If I understand correctly, you are given a finite range of values x, say x[0], x[1], ..., x[N], and a function f, and you want to find the index k for which f(x[k]) is the largest possible. In that case, a simple search will do:
size_t k = 0;
T m = f(x[k]);
T tmp;
for (size_t i = 1; i <= N; ++i)
{
if ((tmp = f(x[i])) > m)
{
k = i;
m = tmp;
}
}
// Maximum is (x[k], m)
Here T is the type such that f is T f(T);