2

I have an array with 100 elements. Array elements are a set of ones and zeros. For example:

Array[100] = {0,0,1,0,1,0,1,1,1,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,1,....,1}

I need to find all zero windows(gaps) and choose one of them randomly. The size of the gap (needed) is chosen according to a uniform distribution between 1 and 20.

 needed = op_dist_load ("uniform_int", 1, 20);

for example If we assume that the rest of the element are equal to 1 in the Array[100], as you can see, I have 8 zero windows (the size of the window =2). I need to find them.

The find_gap_randomly function selects 2 contiguous zero elements (A subarray with 2 zero elements means that there is a gap in my program). Do you have any suggestions for writing the code of find_gap_randomly(int needed) function in C language without using random library, preferably for OPNET simulator?

static void find_gap_randomly(int needed)
{
    //The macros “FIN” and “FOUT” are used in OPNET functions to enable the OPNET 
    //debugging kernel to print out function information. 
    FIN(find_rr_gap());
    /* ... */
    FOUT;
}
Saman2018
  • 33
  • 5
  • Pick a random index between `0` and `99 - needed` (inclusive), see if there are `needed` number of zeros from that index onward. If not then pick another random index, until you find a match. – Some programmer dude Jun 22 '18 at 06:00
  • Thanks... But the value is needed is fixed (i.e. 2) , the problem is that there may be many zero pairs in the array, How can I find zero pairs and pick one of them randomly. – Saman2018 Jun 22 '18 at 06:09
  • I think that is exactly what Some has already answered. – Yunnosch Jun 22 '18 at 06:09
  • What are `FIN()` and `FOUT`. Which role do they play for demonstrating your problem? Please study the concept of a [mcve]. – Yunnosch Jun 22 '18 at 06:11
  • The macros “FIN” and “FOUT” are used in OPNET functions to enable the OPNET debugging kernel to print out function information. – Saman2018 Jun 22 '18 at 06:13
  • Please show what you already have. Surely you have at least something of a HelloWorld, extended to contain the array and call the empty implementation of the prototype you have shown. You probably also have some mechanism in place to actually output your result. This, too, leads to making a MCVE. – Yunnosch Jun 22 '18 at 06:13
  • The relevance of OPNET mechansims for your question is unclear to me. – Yunnosch Jun 22 '18 at 06:14
  • Unsure whether it is a true duplicate, but you will find interesting materials for random algorithms and their C implementation [here](https://stackoverflow.com/a/1026370/3545273). Beware, C standard implementation is known not to be a very good one, but may be enough for your current requirements. – Serge Ballesta Jun 22 '18 at 06:24
  • I was thinking he is looking for a sliding-window of `int needed` width to work down the array to find an all zero window (or gap) in his array/(program). It's quite unclear, but there are a number of sliding-window duplicates already. As Yunnosch suggested, please provide [**A Minimal, Complete, and Verifiable Example (MCVE)**](http://stackoverflow.com/help/mcve). – David C. Rankin Jun 22 '18 at 06:28
  • @David C. Rankin : Yes, That's right. I need to find all zero windows(gaps) and choose one of them randomly. I try to edit my question,thanks. – Saman2018 Jun 22 '18 at 08:02
  • The array is really 100 elements? If so you can make a list of the gaps, or do what @Someprogrammerdude said, I don't know why cannot do that. Is because it won't uniformly distributed? – myradio Jun 22 '18 at 08:21
  • @ myradio , No the array is really 1000 elements But here I wanted to give an example . I am beginner and I have no idea for writing a usable code . . – Saman2018 Jun 22 '18 at 08:35

1 Answers1

2

If you are still working on finding the gaps in Array, (a gap defined as the number of sequential zero elements of at least needed length), then a simple, straight-forward way of finding all gaps is to move a "sliding-window" of needed length down the array checking whether all values within the window are zero. If they are all zero, you have found a gap, if not, move to the next index in Array and repeat.

The concept if fairly simple, but a picture may help (or attempted picture)

    +-------+
    |       |  <= window to slide over array
    |       |
    +---+---+---+---+---+---+---+---+...
    | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 |   <= array values
    +---+---+---+---+---+---+---+---+...
    0   1   2   3   4   5   6   7   8   <= array indexes
    |       |
    +-------+

Shown above you have the first nine elements of your Array shown, and the corresponding index for each element underneath. Since your needed is 2 you have a window that spans 2-elements that you will move from the beginning to end of Array checking the values within. This can be done simply with two nested loops, the outer loop looping while i = needed; i < num_elements; i++ and then the inner loop iterating from j = i - needed; j < i; j++.

To capture where the gaps within Array are, you use a second array (I called gaps) containing the same number of elements as Array initialized All zero. When you find a region within Array where there a needed number of sequential elements, you simply increment gaps[j]++; to set the value at gaps[j] from 0 to 1. (depending on the scope of j, you may need to increment gaps[i-needed]++; if j has gone out of scope.

When you are done moving your sliding window from beginning to end, gaps will have a value of 1 at each index where the beginning of a gap was located in Array.

A simple function implementing the sliding window could be written like:

/** find_gaps locates each sequence of all zero within 'array' of
 *  at least 'needed' length, the corresponding index within 'gaps'
 *  is incremented to identify the start of each gap, returns the
 *  number of gaps of 'needed' length in 'array'.
 */
int find_gaps (int *gaps, int *arr, int nelem, int needed)
{
    int ngaps = 0;  /* count of gaps found */
    /* add code to validate parameters here */

    memset (gaps, 0, nelem * sizeof *gaps);     /* zero gaps array */
    for (int i = needed; i < nelem; i++) {      /* loop needed to end */
        for (int j = i - needed; j < i; j++) {  /* loop previous needed */
            if (arr[j] != 0)    /* if non-zero value, get next in array */
                goto next;      /* lowly 'goto' works fine here */
        }
        gaps[i-needed]++;   /* increment index in gaps */
        ngaps++;            /* increment no. of gaps found */
      next:;
    }

    return ngaps;   /* return no. of gaps found */
}

(note: the inner loop can be replaced with memcmp to check against a value will all bytes set to zero to locate the gaps)

Go through the operation of find_gaps above, using the diagram as your guide and make sure you understand exactly what is going on. If not, let me know.

Putting it altogether in a short example that takes needed as the 1st argument to the program (or uses 2 by default if no argument is given), you could do something like the following:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

/** find_gaps locates each sequence of all zero within 'array' of
 *  at least 'needed' length, the corresponding index within 'gaps'
 *  is incremented to identify the start of each gap, returns the
 *  number of gaps of 'needed' length in 'array'.
 */
int find_gaps (int *gaps, int *arr, int nelem, int needed)
{
    int ngaps = 0;  /* count of gaps found */
    /* add code to validate parameters here */

    memset (gaps, 0, nelem * sizeof *gaps);     /* zero gaps array */
    for (int i = needed; i < nelem; i++) {      /* loop needed to end */
        for (int j = i - needed; j < i; j++) {  /* loop previous needed */
            if (arr[j] != 0)    /* if non-zero value, get next in array */
                goto next;      /* lowly 'goto' works fine here */
        }
        gaps[i-needed]++;   /* increment index in gaps */
        ngaps++;            /* increment no. of gaps found */
      next:;
    }

    return ngaps;   /* return no. of gaps found */
}

int main (int argc, char **argv) {

    int array[] = { 0,0,1,0,1,0,1,1,1,0,0,0,0,0,1,1,0,1,0,0,
                    0,1,1,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,1 },
        nelem = sizeof array / sizeof *array,   /* number of elements */
        gaps[nelem],    /* a VLA is fine here C99+, otherwise allocate */
        ngaps = 0,      /* no. of gaps found */
        needed = argc > 1 ? strtol (argv[1], NULL, 0) : 2;  /* (default: 2) */

    if (errno) {    /* validate strtol conversion succeeded */
        perror ("strtol-argv[1]");
        return 1;
    }
    /* find the number of gaps, storing beginning index in 'gaps' array */
    ngaps = find_gaps (gaps, array, nelem, needed);

    printf ("gaps found: %d\n", ngaps);         /* output number of gaps */
    for (int i = 0; ngaps && i < nelem; i++)    /* output index of gaps */
        if (gaps[i])
            printf (" gap at array[%2d]\n", i);

    return 0;
}

(note: you should add checks that needed is less than nelem, but that and any additional validations are left as an exercise for you)

Example Use/Output

$ ./bin/findgaps
gaps found: 11
 gap at array[ 0]
 gap at array[ 9]
 gap at array[10]
 gap at array[11]
 gap at array[12]
 gap at array[18]
 gap at array[19]
 gap at array[25]
 gap at array[26]
 gap at array[32]
 gap at array[37]

Checking for gaps of at least 3 zeros:

$ ./bin/findgaps 3
gaps found: 5
 gap at array[ 9]
 gap at array[10]
 gap at array[11]
 gap at array[18]
 gap at array[25]

There are several ways to approach this problem, but a sliding-window is probably one of the most straight-forward, and the sliding-window has many, many other applications in C, so it is well worth adding to your toolbox. Let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85