Random number generator with 3 inputs - random

I am looking for a random number generator with 3 inputs for a terrain generator. The inputs are an x, y (position) and a seed value. And the function returns back a random number from 0-1.
So far I found this question, but this has 2 inputs. Although I can combine x and y to a single number, to get two inputs, this will restrict the choices I will have for x, y as they need to be sufficiently large (the terrain is infinite).
Is there any random function that takes in 3 inputs, or would I need to end up using the 2 input version?

Something like this should work. It takes three 32-bit integers, and outputs a single 32-bit integer. If you want to turn the output into a double between 0 and 1, just divide by UINT32_MAX.
The input and output sizes can be adjusted.
You can also tweak the balance between output quality and speed. You'll notice that the middle section is just repeated 3 lines, remove or add more of them to make the output more or less biased.
Here's the C code.
uint32_t rotl32(uint32_t n, uint8_t k) {
uint32_t a = n << k;
uint32_t b = n >> (32 - k);
return a | b;
}
uint32_t three_input_random(uint32_t x, uint32_t y, uint32_t z) {
uint32_t a = x;
uint32_t b = y;
uint32_t c = z;
b ^= rotl32(a + c, 7);
c ^= rotl32(b + a, 9);
a ^= rotl32(c + b, 18);
b ^= rotl32(a + c, 7);
c ^= rotl32(b + a, 9);
a ^= rotl32(c + b, 18);
b ^= rotl32(a + c, 7);
c ^= rotl32(b + a, 9);
a ^= rotl32(c + b, 18);
return a + b + c + x + y + z;
}

Related

Unable to understand the Choice of Area DP

Consider a game, in which you have two types of powers, A and B and there are 3 types of Areas X, Y and Z. Every second you have to switch between these areas, each area has specific properties by which your power A and power B increase or decrease. We need to keep choosing areas in such a way that our survival time is maximized. Survival time ends when any of the powers, A or B reaches less than 0.
Examples:
Initial value of Power A = 20
Initial value of Power B = 8
Area X (3, 2) : If you step into Area X,
A increases by 3,
B increases by 2
Area Y (-5, -10) : If you step into Area Y,
A decreases by 5,
B decreases by 10
Area Z (-20, 5) : If you step into Area Z,
A decreases by 20,
B increases by 5
It is possible to choose any area in our first step.
We can survive at max 5 unit of time by following
these choice of areas :
X -> Z -> X -> Y -> X
This problem can be solved using recursion, after each time unit we can go to any of the area but we will choose that area which ultimately leads to maximum survival time. As recursion can lead to solving same subproblem many time, we will memoize the result on basis of power A and B, if we reach to same pair of power A and B, we won’t solve it again instead we will take the previously calculated result.
Given below is the simple implementation of above approach.
// C++ code to get maximum survival time
#include <bits/stdc++.h>
using namespace std;
// structure to represent an area
struct area
{
// increment or decrement in A and B
int a, b;
area(int a, int b) : a(a), b(b)
{}
};
// Utility method to get maximum of 3 integers
int max(int a, int b, int c)
{
return max(a, max(b, c));
}
// Utility method to get maximum survival time
int maxSurvival(int A, int B, area X, area Y, area Z,
int last, map<pair<int, int>, int>& memo)
{
// if any of A or B is less than 0, return 0
if (A <= 0 || B <= 0)
return 0;
pair<int, int> cur = make_pair(A, B);
// if already calculated, return calculated value
if (memo.find(cur) != memo.end())
return memo[cur];
int temp;
// step to areas on basis of last chose area
switch(last)
{
case 1:
temp = 1 + max(maxSurvival(A + Y.a, B + Y.b,
X, Y, Z, 2, memo),
maxSurvival(A + Z.a, B + Z.b,
X, Y, Z, 3, memo));
break;
case 2:
temp = 1 + max(maxSurvival(A + X.a, B + X.b,
X, Y, Z, 1, memo),
maxSurvival(A + Z.a, B + Z.b,
X, Y, Z, 3, memo));
break;
case 3:
temp = 1 + max(maxSurvival(A + X.a, B + X.b,
X, Y, Z, 1, memo),
maxSurvival(A + Y.a, B + Y.b,
X, Y, Z, 2, memo));
break;
}
// store the result into map
memo[cur] = temp;
return temp;
}
// method returns maximum survival time
int getMaxSurvivalTime(int A, int B, area X, area Y, area Z)
{
if (A <= 0 || B <= 0)
return 0;
map< pair<int, int>, int > memo;
// At first, we can step into any of the area
return
max(maxSurvival(A + X.a, B + X.b, X, Y, Z, 1, memo),
maxSurvival(A + Y.a, B + Y.b, X, Y, Z, 2, memo),
maxSurvival(A + Z.a, B + Z.b, X, Y, Z, 3, memo));
}
// Driver code to test above method
int main()
{
area X(3, 2);
area Y(-5, -10);
area Z(-20, 5);
int A = 20;
int B = 8;
cout << getMaxSurvivalTime(A, B, X, Y, Z);
return 0;
}
Output :
5

Counting inversions in a segment with updates

I'm trying to solve a problem which goes like this:
Problem
Given an array of integers "arr" of size "n", process two types of queries. There are "q" queries you need to answer.
Query type 1
input: l r
result: output number of inversions in [l, r]
Query type 2
input: x y
result: update the value at arr [x] to y
Inversion
For every index j < i, if arr [j] > arr [i], the pair (j, i) is one inversion.
Input
n = 5
q = 3
arr = {1, 4, 3, 5, 2}
queries:
type = 1, l = 1, r = 5
type = 2, x = 1, y = 4
type = 1, l = 1, r = 5
Output
4
6
Constraints
Time: 4 secs
1 <= n, q <= 100000
1 <= arr [i] <= 40
1 <= l, r, x <= n
1 <= y <= 40
I know how to solve a simpler version of this problem without updates, i.e. to simply count the number of inversions for each position using a segment tree or fenwick tree in O(N*log(N)). The only solution I have to this problem is O(q*N*log(N)) (I think) with segment tree other than the O(q*N2) trivial algorithm. This however does not fit within the time constraints of the problem. I would like to have hints towards a better algorithm to solve the problem in O(N*log(N)) (if it's possible) or maybe O(N*log2(N)).
I first came across this problem two days ago and have been spending a few hours here and there to try and solve it. However, I'm finding it non-trivial to do so and would like to have some help/hints regarding the same. Thanks for your time and patience.
Updates
Solution
With the suggestion, answer and help by Tanvir Wahid, I've implemented the source code for the problem in C++ and would like to share it here for anyone who might stumble across this problem and not have an intuitive idea on how to solve it. Thank you!
Let's build a segment tree with each node containing information about how many inversions exist and the frequency count of elements present in its segment of authority.
node {
integer inversion_count : 0
array [40] frequency : {0...0}
}
Building the segment tree and handling updates
For each leaf node, initialise inversion count to 0 and increase frequency of the represented element from the input array to 1. The frequency of the parent nodes can be calculated by summing up frequencies of the left and right childrens. The inversion count of parent nodes can be calculated by summing up the inversion counts of left and right children nodes added with the new inversions created upon merging the two segments of their authority which can be calculated using the frequencies of elements in each child. This calculation basically finds out the product of frequencies of bigger elements in the left child and frequencies of smaller elements in the right child.
parent.inversion_count = left.inversion_count + right.inversion_count
for i in [39, 0]
for j in [0, i)
parent.inversion_count += left.frequency [i] * right.frequency [j]
Updates are handled similarly.
Answering range queries on inversion counts
To answer the query for the number of inversions in the range [l, r], we calculate the inversions using the source code attached below.
Time Complexity: O(q*log(n))
Note
The source code attached does break some good programming habits. The sole purpose of the code is to "solve" the given problem and not to accomplish anything else.
Source Code
/**
Lost Arrow (Aryan V S)
Saturday 2020-10-10
**/
#include "bits/stdc++.h"
using namespace std;
struct node {
int64_t inv = 0;
vector <int> freq = vector <int> (40, 0);
void combine (const node& l, const node& r) {
inv = l.inv + r.inv;
for (int i = 39; i >= 0; --i) {
for (int j = 0; j < i; ++j) {
// frequency of bigger numbers in the left * frequency of smaller numbers on the right
inv += 1LL * l.freq [i] * r.freq [j];
}
freq [i] = l.freq [i] + r.freq [i];
}
}
};
void build (vector <node>& tree, vector <int>& a, int v, int tl, int tr) {
if (tl == tr) {
tree [v].inv = 0;
tree [v].freq [a [tl]] = 1;
}
else {
int tm = (tl + tr) / 2;
build(tree, a, 2 * v + 1, tl, tm);
build(tree, a, 2 * v + 2, tm + 1, tr);
tree [v].combine(tree [2 * v + 1], tree [2 * v + 2]);
}
}
void update (vector <node>& tree, int v, int tl, int tr, int pos, int val) {
if (tl == tr) {
tree [v].inv = 0;
tree [v].freq = vector <int> (40, 0);
tree [v].freq [val] = 1;
}
else {
int tm = (tl + tr) / 2;
if (pos <= tm)
update(tree, 2 * v + 1, tl, tm, pos, val);
else
update(tree, 2 * v + 2, tm + 1, tr, pos, val);
tree [v].combine(tree [2 * v + 1], tree [2 * v + 2]);
}
}
node inv_cnt (vector <node>& tree, int v, int tl, int tr, int l, int r) {
if (l > r)
return node();
if (tl == l && tr == r)
return tree [v];
int tm = (tl + tr) / 2;
node result;
result.combine(inv_cnt(tree, 2 * v + 1, tl, tm, l, min(r, tm)), inv_cnt(tree, 2 * v + 2, tm + 1, tr, max(l, tm + 1), r));
return result;
}
void solve () {
int n, q;
cin >> n >> q;
vector <int> a (n);
for (int i = 0; i < n; ++i) {
cin >> a [i];
--a [i];
}
vector <node> tree (4 * n);
build(tree, a, 0, 0, n - 1);
while (q--) {
int type, x, y;
cin >> type >> x >> y;
--x; --y;
if (type == 1) {
node result = inv_cnt(tree, 0, 0, n - 1, x, y);
cout << result.inv << '\n';
}
else if (type == 2) {
update(tree, 0, 0, n - 1, x, y);
}
else
assert(false);
}
}
int main () {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.precision(10);
std::cout << std::fixed << std::boolalpha;
int t = 1;
// std::cin >> t;
while (t--)
solve();
return 0;
}
arr[i] can be at most 40. We can use this to our advantage. What we need is a segment tree. Each node will hold 41 values (A long long int which represents inversions for this range and a array of size 40 for count of each numbers. A struct will do). How do we merge two children of a node. We know inversions for left child and right child. Also know frequency of each numbers in both of them. Inversion of parent node will be summation of inversions of both children plus number of inversions between left and right child. We can easily find inversions between two children from frequency of numbers. Query can be done in similar way. Complexity O(40*qlog(n))

Smallest number in a range [a,b] with maximum number of '1' in binary representation

Given a range [a,b] (both inclusive) I need to find the smallest number with the maximum number of '1's in binary representation. My current approach is I find the number of bits set in all numbers from a to b and keep track of the maximum.
However this is very slow, any faster method?
Let's find most significant bit which is different in a and b. It will be 0 in a, 1 in b. If we place all other bits to the right to 1 - resulting number will be still in range [a; b]. And it will the single number with maximum number of ones in representation.
EDIT. The result of this algorithm always returns the number with n-1 bits set to one, where n is number of bits which can be changed. As pointed in comments - there is a bug in case if all of there n bits in b are set to 1. Here is the fixed code snippet:
int maximizeBits(int a, int b) {
if (a == b) {
return a;
}
int m = a ^ b, pow2 = 1; // MSB of m=a^b is bit that we need to find
while (m > pow2) { // Set other bits to 0
if ((m & pow2) != 0) {
m ^= pow2;
}
pow2 <<= 1;
}
int res = a | (m - 1); // Now m is in form of 2^n and m - 1 would be mask of n-1 bits
if ((res | b) <= b) { // Fix of problem if all n bits in b are set to 1
res = b;
}
return res;
}
You can replace the loop in Jarlax' answer by a "parallel suffix OR", like this
uint32_t m = (a ^ b) >> 1;
m |= m >> 1;
m |= m >> 2;
m |= m >> 4;
m |= m >> 8;
m |= m >> 16;
uint32_t res = a | m;
if ((res | b) <= b)
res = b;
return res;
It generalizes to different sizes integer, using ceil(log(k)) steps in general. The initial test a == b is not necessary, a ^ b would be zero, therefore m is zero, so nothing interesting happens anyway.
Alternatively, here's a completely different approach: keep changing the lowest 0 to a 1 until it is no longer possible.
unsigned x = a;
while (x < b) {
unsigned newx = (x + 1) | x; // set lowest 0
if (newx <= b)
x = newx;
else
break;
}
return x;

Using extended euclidean algorithm to find number of intersections of a line segment with points on a 2D grid

In the grid constructed by grid points (M*x, M*y) and given the point A(x1,y1) and point B(x2,y2) where all the variables are integers. I need to check how many grid points lie on the line segment from point A to point B. I know that it can be done by using the extended euclidean algorithm somehow, but I have no clue on how to do it. I would appreciate your help.
Rephrased, you want to determine how many numbers t satisfy
(1) M divides (1-t) x1 + t x2
(2) M divides (1-t) y1 + t y2
(3) 0 <= t <= 1.
Let's focus on (1). We introduce an integer variable q to represent the divisibility constraint and solve for t:
exists integer q, M q = (1-t) x1 + t x2
exists integer q, M q - x1 = (x2 - x1) t.
If x1 is not equal to x2, then this gives a periodic set of possibilities of the form t in {a + b q | q integer}, where a and b are fractions. Otherwise, all t or no t are solutions.
The extended Euclidean algorithm is useful for intersecting the solution sets arising from (1) and (2). Suppose that we want to compute the intersection
{a + b q | q integer} intersect {c + d s | s integer}.
By expressing a generic common element in two different ways, we arrive at a linear Diophantine equation:
a + b q = c + d s,
where a, b, c, d are constant and q, s are integer. Let's clear denominators and gather terms into one equation
A q + B s = C,
where A, B, C are integers. This equation has solutions if and only if the greatest common divisor g of A and B also divides C. Use the extended Euclidean algorithm to compute integer coefficients u, v such that
A u + B v = g.
Then we have a solution
q = u (C/g) + k (B/g)
s = v (C/g) - k (A/g)
for each integer k.
Finally, we have to take constraint (3) into consideration. This should boil down to some arithmetic and one floor division, but I'd rather not work out the details (the special cases of what I've written so far already will take quite a lot of your time).
Let's dX = Abs(x2-x1) and dY = Abs(y2 - y1)
Then number of lattice points on the segment is
P = GCD(dX, dY) + 1
(including start and end points)
where GCD is the greatest common divisor (through usual (not extended) Euclidean algorithm)
(See last Properties here)
Following instructions of Mr. David Eisenstat I have managed to write a program in c++ that calculates the answer.
#include <iostream>
#include <math.h>
using namespace std;
int gcd (int A, int B, int &u, int &v)
{
int Ad = 1;
int Bd = 1;
if (A < 0) { Ad = -1; A = -A; }
if (B < 0) { Bd = -1; B = -B; }
int x = 1, y = 0;
u = 0, v = 1;
while (A != 0)
{
int q = B/A;
int r = B%A;
int m = u-x*q;
int n = v-y*q;
B = A;
A = r;
u = x;
v = y;
x = m;
y = n;
}
u *= Ad;
v *= Bd;
return B;
}
int main(int argc, const char * argv[])
{
int t;
scanf("%d", &t);
for (int i = 0; i<t; i++) {
int x1, x2, y1, y2, M;
scanf("%d %d %d %d %d", &M, &x1, &y1, &x2, &y2);
if ( x1 == x2 ) // vertical line
{
if (x1%M != 0) { // in between the horizontal lines
cout << 0 << endl;
} else
{
int r = abs((y2-y1)/M); // number of points
if (y2%M == 0 || y1%M == 0) // +1 if the line starts or ends on the point
r++;
cout << r << endl;
}
} else {
if (x2 < x1)
{
int c;
c = x1;
x1 = x2;
x2 = c;
}
int A, B, C;
C = x1*y2-y1*x2;
A = M*(y2-y1);
B = -M*(x2-x1);
int u, v;
int g = gcd(A, B, u, v);
//cout << "A: " << A << " B: " << B << " C: " << C << endl;
//cout << A << "*" << u <<"+"<< B <<"*"<<v<<"="<<g<<endl;
double a = -x1/(double)(x2-x1);
double b = M/(double)(x2-x1);
double Z = (-a-C*b/g*u)*g/(B*b);
double Y = (1-a-C*b/g*u)*g/(B*b);
cout << floor(Z) - ceil(Y) + 1 << endl;
}
}
return 0;
}
Thank you for your help! Please check if all special cases are taken into consideration.

Bit Reversal using bitwise

I am trying to do bit reversal in a byte. I use the code below
static int BitReversal(int n)
{
int u0 = 0x55555555; // 01010101010101010101010101010101
int u1 = 0x33333333; // 00110011001100110011001100110011
int u2 = 0x0F0F0F0F; // 00001111000011110000111100001111
int u3 = 0x00FF00FF; // 00000000111111110000000011111111
int u4 = 0x0000FFFF;
int x, y, z;
x = n;
y = (x >> 1) & u0;
z = (x & u0) << 1;
x = y | z;
y = (x >> 2) & u1;
z = (x & u1) << 2;
x = y | z;
y = (x >> 4) & u2;
z = (x & u2) << 4;
x = y | z;
y = (x >> 8) & u3;
z = (x & u3) << 8;
x = y | z;
y = (x >> 16) & u4;
z = (x & u4) << 16;
x = y | z;
return x;
}
It can reverser the bit (on a 32-bit machine), but there is a problem,
For example, the input is 10001111101, I want to get 10111110001, but this method would reverse the whole byte including the heading 0s. The output is 10111110001000000000000000000000.
Is there any method to only reverse the actual number? I do not want to convert it to string and reverser, then convert again. Is there any pure math method or bit operation method?
Best Regards,
Get the highest bit number using a similar approach and shift the resulting bits to the right 33 - #bits and voila!
Cheesy way is to shift until you get a 1 on the right:
if (x != 0) {
while ((x & 1) == 0) {
x >>= 1;
}
}
Note: You should switch all the variables to unsigned int. As written you can have unwanted sign-extension any time you right shift.
One method could be to find the leading number of sign bits in the number n, left shift n by that number and then run it through your above algorithm.
It's assuming all 32 bits are significant and reversing the whole thing. You COULD try to make it guess the number of significant bits by finding the highest 1, but that isn't necessarily accurate so I'd suggest you modify the function so it takes a second parameter indicating the number of significant bits. Then after reversing the bits just shift them to the right.
Try using Integer.reverse(int x);

Resources