compare numbers and save them in a array in Kotlin - arrays

2 part question
First part - I wanted to ask the user to give a number and then create an array with as many positions as the number introduced, how can i do this?
Second Part - The array is to be filled with random numbers but i don't want duplicate numbers . This is my code and it keeps registering duplicate numbers
var A = intArrayOf(0,0,0,0,0,0)
for (i in 0..A.size - 1) {
val rnd = (0..10).random()
for (j in 0..A.size-1) {
if (rnd == A[j]){
break
}
else{
A[i] = rnd
break
}
}
}
what am i doing wrong?

One thing to keep in mind is, if you're trying to generate random numbers within a range, but have no duplicates, you need to ensure that the range of random numbers is at least equal to the size of the destination array.
For instance, if you're trying to generate an array of size 12 with a range from 0..10, it can't be done as there are only 11 possibilities.
Depending on your requirements (is the range just 0 till the size of the array?) if the space of numbers is small you could simplify this quite a bit by shuffling a list from rangeStart..rangeEnd:
/**
* Generates an array of unique random numbers between zero and the larger of
* arraySize or upperBound. If upperBound is not specified, it defaults to be
* arraySize.
*
* #param arraySize the size of the returned integer array
* #param upperBound an optional upper bound for the range of random numbers
*/
fun generateArray(arraySize: Int, upperBound: Int = size): IntArray {
return (0..Math.max(upperBound, arraySize)).shuffled().take(arraySize).toIntArray()
}
This also avoids wasteful generation of discarded duplicate random numbers and ensures that the function call takes a deterministic amount of time to execute.

You can ask from the user for the number of the array's items like this:
var n = 0
println("Number of items in the array = ")
try {
n = readLine()!!.toInt()
} catch (e: Exception) {
}
Now the array will be initialized if n is a positive integer and then filled with random non repeating integer numbers:
if (n > 0) {
val array = IntArray(n) // initialize an array of n items all being 0
val r = Random() // create a random numbers generator
array.indices.forEach {
var newInt = 0
while (array.contains(newInt)) { newInt = r.nextInt() }
array[it] = newInt
}
array.forEach { print("$it ") }
}
With contains() you can check if the new generated random number already exists in the array (this means that the array will be filled with non zero integers).
If you want the random numbers to be in a specific range then instead of:
newInt = r.nextInt()
use:
newInt = r.nextInt((upperBound + 1) - lowerBound) + lowerBound
or for Kotlin version 1.3+:
newInt = (lowerBound..upperBound).random()

Related

Rebuild an array of integers after summing the digits of each element

We have an strictly increasing array of length n ( 1 < n < 500) . We sum the digits of each element to create a new array with each elements values is in range 1 to 500.The task is to rebuild the old array from the new one. since there might be more than one answer, we want the answers with the minimum value of the last element.
Example:
3 11 23 37 45 123 =>3 2 5 10 9 6
now from the second array, we can rebuild the original array in many different ways for instance:
12 20 23 37 54 60
from all the possible combinations, we need the one we minimum last element.
My Thoughts so far:
The brute force way is to find all possible permutations to create each number and then create all combinations possible of all numbers of the second array and find the combination with minimum last element. It is obvious that this is not a good choice.
Using this algorithm(with exponential time!) we can create all possible permutations of digits that sum to a number in the second arrays. Note that we know the original elements were less than 500 so we can limit the death of search of the algorithm.
One way I thought of that might find the answer faster is to:
start from the last element in the new arrays and find all possible
numbers that their digit sum resulted this element.
Then try to use the smallest amount in the last step for this element.
Now try to do the same with the second to last element. If the
minimum permutation value found for the second to last element is bigger
than the one found for the last element, backtrack to the last
element and try a larger permutation.
Do this until you get to the first element.
I think this is a greed solution but I'm not very sure about the time complexity. Also I want to know is there a better solution for this problem? like using dp?
For simplicity, let's have our sequence 1-based and the input sequence is called x.
We will also use an utility function, which returns the sum of the digits of a given number:
int sum(int x) {
int result = 0;
while (x > 0) {
result += x % 10;
x /= 10;
}
return result;
}
Let's assume that we are at index idx and try to set there some number called value (given that the sum of digits of value is x[idx]). If we do so, then what could we say about the previous number in the sequence? It should be strictly less than value.
So we already have a state for a potential dp approach - [idx, value], where idx is the index where we are currently at and value denotes the value we are trying to set on this index.
If the dp table holds boolean values, we will know we have found an answer if we have found a suitable number for the first number in the sequence. Therefore, if there is a path starting from the last row in the dp table and ends at row 0 then we'll know we have found an answer and we could then simply restore it.
Our recurrence function will be something like this:
f(idx, value) = OR {dp[idx - 1][value'], where sumOfDigits(value) = x[idx] and value' < value}
f(0, *) = true
Also, in order to restore the answer, we need to track the path. Once we set any dp[idx][value] cell to be true, then we can safe the value' to which we would like to jump in the previous table row.
Now let's code that one. I hope the code is self-explanatory:
boolean[][] dp = new boolean[n + 1][501];
int[][] prev = new int[n + 1][501];
for (int i = 0; i <= 500; i++) {
dp[0][i] = true;
}
for (int idx = 1; idx <= n; idx++) {
for (int value = 1; value <= 500; value++) {
if (sum(value) == x[idx]) {
for (int smaller = 0; smaller < value; smaller++) {
dp[idx][value] |= dp[idx - 1][smaller];
if (dp[idx][value]) {
prev[idx][value] = smaller;
break;
}
}
}
}
}
The prev table only keeps information about which is the smallest value', which we can use as previous to our idx in the resulting sequence.
Now, in order to restore the sequence, we can start from the last element. We would like it to be minimal, so we can find the first one that has dp[n][value] = true. Once we have such element, we then use the prev table to track down the values up to the first one:
int[] result = new int[n];
int idx = n - 1;
for (int i = 0; i <= 500; i++) {
if (dp[n][i]) {
int row = n, col = i;
while (row > 0) {
result[idx--] = col;
col = prev[row][col];
row--;
}
break;
}
}
for (int i = 0; i < n; i++) {
out.print(result[i]);
out.print(' ');
}
If we apply this on an input sequence:
3 2 5 10 9 6
we get
3 11 14 19 27 33
The time complexity is O(n * m * m), where n is the number of elements we have and m is the maximum possible value that an element could hold.
The space complexity is O(n * m) as this is dominated by the size of the dp and prev tables.
We can use a greedy algorithm: proceed through the array in order, setting each element to the least value that is greater than the previous element and has digits with the appropriate sum. (We can just iterate over the possible values and check the sums of their digits.) There's no need to consider any greater value than that, because increasing a given element will never make it possible to decrease a later element. So we don't need dynamic programming here.
We can calculate the sum of the digits of an integer m in O(log m) time, so the whole solution takes O(b log b) time, where b is the upper bound (500 in your example).

How to create n strings of random lengths the sum of which is equal to a given amount?

I'm trying to create an algorithm to create n strings of random length the sum of which is equal to a given amount.
An example to make it clearer:
total = 20;
n = 7;
strings = ['aaaa', 'a', 'aaaaaaa', 'aa', 'aaa', 'aa', 'a'];
So I have 7 strings of random lengths and the sum of their individual lengths is (unless I made an error counting) 20.
Till now I came up with this recursive function:
gaps = [];
function createGapsArray(total, n) {
if (n == 1) {
var gapLength = total;
} else {
var gapLength = getRandomInt(1, total / 2);
}
var gap = "";
for (var i = 0; i < gapLength; i++) {
gap += "a";
}
gaps.push(gap);
if (n > 1 && total > 0) {
createGapsArray(total - gapLength, --n);
}
}
Which doesn't really work. Usually it finishes before generating all the n segments I want. With the few tests that I've done, it seems that dividing the total by 4 instead of 2, gets the job done. Like:
var gapLength = getRandomInt(1, total / 4);
But the choice of this constraint is just arbitrary. I'm wondering if there is a better approach to this.
Also, I'm aware that with my approach the algorithm is likely to generate longer segments at first and smaller ones towards the end. I wouldn't mind an even distribution, but it's not a big deal because for what I need it I can simply shuffle the array once it's done.
This is a similar problem to "find a random collection of k numbers whose sum is N". The original version of this answer used a simple solution which is unbiased if the numbers are continuous (i.e. floating point): generate k-1 numbers in the range [0, N], sort them, put 0 at the beginning and N at the end, and then find the differences between successive elements. But since there are no fractional characters, we need the numbers to be integers and the above algorithm is biased against collections which include 0 (there is an infinitesimal probability of getting 0 in the continuous case, but it is significant in the discrete case).
An unbiased solution for generating non-empty integer solutions is to find a random (k-1)-combination of the integers in the inclusive range [1, N-1]. To find the random combination use the first k-1 elements of a random shuffle of the range (using the Fisher-Yates shuffle). The combination is then sorted (if necessary) and a 0 prepended; these values are the starting positions of each string (so that the next value is the ending position.)
That will not produce empty substrings, since each substring has a unique starting point. To include empty substrings, use the above with N+k instead of N, and then shrink every range by 1: if the indices are sorted, you can do that by subtracting i from the ith index.
In Python:
from random import sample
def random_split(str, k):
v = [0] + sorted(sample(range(1, len(str)), k-1)) + [len(str)]
return [str[v[i]:v[i+1]] for i in range(k)]
def random_split_allow_empty(str, k):
v = [0] + sorted(sample(range(1, len(str)+k), k-1)) + [len(str)+k]
return [str[v[i]-i:v[i+1]-i-1] for i in range(k)]
In Javascript:
function shuffle(vec, k) {
for (let i = 0; i < k; ++i) {
let r = i + Math.floor(Math.random() * (vec.length - i));
let t = vec[r];
vec[r] = vec[i];
vec[i] = t;
}
return vec;
}
function random_partition(N, k) {
let v = [];
for (let i = 1; i < N; ++i) v[i-1] = i;
shuffle(v, k - 1);
v[k-1] = 0;
return v.slice(0, k).sort((a,b)=>a-b);
}
function random_split(s, k) {
return random_partition(s.length, k).map(
(v, i, a) => s.slice(v, a[i+1]));
}
function random_split_allow_empty(s, k) {
return random_partition(s.length + k, k).map((v,i)=>v-i).map(
(v, i, a) => s.slice(v, a[i+1]));
}
Strictly speaking, you can't do this, because you're adding constraints to at least the last "string" that violate the desired randomness property. Of course, how strictly you need to interpret the requirement for randomness depends largely on what you're doing in the bigger problem domain.
What you could do instead, is start with an initial string of the desired length, and then iteratively generate a random split point until you have the desired number of fragments. To be truly random, you'd have to allow for some of those fragments to be empty (e.g. what happens if you randomly pick a single-character fragment to split?), but that could probably be worked around without doing too much violence to the randomness of the overall result...
The way to think of it is as having string of characters of length equal to total. I'll use 20 as an example:
string: aaaaaaaaaaaaaaaaaaaa
index: 01234567890123456789
You then generate N-1 random numbers between 0 and total that correspond to the positions that you should cut the string to generate N different strings.
Lets say the numbers are 5, 8, 13, 15, 1, 3. These will be the indices to cut the string:
string: a aa aa aaa aaaaa aa aaaaa
index: 0|12|34|567|89012|34|56789
This is the same as generating N-1 random numbers, sorting them, adding 0 at the beginning of the list and total at the end, and taking the difference:
var numbers = [0];
for (var i = 0; i < N-1; i++) numbers.push(getRandomInt(0, total));
numbers.push(total);
numbers.sort();
var strings = [];
for (var i = 0; i < N; i++)
strings.push(new Array(numbers[i + 1] - numbers[i]).join('a'));
This will give a uniform distribution.
Note that if you want only non-empty strings there should be no duplicate random values.

Assigning user-determined coordinates to a nested array

I have two integers, range1 and range2, and a nested integer array distance[][].
I also have two integer arrays, elasticity[] and resistance[], both containing a group of user-determined values. The aforementioned range1 is equal to the length of elasticity[], whilst range2 is equal to the length of resistance[].
What I'm trying to do is set each location in distance[][] to a specific "coordinate". As an example, assume range1 = 2 and range2 = 3:
distance[0][0] = elasticity[0] * resistance[0];
distance[0][1] = elasticity[0] * resistance[1];
distance[0][2] = elasticity[0] * resistance[2];
distance[1][0] = elasticity[1] * resistance[0];
distance[1][1] = elasticity[1] * resistance[1];
distance[1][2] = elasticity[1] * resistance[2];
and so forth. Obviously I can't use anything like the above example, because the values of range1 and range2 are a result of the user's input to elasticity[] and resistance[], and so may be different every time the program runs. I attempted to use a nested for loop, like so:
int distance[range1][range2];
for(int i = 0; i <= range1; i++)
{
for(int j = 0; j <= range2; j++)
{
distance[i][j] = elasticity[i] * resistance[j];
}
}
which, as far as I can tell, should work, but Xcode just spat runtime errors at me.
Anyway, I'm not sure what I can do to fix this; the program is supposed to take three values from the user (the minimum + maximum resistance values, and an increment size for the elasticity) in order to calculate the maximum distance of a projectile and output the results in the form of a table.
Help!
First of all, if using plain C, you need to provide constant values for the matrix dimensions (you need to set maximum values for range1 and range2, like this for instance:
int distance[200][200];
This means the maximum of range1 and range2 is 200
Then, in the loop condition, you need to take into account that array indexing is 0-based. Therefore, if you have say, 4 elements in an array, their indexes will be 0, 1, 2 and 3.
So, you need to change your code like this:
for(int i = 0; i < range1; i++)
{
for(int j = 0; j < range2; j++)
{
distance[i][j] = elasticity[i] * resistance[j];
}
}
so that the index is always less than the array dimension.
I hope this helps.
Cheers.

Given an array of booleans, what is the most efficient way to select the index of a random TRUE value?

You're given an array of size n, containing arbitrary boolean values.
What is the fastest way to return the index of a random TRUE value.
The algorithm should randomly return any one of the indices containing a TRUE.
Something like this:
int count = 0;
int index = -1;
for (int i = 0; i != n; ++i)
{
if (values[i])
{
++count;
if (unit_random <= 1.0f / count)
{
index = i;
}
}
}
So for 4 values for example you get the following probabilities for their indices:
1: (1 / 1) * (1 / 2) * (2 / 3) * (3 / 4) = 1 / 4
2: (1 / 2) * (2 / 3) * (3 / 4) = 1 / 4
3: (1 / 3) * (3 / 4) = 1 / 4
4: 1 / 4 = 1 / 4
EDIT: As Steve Jessop pointed out the floating point comparision will eventually lead to a very non uniform selection. Assuming unit_random is defined as rand() / RAND_MAX the comparision can be changed to:
typedef unsigned long long u64;
u64 product = u64(count) * rand();
if (product <= u64(RAND_MAX))
This won't give perfect distribution due to the discrete nature of rand but it will be better.
The quickest solution - assuming you don't select repeatedly on the same array - is to pick a random index, return it if it's true, and repeat if not. In the best case, where all entries are true, this is O(1); in the worst case, where only one entry is true, this is O(n) (each try has a 1/n chance of hitting the only true value, which means an expected number of tries of n). This is no worse than any of the other posted solutions.
If you expect the array to usually be almost all false, though, you may want to pick another solution, as the variance in runtime of this random method will be high.
It's not quite clear what "randomly distibuted" means. Does it mean "with some unknown distribution"? If so, let's pretend all possible distributions are equally probable, so the "expected distribution" (like in "expected value") is uniform (the "average" of all possible distributions.) Then any index is TRUE with a probability of 1/2. So your task becomes the task of iterating through the array as quickly as possible. Start at the beginning, like you would normally iterate an array, until you encounter a TRUE value.
In order to return it, you must first count the True values (there is not way to skip that) and accumulate their indices in another array. And after counting you need to just generate random integer from 0 to N-1 (where N is the number of True values) and pick the value from the created array.
in pseudo-python:
indices=[]
for i,val in enumerate(arr):
if val:
indices.append(i)
randi = randint(0,len(indices)-1)
return indices[randi]
Simple solution: Generate a permutation of possible indexes (1:n ?) and in the order of that permutation return index if the corresponding value is true
def randomTrue(x):
perm = randomPermute(0:len(x))
for i in perm:
if x[i]:
return i

Starting with a 10x10 array how do I choose 10 random sites

I am trying to write C code to randomly select 10 random sites from a grid of 10x10. The way I am considering going about this is to assign every cell a random number between zero and RAND_MAX and then picking out the 10 smallest/largest values. But I have very little idea about how to actually code something like that :/
I have used pseudo-random number generators before so I can do that part.
Just generate 2 random numbers between 0 and 9 and the select the random element from the array like:
arr[rand1][rand2];
Do that 10 times in a loop. No need to make it more complicated than that.
To simplify slightly, treat the 10x10 array as an equivalent linear array of 100 elements. Now the problem becomes that of picking 10 distinct numbers from a set of 100. To get the first index, just pick a random number in the range 0 to 99.
int hits[10]; /* stow randomly selected indexes here */
hits[0] = random1(100); /* random1(n) returns a random int in range 0..n-1 */
The second number is almost as easy. Choose another number from the 99 remaining possibilities. Random1 returns a number in the continuous range 0..99; you must then map that into the broken range 0..hits[0]-1, hits[0]+1..99.
hits[1] = random1(99);
if (hits[1] == hits[0]) hits[1]++;
Now for the second number the mapping starts to get interesting because it takes a little extra work to ensure the new number is distinct from both existing choices.
hits[2] = random1(98);
if (hits[2] == hits[0]) hits[2]++;
if (hits[2] == hits[1]) hits[2]++;
if (hits[2] == hits[0]) hits[2]++; /* re-check, in case hits[1] == hits[0]+1 */
If you sort the array of hits as you go, you can avoid the need to re-check elements for uniqueness. Putting everything together:
int hits[10];
int i, n;
for (n = 0; n < 10; n++) {
int choice = random1( 100 - n ); /* pick a remaining index at random */
for (i = 0; i < n; i++) {
if (choice < hits[i]) /* find where it belongs in sorted hits */
break;
choice++; /* and make sure it is distinct *
/* need ++ to preserve uniform random distribution! */
}
insert1( hits, n, choice, i );
/* insert1(...) inserts choice at i in growing array hits */
}
You can use hits to fetch elements from your 10x10 array like this:
array[hits[0]/10][hits[0]%10]
for (int i = 0; i < 10; i++) {
// ith random entry in the matrix
arr[rand() % 10][rand() % 10];
}
Modified this from Peter Raynham's answer - I think the idea in it is right, but his execution is too complex and isn't mapping the ranges correctly:
To simplify slightly, treat the 10x10 array as an equivalent linear array of 100 elements. Now the problem becomes that of picking 10 distinct numbers from a set of 100.
To get the first index, just pick a random number in the range 0 to 99.
int hits[10]; /* stow randomly selected indexes here */
hits[0] = random1(100); /* random1(n) returns a random int in range 0..n-1 */
The second number is almost as easy. Choose another number from the 99 remaining possibilities. Random1 returns a number in the continuous range 0..99; you must then map that into the broken range 0..hits[0]-1, hits[0]+1..99.
hits[1] = random1(99);
if (hits[1] >= hits[0]) hits[1]++;
Note that you must map the complete range of hits[0]..98 to hits[0]+1..99
For another number you must compare to all previous numbers, so for the third number you must do
hits[2] = random1(98);
if (hits[2] >= hits[0]) hits[2]++;
if (hits[2] >= hits[1]) hits[2]++;
You don't need to sort the numbers! Putting everything together:
int hits[10];
int i, n;
for (n = 0; n < 10; n++) {
int choice = random1( 100 - n ); /* pick a remaining index at random */
for (i = 0; i < n; i++)
if (choice >= hits[i])
choice++;
hits[i] = choice;
}
You can use hits to fetch elements from your 10x10 array like this:
array[hits[0]/10][hits[0]%10]
If you want your chosen random cells from grid to be unique - it seems that you really want to construct random permutations. In that case:
Put cell number 0..99 into 1D array
Take some shuffle algorithm and toss that array with it
Read first 10 elements out of shuffled array.
Drawback: Running time of this algorithm increases linearly with increasing number of cells. So it may be better for practical reasons to do as #PaulP.R.O. says ...
There is a subtle bug in hjhill's solution. If you don't sort the elements in your list, then when you scan the list (inner for loop), you need to re-scan whenever you bump the choice index (choice++). This is because you may bump it into a previous entry in the list - for example with random numbers: 90, 89, 89.
The complete code:
int hits[10];
int i, j, n;
for (n = 0; n < 10; n++) {
int choice = random1( 100 - n ); /* pick a remaining index at random */
for (i = 0; i < n; i++) {
if (choice >= hits[i]) { /* find its place in partitioned range */
choice++;
for (j = 0; j < i; j++) { /* adjusted the index, must ... */
if (choice == hits[j]) { /* ... ensure no collateral damage */
choice++;
j = 0;
}
}
}
}
hits[n] = choice;
}
I know it's getting a little ugly with five levels of nesting. When selecting just a few elements (e.g., 10 of 100) it will have better performance than the sorting solution; when selecting a lot of elements (e.g., 90 of 100), performance will likely be worse than the sorting solution.

Resources