Array of random numbers with sum in given range? - c

In C, how do I get an array of n numbers (each 0x00-0xFF in my case), of which the sum is within a given range 0..k?
The almost duplicate C++ multiple random numbers adding up to equal a certain number targets a specific sum, but in my case the sum can be anything between 0..k.

You need to specify what is the desired distribution of the random numbers.
If there are no further requirements, I would suggest one of the following:
(1)
pick random number a[1] in interval 0 .. k
pick random number a[2] in interval 0 .. k-a[1]
pick random number a[3] in interval 0 .. k-a[1]-a[2]
...
pick random number a[n] in interval 0 .. k-a[1]-a[2]-...-a[n-1]
If you have upper limit m on the range of the random number, use min(k-a[1]-... m) as upper bound of the interval.
Disadvantages: you will get a lot of small numbers and just a few big ones.
(2)
pick n random numbers a[1], .., a[n] in interval 0 .. m, m being the upper limit
s = a[1]+a[2]+...+a[n]
multiply each a[i] by k/s (if integers are required, round down)
Disadvantages: It is unlikely to get large numbers this way. If integers are required, there will likely be a gap between the sum of numbers and k due to rounding error.
I think you get "nicer" numbers with option (2) but as stated above, it depends on the requirements.

Assuming k is less than 255 * n one solution is to assign k / n to every element of the array, then randomly subtract a value to the array elements.
// for (int i = 0; i < n; i++) array[i] = k / n;
// for (int i = 0; i < n; i++) array[i] -= randbetween(0, array[i]);
for (int i = 0; i < n; i++) array[i] = randbetween(0, k / n);
This has an expected sum of k / 2. By tweaking the randbetween() function you can change the probability of the resulting array sum.

It is easy to create one number within range [0, 255].
It is easy to identify if k > 255*n or k < 0 there is no solution.
If 0 <= k <= 255*n, the solution exists. Here we only talk about n > 1 condition.
You have created n-1 random numbers, and sum of the n-1 numbers is s1, suppose the nth number is x. So s1 + x = k, and x should be [0, 255]. If the n-1 numbers are all within range [0, a], then (n-1)*a + 255 >= k, we get a >= (k-255)/(n-1).
If k > 255, just let a = (k-255)/(n-1). It means s1 is [0, k-255]. Then the nth number x can be any random number within [0, 255].
So the solution is arbitrary select n-1 numbers each within [0, (k-255)/(n-1)] (you know (k-255)/(n-1) <= 255, thus it satisfied your condition), and select one random number within [0, 255].
If k <= 255, arbitrary select n numbers each within [0, k/n] (you know k/n is within [0, 255]).

Related

Finding smallest number N, having k trailing zeroes in factorial of N

I got a problem about finding the smallest N, where N! contains exactly k trailing zeros.
I've got an idea of finding it through binary search from here - Finding natural numbers having n Trailing Zeroes in Factorial .
Is it possible to calculate it without binary search, using any formula or some iterations?
You can use the formula that the number of times p divides n! is:
k = floor(n/p) + floor(n/p^2) + floor(n/p^3) + ...
Combining this with the fact that the number of trailing zeros is exactly equal to the number of times 5 evenly divides it (each zero corresponds to a 2 and 5 pair, but given 2 is less than 5, we'll always have more 2s than 5s, and thus be constrained by our 5s).
With some algebra, and applying the formula for an infinite geometric series, we can get a very (very!) close lower bound on n. We then just increment n by 5 as much as necessary get the actual result. In practice, this ends up being 1-2 increments for k in the lower thousands, so its fairly negligible.
Full code below:
def count_div5(n):
result = 0
pow5 = 5
while pow5 <= n:
result += n // pow5
pow5 *= 5
return result
def n_from_fact_zeros(k):
n = round(4*k)
n += -n % 5
while count_div5(n) < k:
n += 5
return n

Finding the probability that two items are compared. (hints please)

I'm attempting to solve the following problem (from Prof. Jeff Erikson's notes): Given the algorithm below which takes in an unsorted array A and returns the k-th smallest element in the array (given that Partition does what its name implies via the standard quicksort method given the pivot returned by Random (which is assumed to return a uniformly random integer between 1 and n in linear time) and returns the new index of the pivot), we are to find the exact probability that this algorithm compares the i-th smallest and j-th smallest elements in the input array.
QuickSelect(A[1..n],k):
r <-- Partition(A[1..n],Random(n))
if k < r:
return QuickSelect(A[1..r-1],k)
else if k > r:
return QuickSelect(A[r+1..n],k-r)
else:
return A[k]
Now, I can see that the probability of the first if statement being true is (n-k)/n, the probability of the second block being true is (k-1)/n, and the probability of executing the else statement is 1/n. I also know that (assuming i < j) the probability of i < r < j is (j-i-1)/n which guarantees that the two elements are never compared. On the other hand, if i==r or j==r, then i and j are guaranteed to be compared. The part that really trips me up is what happens if r < i or j < r, because whether or not i and j are compared depends on the value of k (whether or not we are able to recursively call QuickSelect).
Any hints and/or suggestions would be greatly appreciated. This is for homework, so I would rather not have full solutions given to me so that I may actually learn a bit. Thanks in advance!
As it has already been mentioned Monte Carlo method is simple solution for fast (in sense of implementation) approximation.
There is a way to compute exact probability using dynamic programming
Here we will assume that all elements in array are distinct and A[i] < A[j].
Let us denote P(i, j, k, n) for probability of comparison ith and jth elements while selecting k-th in an n-elements array.
Then there is equal probability for r to be any of 1..n and this probability is 1/n. Also note that all this events are non-intersecting and their union forms all the space of events.
Let us look carefully at each possible value of r.
If r = 1..i-1 then i and j fall into the same part and the probability of their comparison is P(i-r, j-r, k-r, n-r) if k > r and 0 otherwise.
If r = i the probability is 1.
If r = i+1..j-1 the probability is 0.
If r = j the probability is 1 and if r = j+1..n the probability is P(i, j, k, r-1) if k < r and 0 otherwise.
So the full recurrent formula is P(i, j, k, n) = 1/n * (2 + Sum for r = 1..min(r, i)-1 P(i-r, j-r, k-r, n-r) + sum for r = max(j, k)+1..n P(i, j, k, r-1))
Finally for n = 2 (for i and j to be different) the only possible Ps are P(1, 2, 1, 2) and P(1, 2, 2, 2) and both equal 1 (no matter what r is equal to there will be a comparison)
Time complexity is O(n^5), space complexity is O(n^4). Also it is possible to optimize calculations and make time complexity O(n^4). Also as we only consider A[i] < A[j] and i,j,k <= n multiplicative constant is 1/8. So it would possible to compute any value for n up to 100 in a couple of minutes, using straight-forward algorithm described or up to 300 for optimized one.
Note that two positions are only compared if one of them is the pivot. So the best way to look at this is to look at the sequence of chosen pivots.
Suppose the k-th smallest element is between i and j. Then i and j are not compared if and only if an element between them is selected as a pivot before i or j are. What is the probability that this happens?
Now suppose the k-th smallest element is after j. i and j are not compared if and only if an element between i+1 and k (excluding j) is selected as a pivot before i or j are. What is the probability that this happens?

Rearrange array with sum and length n while minimizing distance change

An array A[n] (length n) of nonnegative integers is given. The array contains n objects dispersed through itself, so that A[i] represents the number of objects in slot i, and the sum from i=0 to n of A[i] is n. We must rearrange the array such that each element is 1. We are given that n <= 10^5. (So O(n^2) is too slow, but O(n log n) is fine.)
Rearranging works as follows: if A[i] = k and A[j] = h, then we can decrease A[i] by some positive integer m <= k and increase some element A[j] by m correspondingly, so that A[i] = k-m and A[j] = h+m. However, each rearrange has a cost given by Cost(m, i, j) = m d(i, j)^2 (proportional to the square of the distance of the rearrange). The array works such that the distance function d(i, j) is standard subtraction, but it can wrap around the array, so if n = 7 then d(1, 4)=3, but d(0, 6) = 1 and d(1,5) = 3, etc. That is, we can think of the array as "circular."
The total cost is given by the sum of the cost function over all rearranges, and our goal is to find the minimum value of the cost function such that A[i] = 1 for all i, i.e. all the elements are equal to 1. Each object can only be rearranged once, so for example if A = [5,0,0,0,0] we can't just move an object from A[0] to A[1] and then to A[2] to circumvent the squaring of the distance.
Help on an algorithm or pseudocode/code to solve this problem would be appreciated.

Finding continuous subsequence that minimizes the average of the rest of the array?

Suppose there's an integer array arr[0..n-1]. Find a subsequence sub[i..j] (i > 0 and j < n - 1) such that the rest of the array has the smallest average.
Example:
arr[5] = {5,1,7,8,2};
Remove {7,8}, the array becomes {5, 1, 2} which has average 2.67 (smallest possible).
I thought this is a modification of the Longest Increasing Subsequence but couldn't figure it out.
Thanks,
Let's find the average value using binary search.
Suppose, that sum of all elements is S.
For given x let's check if exist i and j such that avg of all elements except from i to j less or equal to x.
To do that, let's subtract x from all elements in arr. We need to check if exists i and j such that sum of all elements except from i to j less or equal to zero. To do that, lets find sum of all elements in current array: S' = S - x * n. So we want to find i and j such that sum from i to j will be greater or equal than S'. To do that, let's find subarray with the larges sum. And this can be done using elegant Jay Kadane's algorithm: https://en.wikipedia.org/wiki/Maximum_subarray_problem
When to terminate binary search? When the maximum subarray sum will be zero (or close enough).
Time complexity: O(n log w), w - presicion of the binary search.

find maximum difference between successive elements [duplicate]

Given an array of N integers, sort the array, and find the 2 consecutive numbers in the sorted array with the maximum difference.
Example – on input [1,7,3,2] output 4 (the sorted array is [1,2,3,7], and the maximum difference is 7-3=4).
Algorithm A runs in O(NlogN) time.
I need to find an algorithm identical in function to algorithm A, that runs in O(N) time.
Let the array be X and let n = length(X). Put each element x in bucket number floor((x - min(X)) * (n - 1) / (max(X) - min(X))). The width of each bucket is (max(X) - min(X))/(n - 1) and the maximum adjacent difference is at least that much, so the numbers in question wind up in different buckets. Now all we have to do is consider the pairs where one is the max in bucket i and the other is the min in bucket j where i < j and all buckets k in (i, j) are empty. This is linear time.
Proof that we really need floor: let the function be f(X). If we could compute f(X) in linear time, then surely we could decide in linear time whether
0 < f(X) ≤ (max(X) - min(X))/(length(X) - 1),
i.e., whether the elements of X are evenly spaced and not all identical. Let this predicate be P(X). The support of P has factorial(length(X)) connected components, so the usual Ω(n log n) lower bounds for algebraic models of computation apply.
Execute a Counting Sort and then scan the result for the largest difference.
Because of the consecutive number requirement, at first glance it seems like any solution will require sorting, and this means at best O(n log n) unless your number range is sufficiently constrained for a Counting Sort. But if it is, you win with O(n).
Now, first try to think if you were already given the minimum value MIN and maximum value MAX in the array of size N, under what circumstances would the max gap be minimum and maximum ?
Obviously, maximum gap will be maximum when all elements are either MIN or MAX making maxgap = MAX - MIN.
Maximum gap will be minimum when all the elements are equally spaced apart between MIN and MAX. Lets say the spacing between them is gap.
So, they are arranged as
MIN, MIN + gap, MIN + 2*gap, MIN + 3*gap, ... MIN + (N-1)*gap
where
MIN + (N-1)*gap = MAX .
gap = (MAX - MIN) / (N - 1).
So, we know now that our answer will lie in the range [gap, MAX - MIN].
Now, if we know the answer is more than gap, what we do is create buckets of size gap for ranges .
[MIN, MIN + gap), [Min + gap, `MIN` + 2* gap) ... and so on
There will only be (N-1) such buckets. We place the numbers in these buckets based on their value.
If you pick any 2 numbers from a single bucket, their difference will be less than gap, and hence they would never contribute to maxgap ( Remember maxgap >= gap ). We only need to store the largest number and the smallest number in each bucket, and we only look at the numbers across bucket.
Now, we just need to go through the bucket sequentially ( they are
already sorted by value ), and get the difference of min_value with
max_value of previous bucket with at least one value. We take maximum of all such values.
int maximumGap(const vector<int> &num) {
if (num.empty() || num.size() < 2) return 0;
int maxNum = *max_element(num.begin(), num.end());
int minNum = *min_element(num.begin(), num.end());
//average gap from minNum to maxNum.
int gap = (maxNum - minNum - 1) / (num.size() - 1) + 1;
//number of buckets = num.size() - 1
vector<int> bucketsMin(num.size() - 1, INT_MAX);
vector<int> bucketsMax(num.size() - 1, INT_MIN);
//put into buckets
for (int i = 0; i < num.size(); i++)
{
if (num[i] != maxNum && num[i] != minNum)
{
int buckInd = (num[i] - minNum) / gap;
bucketsMin[buckInd] = min(bucketsMin[buckInd], num[i]);
bucketsMax[buckInd] = max(bucketsMax[buckInd], num[i]);
}
}
int maxGap = INT_MIN;
int previous = minNum;
for (int i = 0; i < num.size() - 1; i++)
{
if (bucketsMin[i] == INT_MAX && bucketsMax[i] == INT_MIN) continue; //empty
//i_th gap is minvalue in i+1_th bucket minus maxvalue in i_th bucket
maxGap = max(maxGap, bucketsMin[i] - previous);
previous = bucketsMax[i];
}
maxGap = max(maxGap, maxNum - previous);
return maxGap;
}
Find minimum and maximum
Pick a random number k from the array
Sort the algorithm by placing all the values smaller than k to the left and larger than k to the right.
You know the minimum and the maximum of both of the groups, calculate the gape of the left group assuming that the values are on a strait line. Do the same for the right group.
Go to 2 with the group that got the bigger gape, you know the min and max of that group. Do this until the selected group got no more than 4 values.
You got now a group with only 4 elements, sort and find the solution.
Here is an example of how this algorithm works:
Input: 9 5 3 4 12 9 31 17
Pick random number: k = 9
Sort by smaller and bigger values of k
5 3 4 9 9 12 31 17, k is in index 3
Left group gape = (9 + 3) / (4 - 1) = 4
Right group gape = (31 + 9) / (5 - 1) = 10
We pick the right group 9 9 12 31 17
Pick random number: k = 12
Sort by smaller and bigger values of k
9 9 12 31 17, k is in index 2
Left group gape = (12 + 9) / (3 - 1) = 11.5
Right group gape = (31 + 12) / (3 - 1) = 21.5
The maximum gape in 12 31 17 is 31 - 17 = 14
My algorithm is very similar to Selection Algorithm for finding the k index value of sorted algorithm in linear time.

Resources