I have an nxn grid filled with photos. How can I make sure photos are not showing together in C #

I basically have a grid of, say, 100 x 100, which is filled with a url from a collection of photos. Some of them are duplicates, since I can only have 50 photographs, but I want to duplicate them to make sure that the 100 x 100 grid is full. I randomly fill the grid with a URL and then show that this is normal. The problem is that, obviously, sometimes photos with the same URL are randomly grouped either on the x-axis, or on the y-axis, or on both sides.

How can I make sure that I fill the grid so that these images with the same URL are as far apart as possible, thus preventing the appearance of two identical photos next to each other.

Any help appreciated

Mike

+8
sorting c # algorithm
source share
4 answers

If you really want to be β€œas far apart as possible,” then (1) I bet you're out of luck, and (2) if that were possible, it would probably not produce very random results. But if all you need is β€œsomewhat far apart,” that’s not so bad. Here are a few things you can do.

(1) Classify the grid positions according to the parity of their x, y coordinates: that is, whether they are odd and even. Divide the photos into four batches of approximately equal size. Now select from different parties according to the parity of the coordinates. The following code (which is too smart, sorry) does this, modulates errors and typos.

System.Random rng = new System.Random(); for (int x=0; x<nx; ++x) { for (int y=0; y<ny; ++y) { k = ((x&1)<<1) + (y&1); // 0..3 int n_photos_in_batch = (n_photos+3-k) >> 2; int photo_number = (rng.Next(0,n_photos_in_batch-1) << 2) + k; // use this photo } } 

Disadvantages: It does nothing to move copies of the photo farther apart than one step. It slightly reduces randomness, since all copies of any photo will be in a fixed subset of positions; in some contexts, it can be visible and look pretty dumb.

Variations: we mainly cover a grid of 2x2 tiles and limit the range of photos allowed for each tile. You could use larger tiles or tiles differently or arrange them differently. For example, if you say k = ((x&1)<<1) ^ (y&3) , you will get 2x2 tiles arranged in a hexagonal pattern, which is actually probably better than the version above.

(2) Move the positions in your grid (a raster order is performed, although there may be better alternatives), and for each choose a photo that (a) is not too close to the position you are looking for at and (b) randomly. The following code (again, modulo errors and typos) does something like this, although for large grids you can make it more efficient.

 System.Random rng = new System.Random(); radius = MAX_RADIUS; // preferably not too big, so that the search isn't too slow while ((2*radius+1)*(2*radius+1) >= n_photos) --radius; // gratuitously inefficient! for (int x=0; x<nx; ++x) { for (int y=0; y<ny; ++y) { // which photos already appear too near to here? System.Collections.BitArray unseen = new System.Collections.BitArray(n_photos,True); for (x1=x-radius; x1<=x+radius; ++x1) { for (int y1=y-radius; y1<=y+radius; ++y1) { if (0 <= x1 && x1 < nx && 0 <= y1 && y1 < nx && (y1<y || (y1==y && x1<x))) { unseen[photos[x1,y1]] = False; } } } // now choose a random one of them int n_unseen = 0; for (int i=0; i<n_photos; ++i) if (unseen[i]) ++n_unseen; System.Debug.Assert(n_unseen>0, "no photos available"); int j = rng.Next(0,n_unseen-1); for (int i=0; i<n_photos; ++i) { if (unseen[i]) { if (j==0) { photos[x,y] = i; break; } --j; } } } } 

Notes: This is much more expensive than option 1. Of course, validation on x1, y1 is useless ineffective here. That is, the choice of radius. The obvious more effective versions of these, however, may break if you accept some of the options that I am going to list. This code, in its current form, will not do anything to save photos from each other if there are less than 9. The choice of radius is actually completely fictitious, for the grid tracing method I use, because no more than 2r ^ 2 + 2r " Excluded "line items again, this may change if you cross the grid in a different order. Etc.

Variations: There is no real reason why the region you are viewing should be square. For example, a circuit might be better. You could, with some extra work, create an area in which there are always as many points as you have photos (although if you do, you will get a mostly periodic picture of the photos, so it’s better to be a little less aggressive). It might be better to process the grid entries in a different position β€” for example, twisting out of the center.

(3) Option 2 above will keep the photos unique in a certain range (roughly as it may indicate how many different photos you have), but do not care about saving copies further. Instead, you could decide how badly he has two identical photos at any given distance, and then selects the photos to minimize the overall bad state. It will be even more expensive than option 2. I will not write sample code; you can probably decide how to do it.

[EDITED added ...]

(4) Here is a nice variation on the theme of (1). It will work best when the grid is square and its size is 2, but you can adapt it to work more generally. It takes time proportional to the size of your grid, however you have a lot of photos. For each position (x, y): drop everything except the bottom k bits of the coordinates for some k. Bit-reverse them and alternate the bits, giving the number m from 0 to 2 ^ (2k) -1. Choose k so that it is somewhere of the order of, say, n_photos / 4. Now, at position (x, y), you put the photo number in a round (n_photos * m / 2 ^ (2k) + smallish_random_number). There are a few details that I will leave for you to fill out :-).

+4
source share

What you want is a space filling curve, such as a hilbert curve. It fills your grid with a continuous line dividing each square by just 1 bit. Since the nature of sfc is to recursivley fill the space and preserve the surroundings, you can use this and place the image along the line. If you do not want to place the same picture in direct proximity, you can use sfc depth on each node to exclude copies.

0
source share

The fastest way looks something like this:

  • You have an array of n imgs URLs and a grid x * y
  • Find the central grid cell.
  • Randomly fetch the imgs url from the array and put each url in the center cell (the first url is placed in the center)
  • Do this until you fill in all the grid cells or until you have the URLs in the array.
  • If each URL is used, you must use the concentric circle URLs that you created. Go from the center cell to the circle with the largest radius.
  • URLs made using this method, you should accidentally place around a large circle.

This algorithm will work if you have enough URLs to draw less than 2 disks in the grid.

You can successfully change it if you follow the rule that URLs from one set should be filled in as large a circle as possible.

0
source share

Warning, brainstorming:

I will have a collection of available URLs and randomly pull from it. As soon as I use the URL, I will either remove it from the collection or add that it is being used. I would stop as soon as I ran out of collection or hit 100.

If I ran out of collection before reaching 100, I would mention the last URLs of X and run the loop again, making sure that the next URL selected was not one of the last used by X.

Sorry for the lack of code, hope this is helpful.

-one
source share

All Articles