How to get N unique random quantities without indefinite loop? - c

I want to generate 5 random positions on a map. I can only come up with the code below, which uses while (1) and break:
int map[10][10];
memset(map,0,sizeof(map));
for (int i = 0; i < 5; i++) {
while (1) {
int x = RAND_FROM_TO(0, 10);
int y = RAND_FROM_TO(0, 10);
if (map[x][y]==0) {
map[x][y]=1;
break;
}
}
}
Is there any other way to do the same job without while(1), because I have been told the while(1) is very bad.
I just want to find a simple way to do it, so the efficiency of the generating random numbers is not under my consideration.

You can use a shuffle algorithm such as Fisher–Yates. I would pose a modified (truncated) version as so:
Express your XY coordinates as a single number.
Construct a list of all coordinates.
Pick one at random, mark it.
Remove that coordinate from the list (swap it with the one at the end of the list, and treat the list as 1 element shorter)
repeat with the list that no longer contains the marked coordinate.
This way, rather than choosing 5 numbers from 0-99, you choose one 0-99, 0-98, ... 0-95, which guarantees that you can complete the task with exactly 5 choices.
EDIT: Upon further consideration, step 1 is not strictly necessary, and you could use this on a system with sparse coordinates if you did it that way.

What about something like this:
// Create an array of valid indexes for both x and y.
NSMutableArray *xCoords = [NSMutableArray array];
NSMutableArray *yCoords = [NSMutableArray array];
for (int i = 0; i < 9; ++i) {
[xCoords addObject:#(i)];
[yCoords addObject:#(i)];
}
int map[10][10];
memset(map, 0, sizeof(map));
for (int i = 0; i < 5; ++i) {
// Pick a random x coordinate from the valid x coordinate list.
int rand = RAND_FROM_TO(0, [xCoords count]);
int x = [xCoords objectAtIndex:rand];
// Now remove that coordinate so it cannot be picked again.
[xCoords removeObjectAtIndex:rand];
// Repeat for y.
rand = RAND_FROM_TO(0, [yCoords count]);
int y = [yCoords objectAtIndex:rand];
[yCoords removeObjectAtIndex:rand];
assert(map[x][y] == 0);
map[x][y] = 1;
}
Note: I'm using NSMutableArray because you originally specified Objective-C as a tag.
Note 2: An array of valid indexes is not the most efficient representation. Using NSMutableIndexSet instead is left as an exercise to the reader. As is using basic C primitives if you don't / can't use NSMutableArray.
Note 3: This has a bug where if you pick, say, x = 3 the first time, no further choices will end up with x = 3, even though there will be valid choices where x = 3 but y is different. Fixing that is also left as an exercise, but this does satisfy your requirements, on the surface.

Related

Code is not executing the else condition in the inner most loop when matching array to array index by index?

var amazon = activeSpreadsheet.getSheetByName('Amazon');
var lastRow1 = amazon.getLastRow();
var array1 = amazon.getRange('A2:A' + lastRow1).getValues();
var source = activeSpreadsheet.getSheetByName('ProductDetails');
var lastRow2 = source.getLastRow();
var array2 = source.getRange('B2:B' + lastRow2).getValues();
n = 2;
x = 0; // match
z = 0; // non-match
for (var i = 0; i < array2.length; i++){
for (var j = 0; j < array1.length; j++){
if (array2[i] !== array1[j]){
z = z + 1;
}
else {
x = 9999
}
}
newsheet.getRange([n],[5]).setValue(z);
newsheet.getRange([n],[6]).setValue(x);
if (z > x) {
newsheet.getRange([n],[1]).setValue(array2[i]);
n == n++;
z = 0;
x = 0;
}
else if (z < x) {
z = 0;
x = 0;
}
}
My project is written in GAS (google app scripts) which is essentially, for all intents and purposes JS with variation in libraries.
Basically I am grabbing an element in the array2 and passing it through a loop to match to array1. For every time it does not match it adds 1, and when it matches (should only match once if it has any matches) it stores an arbitrary large number (larger than length of array1) and compares them.
As you can see I've written out to display these values and I always get z = 5183 (length of array1) and x = 0 (meaning no non-matches found). Therefore even if something exists in array 2 and 1 it will always write it to the cell.
What should happen is if there is a match, z= 5182 and x= 9999 (or arbitrary large number) and since 5182 < 9999 it doesn't do anything.
Is my scope wrong? Or am I not writing the If/Else correctly? Or is it something else?
Your code performs a strict comparison between the elements of two Arrays. That's fine, in general. However, for those specific Arrays those elements are also Arrays, which means strict (in)equality is checking to see if those are the exact same array object in memory. See this question for more information.
You probably wanted to do a value-based comparison, which means you need to compare the specific element of that inner array (i.e., index again). if (array2[i][0] !== array1[j][0]) {...} will check the 1st element of the inner array.
Looking at the instantiation of array1 and array2, we see that these are indeed 2D arrays from a single-column Ranges, so there will be only 1 element in each inner array. You can reduce the level of indexing necessary by flattening these arrays when you read them:
const array1 = sheet.getRange(...).getValues().map(function (row) { return row[0]; });
const array2 = ...;
I'm also not sure why you are passing in arrays to Sheet#getRange - you should pass in 1-4 arguments in manners consistent with the method signatures detailed in the Apps Script documentation.
Note that there are much better algorithms for checking if a value exists in a given array - you re-scan all of the 2nd array for every value of the first array. You should conduct thorough research into this topic before asking a new question on how to improve your algorithm.
Lastly, you should implement the best practice of using batch methods - you currently call setValue in a loop. Consider storing the results to write in an array, and then writing with Range#setValues once your loop has completed. There are many questions available for you to review on this topic.

Filling in random positions in a huge 2D array

Is a there a neat algorithm that I can use to fill in random positions in a huge 2D n x n array with m number of integers without filling in an occupied position? Where , and
Kind of like this pseudo code:
int n;
int m;
void init(int new_n, int new_m) {
n = new_n;
m = new_m;
}
void create_grid() {
int grid[n][n];
int x, y;
for(x = 1; x <= n; x ++) {
for(y = 1; y <= n; y ++) {
grid[x][y] = 0;
}
}
populate_grid(grid);
}
void populate_grid(int grid[][]) {
int i = 1;
int x, y;
while(i <= m) {
x = get_pos();
y = get_pos();
if(grid[x][y] == 0) {
grid[x][y] = i;
i ++;
}
}
}
int get_pos() {
return random() % n + 1;
}
... but more efficient for bigger n's and m's. Specially if m is bigger and more positions are being occupied, it would take longer to generate a random position that isn't occupied.
Unless the filling factor really gets large, you shouldn't worry about hitting occupied positions.
Assuming for instance that half of the cells are already filled, you have 50% of chances to first hit a filled cell; and 25% to hit two filled ones in a row; 12.5% of hitting three... On average, it takes... two attempts to find an empty place ! (More generally, if there is only a fraction 1/M of free cells, the average number of attempts raises to M.)
If you absolutely want to avoid having to test the cells, you can work by initializing an array with the indexes of the free cells. Then instead of choosing a random cell, you choose a random entry in the array, between 1 and L (the lenght of the list, initially N²).
After having chosen an entry, you set the corresponding cell, you move the last element in the list to the random position, and set L= L-1. This way, the list of free positions is kept up-to-date.
Note the this process is probably less efficient than blind attempts.
To generate pseudo-random positions without repeats, you can do something like this:
for (int y=0; y<n; ++y) {
for(int x=0; x<n; ++x) {
int u=x,v=y;
u = (u+hash(v))%n;
v = (v+hash(u))%n;
u = (u+hash(v))%n;
output(u,v);
}
}
for this to work properly, hash(x) needs to be a good pseudo-random hash function that produces positive numbers that won't overflow when you add to a number between 0 and n.
This is a version of the Feistel structure (https://en.wikipedia.org/wiki/Feistel_cipher), which is commonly used to make cryptographic ciphers like DES.
The trick is that each step like u = (u+hash(v))%n; is invertible -- you can get your original u back by doing u = (u-hash(v))%n (I mean you could if the % operator worked with negative numbers the way everyone wishes it did)
Since you can invert the operations to get the original x,y back from each u,v output, each distinct x,y MUST produce a distinct u,v.

Feasibility of non-self-intersecting path according to array constraints

I have two arrays, each containing a different ordering of the same set of integers. Each integer is a label for a point in which two closed paths intersect in the plane. The two arrays are interpreted as giving the circular ordering (in clockwise order) of points along each of two closed paths in the plane, with no particular starting point. The two paths intersect with each other as many times as there are points in the arrays, but a path may not self-intersect at all. How do I determine, from these two arrays, whether it is possible to draw the two paths in the plane without self-crossings? (The integer labels have no inherent meaning.)
Example 1: A = {3,4,2,1,10,7} and B = {1,2,4,10,7,3}: it is possible
Example 2: A = {2,3,0,10,8,11} and B = {10,2,3,8,11,0}: it is not possible.
Try it by drawing a circle, with 6 points labelled around it according to A, then attempt to connect the 6 points in a second closed path, according to the ordering in B, without crossing the new line you are drawing. (I believe it makes no difference to the possibility/impossibility of drawing the line whether you start by exiting or entering the first loop.) You will be able to do it for example 1, but not for example 2.
I am currently using a very elaborate method where I look at adjacent pairs in one array, e.g. in Example 1, array A is divided into {3,4}, {2,1}, {10,7}, then I find the groupings in the array B as partitioned by the two members listed in each case:
{3,4} --> {{1,2}, {10,7}}
{2,1} --> {{4,10,7,3}, {}}
{10,7} --> {{3,1,2,4}, {}}
and check that each pair on the left-hand-side finds itself in the same grouping of the right-hand-side partition in each of the other 2 rows. Then I do the same, offset by one position:
{4,2} --> {{10,7,3,1}, {}}
{1,10} --> {{2,4}, {7,3}}
{7,3} --> {{1,2,4,10}, {}}
Everything checks out here.
In Example 2, though, the method shows that it is impossible to draw the path. Among the "offset by 1" pairs from array A we find {10,8} causes a partition of array B into {{2,3}, {11,0}}. But we need 11 and 2 to be in the same grouping, as they are the next pair of points in array A.
This idea is unwieldy, and my implementation is even more unwieldy. I'm not even 100% convinced it always works. Could anyone suggest an algorithm for deciding? Target language is C, if that matters.
EDIT: I've added an illustration here: http://imgur.com/TS8xDIk. Here the paths to be reconciled share points 0, 1, 2 and 3. On the black path they are visited in order (A = {0,1,2,3}). On the blue path we have B = {0,2,1,3}. You can see on the left-hand side that this is impossible--the blue path will have to self-intersect in order to do it (or have additional intersections with the black path, which is also not allowed).
On the right-hand side is an illustration of the same problem interpreted as a graph with edges, responding to the suggestion that the problem boils down to a check for planarity. Well, as you can see, it's quite possible to form a planar graph from this collection of edges, but we cannot read the graph as two closed paths with n intersections--the blue path has "intersections" with the other path that don't actually cross. The paths are required to cross from inside to outside or vice-versa at each node, they cannot simply kiss and turn back.
I hope this clarifies the problem and I apologise for any lack of clarity the first time around.
By the way introducing coordinates would be a complete red herring: any point can be given any coordinates, and the problem remains the same. In a sense it is topological more than geometrical. Thanks for any additional suggestions on how to accomplish this feasibility check.
SECOND EDIT to show my current code. Like in the suggestion below by svinja, I first reduced the two arrays to a permutation of 0..2n-1. The input to the function is two arrays (which contain different orderings of the same 2n integers) and the length of these arrays. I am a hobbyist with no training in programming so I expect you will find several infelicities in the approach to coding. The idea is to return 1 if the arrays A and B are in a permutational relationship that allows the path to be drawn, and 0 if not.
int isGoodPerm(int A[], int B[], int len)
{
int i,j,a,b;
int P[max_len];
for (i=0; i<len; i++)
for (j=0; j<len; j++)
if (B[j] == A[i])
{
P[i] = j;
break;
}
for (i=0; i<len; i++)
{
if (P[i] < P[(i+1)%len])
{
a = P[i];
b = P[(i+1)%len];
}
else
{
a = P[(i+1)%len];
b = P[i];
}
for (j=i+2; j<i+len; j+=2)
if ((P[j%len] > a && P[j%len] < b) != (P[(j+1)%len] > a && P[(j+1)%len] < b))
return 0;
}
return 1;
}
I'm actually still testing another part of this project, and have only tested this part in isolation. I tweaked a couple of things when pasting it into the larger codebase and have copied that version--I hope I didn't introduce any errors.
I think the long question is hiding the true intent. I might be missing something, but it looks like the only thing you really need to check is if the points in an array can be drawn without self-intersecting. I'm assuming you can map the integers to the actual coordinates. If so, you might find the solution posed by the related math.statckexchange site here describing either the determinant-based method or the Bentley-Ottman algorithm for crossings to be helpful.
I am not sure if this is correct, but as nobody is posting an answer, here it is:
We can convert any instance of this problem to one where the first path is (0, 1, 2, ... N). In your example 2, this would be (0, 1, 2, 3, 4, 5) and (3, 0, 1, 4, 5, 2). I only mention this because I do this conversion in my code to simplify further code.
Now, imagine the first path are points on a circle. I think we can assume this without loss of generality. I also assume we can start the second path either inside or outside of the circle, if one works the other should, too. If I am wrong about either, the algorithm is certainly wrong.
So we always start by connecting the first and second point of the second path on the, let's say, outside. If we connect 2 points X and Y which are not right next to each other on the circle, we divide the remaining points into group A - the ones from X to Y clockwise, and group B - the ones from Y to X clockwise. Now we remember that points from group A can no longer be connected to points from group B on the outside part.
After this, we continue connecting the second and third point of the second path, but we are now on the inside. So we check "can we connect X and Y on the inside?" if we can't, we return false. If we can, we again find groups A and B and remember that none of them can be connected to each other, but now on the inside.
Now we're back on the outside, and we connect the third and fourth point of the second path... And so on.
Here is an image that shows how it works, for your examples 1 and 2:
And here is the code (in C#, but should be easy to translate):
static bool Check(List<int> path1, List<int> path2)
{
// Translate into a problem where the first path is (0, 1, 2, ... N}
var path = new List<int>();
foreach (var path2Element in path2)
path.Add(path1.IndexOf(path2Element));
var N = path.Count;
var blocked = new bool[N, N, 2];
var subspace = 0;
var currentElementIndex = 0;
var nextElementIndex = 1;
for (int step = 1; step <= N; step++)
{
var currentElement = path[currentElementIndex];
var nextElement = path[nextElementIndex];
// If we're blocked before finishing, return false
if (blocked[currentElement, nextElement, subspace])
return false;
// Mark appropriate pairs as blocked
for (int i = (currentElement + 1) % N; i != nextElement; i = (i + 1) % N)
for (int j = (nextElement + 1) % N; j != currentElement; j = (j + 1) % N)
blocked[i, j, subspace] = blocked[j, i, subspace] = true;
// Move to the next edge
currentElementIndex = (currentElementIndex + 1) % N;
nextElementIndex = (nextElementIndex + 1) % N;
// Outside -> Inside, or Inside -> Outside
subspace = (2 - subspace) / 2;
}
return true;
}
Old answer:
I am not sure I understood this problem correctly, but if I have, I think this can be reduced to planarity testing. I will use your example 2 for the numbers:
Create graph G1 from the first array; it has edges 2-3, 3-0, 10-8, 8-11, 11-2
Create graph G2 from the second array; 10-2, 2-3, 3-8, 8-11, 11-0, 0-10
Create graph G whose set of edges is the union of the sets of edges of G1 and G2: 2-3, 3-0, 10-8, 8-11, 11-2, 10-2, 3-8, 11-0, 0-10
Check if G is planar.
This is if I correctly interpreted the question in the sense that the second path must not cross itself but must not cross the first path either (except for the unavoidable 1 intersection per vertex due to shared vertices). If this is not the case, then Example 2 does have solutions (note how the 11-2 and 8-10 edges are crossed by the second path).

How to compare and replace (int) pointers?

So i have this piece of code:
int* get_lotto_draw() //Returns an array of six random lottery numbers 1-49
{
int min = 1;
int max = 49;
int counter = 0;
srand(time(NULL));
int *arrayPointer = malloc(6 * sizeof(int));
for(counter = 0; counter <= 5; counter++)
{
arrayPointer[counter] = rand()%(max-min)+min;
}
return arrayPointer;
}
This gives me 6 int* but sometimes these int* values can be the same. How can i compare each of them to eachother, so that if they are the same number, it will re-calculate on of the values that are equal ? Thanks for your time.
make a search in the array for same number before storing the number as,
for(counter = 0; counter <= 5; counter++)
{
int x1 = 1;
while(x1)
{
int temp = rand()%(max-min)+min;
for(i = 0; i < counter; i++)
{
if(arrayPointer[i] == temp)
{
break;
}
}
if(i == counter)
{
x1 = 0;
arrayPointer[counter] = temp;
}
}
}
The problem is that random-number generators don't know or care about history (at least, not in the sense that you do--software random number generators use recent results to generate future results). So, your choices are generally to...
Live with the possibility of duplicates. Obviously, that doesn't help you.
Review previous results and discard duplicates by repeating the draw until the value is unique. This has the potential to never end, if your random numbers get stuck in a cycle.
Enumerate the possible values, shuffle them, and pick the values off the list as needed. Obviously, that's not sensible if you have an enormous set of possible values.
In your case, I'd pick the third.
Create an array (int[]) big enough to hold one of every possible value (1-49).
Use a for loop to initialize each array value.
Use another for loop to swap each entry with a random index. If you swap a position with itself, that's fine.
Use the first few (6) elements of the array.
You can combine the second and third steps, if you want, but splitting them seems more readable and less prone to error to me.

How do I return the indices of a multidimensional array element in C?

Say I have a 2D array of random boolean ones and zeroes called 'lattice', and I have a 1D array called 'list' which lists the addresses of all the zeroes in the 2D array. This is how the arrays are defined:
define n 100
bool lattice[n][n];
bool *list[n*n];
After filling the lattice with ones and zeroes, I store the addresses of the zeroes in list:
for(j = 0; j < n; j++)
{
for(i = 0; i < n; i++)
{
if(!lattice[i][j]) // if element = 0
{
list[site_num] = &lattice[i][j]; // store address of zero
site_num++;
}
}
}
How do I extract the x,y coordinates of each zero in the array? In other words, is there a way to return the indices of an array element through referring to its address?
EDIT: I need to make the code as efficient as possible, as I'm doing lots of other complicated stuff with much larger arrays. So a fast way of accomplishing this would be great
One solution is to map (x, y) to a natural number (say z).
z = N * x + y
x = z / N (integer division)
y = z % N
In this case, you should use int list[N * N];
Another solution is to just store the coordinates when you find a zero, something like:
list_x[site_num] = x;
list_y[site_num] = y;
site_num++;
Or you can define a struct of two ints.
Well, it is possible with some pointer arithmetic.
You have the address of your first element of lattice and the addresses of all zero-fields in list. You know the size of bool. By subtracting the first-elements address from a zero-field address and dividing by the size of bool you get a linar index. This linear index can be calculated into the 2-dim index by using modulo and division.
But why don't you store the 2-dim index within your list instead of the address? Do you need the addess or just the index?
And you should think about turning the for-loops around (outer loop i, inner loop j).
struct ListCoords
{
int x, y;
} coords[n*n];
for(i = 0; i < site_num; i++)
{
int index = list[i] - &lattice[0][0];
coords[i].x = index % n;
coords[i].y = index / n;
}
I may have the % and / operators backwards for your needs, but this should give you the idea.
How do I extract the x,y coordinates of each zero in the array? In other words, is there a way to return the indices of an array element through referring to its address?
You can't. Simple as that. If you need that information you need to pass it along with the arrays in question.
bool *list[n*n]; is an illegal statement in C89 (EDIT: Unless you made n a macro (yuck!)), you may wish to note that variable length arrays are a C99 feature.

Resources