Generate "In-Range" Random Numbers in C - c

I need to generated random numbers in the range [0, 10] such that:
All numbers occur once.
No repeated results are achieved.
Can someone please guide me on which algorithm to use?

The algorithm in Richard J. Ross's answer is incorrect. It generates n^n possible orderings instead of n!. This post on Jeff Atwood's blog illustrates the problem: http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html
Instead, you should use the Knuth-Fisher-Yates Shuffle:
int values[11] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
srand(time(NULL));
for (int i = 10; i > 0; i--)
{
int n = rand() % (i + 1);
int temp = values[n];
values[n] = values[i];
values[i] = temp;
}

Try out this algorithm for pseudo-random numbers:
int values[11] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
srand(time(NULL));
for (int i = 0; i < 11; i++)
{
int swap1idx = rand() % 11;
int swap2idx = rand() % 11;
int tmp = values[swap1idx];
values[swap1idx] = values[swap2idx];
values[swap2idx] = tmp;
}
// now you can iterate through the shuffled values array.
Note that this is subject to a modulo bias, but it should work for what you need.

Try to create a randomize function, like this:
void randomize(int v[], int size, int r_max) {
int i,j,flag;
v[0] = 0 + rand() % r_max; // start + rand() % end
/* the following cycle manages, discarding it,
the case in which a number who has previously been extracted, is re-extracted. */
for(i = 1; i < size; i++) {
do {
v[i]= 0 + rand() % r_max;
for(j=0; j<i; j++) {
if(v[j] == v[i]) {
flag=1;
break;
}
flag=0;
}
} while(flag == 1);
}
}
Then, simply call it passing an array v[] of 11 elements, its size, and the upper range:
randomize(v, 11, 11);
The array, due to the fact that it is passed as argument by reference, will be randomized, with no repeats and with numbers occur once.
Remember to call srand(time(0)); before calling the randomize, and to initialize int v[11]={0,1,2,3,4,5,6,7,8,9,10};

Related

How to check if two arrays have the same set of digits in C?

I want to check if two integer type arrays have the same set of digits. For example, if array 1 is 5 1 2 3 3 4 6 1, and array 2 is 1 2 3 4 5 6, the program returns 1. If any number from either array isn't in the second one, the program returns a 0.
I tried doing something like this, but I can't get it to work:
#include <stdio.h>
int main()
{
int i, j, a[8]={5, 1, 2, 3, 3, 4, 6, 1}, b[6]={1, 2, 3, 4, 5, 6}, x=0;
for(i=0; i<6; i++)
{
for(j=0; j<8; j++)
{
if(a[j]==b[i])
{
x=1;
continue;
}
else
{
x=0;
break;
}
}
}
return x;
}
EDIT:
Thank you Some programmer dude
#include <stdio.h>
void sort(int arr[], int n)
{
int i, j, a;
for (i=0; i<n; i++)
{
for (j=i+1; j<n; j++)
{
if (arr[i]>arr[j])
{
a=arr[i];
arr[i]=arr[j];
arr[j]=a;
}
}
}
}
int main()
{
int i, j, k;
int a[8]={5, 1, 2, 3, 3, 4, 6, 1};
int b[6]={1, 2, 3, 4, 5, 6};
int na=8, nb=6;
for(i=0; i<na; i++) // removing duplicates from a
{
for(j=i+1; j<na; j++)
{
if(a[i]==a[j])
{
for(k=j; k<na; k++)
{
a[k]=a[k+1];
}
na--;
j--;
}
}
}
for(i=0; i<nb; i++) // removing duplicates from b
{
for(j=i+1; j<nb; j++)
{
if(b[i]==b[j])
{
for(k=j; k<nb; k++)
{
b[k]=b[k+1];
}
nb--;
j--;
}
}
}
sort(a, na);
sort(b, nb);
if(na!=nb)
return 0;
for(i=0; i<na; i++)
{
if(a[i]!=b[i])
return 0;
}
return 1;
}
You have several ways you can approach this, you can use two sets of nested loops swapping the order you loop over the two arrays validating each element is found in the other. Two full sets of nested loops are needed as you have a 50/50 chance any single outlier will be contained in either of the arrays. This is the brute-force method and has the potential worst-case number of iterations.
Since an outlier is what drove the need for looping with one arrays as outer and the other inner and then swapping a repeating, e.g. to catch 5, 1, 2, 3, 3, 4, 6, 1 and 1, 2, 3, 4, 5, 6, 7, if you can catch the outlier with another method that requires fewer iterations you can make your algorithm more efficient.
An outlier would be detected in a comparison of the min and max from each array, and to find min and max only requires a single linear traversal of each array. Much better than the worst-case nested loop over all elements.
The min and max check provide a way to shorten your work, but do not eliminate the need to press forward with a second set of nested loops if the result is inconclusive at that point. Why? Consider the following sets, where the min and max are equal, but one element within the range is not included in both arrays, e.g.:
int a[] = { 5, 1, 2, 3, 3, 4, 6, 112 },
b[] = { 1, 2, 3, 4, 5, 6, 7, 112 };
The only way the 7 will be detected is by nested loop with the array containing 7 being the outer loop.
So you could write a short function to test for the common set as:
#include <stdio.h>
#include <limits.h>
int commonset (int *a, int *b, int sza, int szb)
{
int maxa = INT_MIN, maxb = INT_MIN,
mina = INT_MAX, minb = INT_MAX;
for (int i = 0; i < sza; i++) { /* find max/min of elements of a */
if (a[i] > maxa)
maxa = a[i];
if (a[i] < mina)
mina = a[i];
}
for (int i = 0; i < szb; i++) { /* find max/min of elements of b */
if (b[i] > maxb)
maxb = b[i];
if (b[i] < minb)
minb = b[i];
}
if (maxa != maxb || mina != minb) /* validate max & mins equal or return 0 */
return 0;
for (int i = 0; i < sza; i++) { /* compare of each element between arrays */
int found = 0;
for (int j = 0; j < szb; j++)
if (a[i] == b[j]) {
found = 1;
break;
}
if (!found)
return 0;
}
for (int i = 0; i < szb; i++) { /* compare of each element between arrays */
int found = 0;
for (int j = 0; j < sza; j++)
if (a[j] == b[i]) {
found = 1;
break;
}
if (!found)
return 0;
}
return 1;
}
Adding a short example program:
int main (void) {
int a[] = { 5, 1, 2, 3, 3, 4, 6, 1 },
sza = sizeof a / sizeof *a,
b[] = { 1, 2, 3, 4, 5, 6 },
szb = sizeof b / sizeof *b,
result;
result = commonset (a, b, sza, szb);
if (result)
puts ("arrays have common set of numbers");
else
puts ("arrays have no common set of numbers");
return result;
}
Example Use/Output
$ ./bin/arr_commonset
arrays have common set of numbers
$ echo $?
1
With b[] = { 1, 2, 3, 4, 5, 6, 7 }:
$ ./bin/arr_commonset
arrays have no common set of numbers
$ echo $?
0
With a[] = { 5, 1, 2, 3, 3, 4, 6, 112 } and b[] = { 1, 2, 3, 4, 5, 6, 7, 112 }:
$ ./bin/arr_commonset
arrays have no common set of numbers
$ echo $?
0
There are probably even ways to combine the two and shave off a few iterations, and, if you have a guaranteed range for your input sets, you can use a simple frequency array for each and then two simple linear iterations would be needed to increment the element that corresponds to the index for each value in the array, and then a third linear iteration over both frequency arrays comparing that like indexes either both are non-zero or both are zero to confirm the common set -- that is left to you.
Look things over and let me know if you have any further questions.

Split array into two arrays by index even or odd in c

How to separate the even position number of an array from the odd position number in C.
Example
int arr[]= {2,3,4,5,6,7,8,9,1};
int odd[]= {2,4,6,8,1};
int even[] = {3,5,7,9};
Use % to get the remainder. If the remainder is nonzero, then the index is odd, otherwise even. But index starts from 0 and not 1, thus the first element's index is 0 and is even. if you want to sort according to that (seems to be you do), add 1 to index.
#include <stdio.h>
int main() {
int arr[] = {2, 3, 4, 5, 6, 7, 8, 9, 1}; // our array
const size_t max_size = sizeof(arr) / sizeof(arr[0]);
int odd[max_size];
size_t odd_cnt = 0;
int even[max_size];
size_t even_cnt = 0;
for (size_t i = 0; i != max_size; ++i) {
if ((i + 1) % 2) { // if (i + 1) % 2 is nonzero, i + 1 is odd
odd[odd_cnt++] = arr[i];
} else {
even[even_cnt++] = arr[i];
}
}
for (size_t i = 0; i != odd_cnt; ++i) {
printf("%d ", odd[i]);
}
printf("\n");
for (size_t i = 0; i != even_cnt; ++i) {
printf("%d ", even[i]);
}
printf("\n");
return 0;
}

How many times a digit show up

Please help me. I don't get why the out put is in "occurs" is "30", instead of '3'.. It's as if I'm multiplying the answer with '10', but I'm not.. Maybe the answer to my problem is right in to my code but Can someone explain why and how? please.. Thank you very much in advance..
Please take a look at my code.
#include <stdio.h>
int main(){
int arr[10] = {7, 7, 3, 2, 9, 8, 5, 1, 7, 9};
int occur[10] = {NULL};
int max = 0;
int most;
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
occur[arr[j]]++;
if(occur[arr[j]] > max)
{
max = occur[arr[j]];
most = arr[j];
}
}
}
printf("Most frequent: %d\ occurs: %d\n", most, max);
return 0;
}
I am getting the correct answer in "Most Frequent". But the "occurs" is 30, instead of just 3 because 7 occurs 3 times.
It becomes 30 because there is an outer loop which executes 10 times.
I'm guessing that you want to get the most frequent number in the array and how many times it occurred that's why you have an outer loop. This will not work if you have a number in your array that is greater than 9 which will result in index out of bounds problem in occur array. You should change your implementation to this:
#include <stdio.h>
int main(){
int arr[10] = {7, 7, 3, 2, 9, 8, 5, 1, 7, 9};
int max = 0;
int most;
for(int i = 0; i < 10; i++)
{
int tmp = arr[i], count = 0;
// if the current number is the current max number then skip
if(tmp == max)
continue;
for(int j = 0; j < 10; j++)
{
// increment count if number in index j is equal to tmp number
count += arr[j] == tmp ? 1 : 0;
}
// [this condition will depend on the requirement.]
// replace max and most if the count of tmp number is greater than your
// current max
if(count > max){
max = count;
most = tmp;
}
}
printf("Most frequent: %d\ occurs: %d\n", most, max);
return 0;
}
This is not tested so if there are any problems, please feel free to edit.
You ARE multiplying max by 10 since you are doing everything 100 times (instead of 10) because of your totally redundant for i loop.
Specifically your problem is you are incrementing the values in occurs 10 times (instead of once). Since most doesn't use the incremented values it doesn't have problem.
The faster, O(2n-1) complexity solution
#include <stdio.h>
int main(){
int arr[10] = {7, 7, 3, 2, 9, 8, 5, 1, 7, 9};
int occur[10] = {NULL};
int max = 0;
for(int i = 0; i < 10; ++i)
++occur[arr[i]];
for (int i = 1; i < 10; ++i)
if (occur[i] > occur[max])
max = i;
printf("Most frequent: %d\ occurs: %d\n", max, occur[max]);
return 0;
}
Yet faster, in O(n)... I had a feeling that..
int main(){
int arr[10] = {7, 7, 3, 2, 9, 8, 5, 1, 7, 9};
int occur[10] = {NULL};
int max = 0;
for(int i = 0; i < 10; ++i)
if (++occur[arr[i]] > occur[max])
max = arr[i];
printf("Most frequent: %d\ occurs: %d\n", max, occur[max]);
return 0;
}
I will not argue that your O(n^2) operations algorithm is not the ideal way to do the task.
But moving one line of code will fix your code.
Your loop:
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
occur[arr[j]]++;
Fix:
for(int i = 0; i < 10; i++)
{
occur[arr[i]]++;
for(int j = 0; j < 10; j++)
{
I'll let you figure out how you can do this in O(2n) operations or less...

Iterate an array from the middle then the beginning

I want to iterate through any array starting at an index that's close to the middle, go to the end then go to the beginning.As an example:
#include <stdio.h>
int main(){
int a[]= {1, 2, 3, 4, 5, 6, 7,};
int i = 0;
for (i = 2; i < 6; i++){
if (i == 6){
i = 0;
}
printf("%d\n", a[i]);
}
return 0;
}
How can I "reassign" the index to be zero when it reaches the end (index 6)
Here is a simple write-up. Not tested so adjust as needed. The idea is have the counter start at 0 and add the value of start each time using modulus to make it relative.
int a[]= {1, 2, 3, 4, 5, 6, 7};
int length = sizeof(a)/sizeof(a[0]);
int start = length/2;
for (int i = 0; i < length; i++)
{
printf("%d\n", a[(i+start)%length]);
}
And props to #SouravGhosh for pointing out modulus in the comments before I got this answer up.
If I well understood the question you want two for loops, one starting from the middle of your array and going to the end of the array and the second starting from the middle (minus one) and decreasing to the beginning of the array.
This is the code you can use, it is quite easy and works fine for me:
#include <stdio.h>
int main() {
int a[] = { 1, 2, 3, 4, 5, 6, 7, };
int max = (int)(sizeof(a)/sizeof(a[0]));
int middle = (int)(max / 2);
int i;
for (i = middle; i < max ; i++) {
printf("%d\n", a[i]);
}
for (i = middle - 1; i >= 0; i--) {
printf("%d\n", a[i]);
}
}

Finding mode of a sorted array

I was hoping to get some input on how to correctly find the mode of a sorted array in C. Here's what I'm working with. First, my freqDistrib function:
void freqDistrib(int t[], int num) {
int i, j, x;
static int f[SIZE];
printf("\n\n");
printf("Part C:\n");
printf(" %-5s %-16s\n", "score", "frequency");
printf(" %-5s %-16s\n", "-----", "---------");
for (i = 1; i < num; i++) {
x = t[i];
j = i - 1;
while (j >= 0 && x > t[j]) {
t[j + 1] = t[j];
j = j - 1;
}
t[j + 1] = x;
} // sorts input in descending order
for (i = 0; i < num; i++) {
++f[t[i]];
if (t[i] != t[i + 1])
printf(" %3d %7d\n", t[i], f[t[i]]);
} // finds the frequency of each input and prints
}
and my mode function:
void modeScore(int t[], int num) {
int i, j, max, mode;
int f[SIZE];
for (i = 0; i < num; i++) {
f[t[i]]++;
}
mode = 0;
max = 0;
for (j = 0; j < num; j++) {
if (f[j] > max) {
max = f[j];
mode = j;
}
}
printf("\n\n");
printf("Part F:\n");
printf("%3d is mode\n", mode);
}
Output right now:
0 is mode
I realize that I need to compare the current frequency tally to a max, and if it is higher than set it equal to max. I just can't for the life of my figure out why this isn't working. Any input would be appreciated thanks.
As noted in a comment, the principal problem was that you did not initialize f in the function.
Here's working code which shows that was all the change that was necessary:
#include <stdio.h>
enum { SIZE = 100 };
static void modeScore(int t[], int num)
{
int f[SIZE] = { 0 };
for (int i = 0; i < num; i++)
f[t[i]]++;
int mode = 0;
int max = 0;
for (int j = 0; j < num; j++)
{
if (f[j] > max)
{
max = f[j];
mode = j;
}
}
printf("Part F: %3d is mode (count %d)\n", mode, max);
}
int main(void)
{
int data[] =
{
/* random -n 40 0 9 | commalist -b ' ' -l 38 */
7, 8, 3, 8, 5, 9, 5, 8, 9, 6,
8, 0, 1, 8, 2, 0, 3, 4, 3, 3,
3, 0, 2, 7, 5, 4, 6, 5, 9, 0,
1, 9, 1, 7, 8, 0, 5, 4, 0, 8,
};
enum { DATA_SIZE = sizeof(data) / sizeof(data[0]) };
modeScore(data, DATA_SIZE);
return 0;
}
For the given data, the output is:
Part F: 8 is mode (count 7)
(Funny coincidence: the first time I ran it — with slightly different data — the answer came back as Part F: 0 is mode (count 7). This was actually correct; I changed one of the zeros into an eight to produce the current result.)
Note that I would normally design the function to return the modal value, rather than have it do the printing. As it stands, it can't be reused because the printing is not material to most code that wants to determine the mode.
The code also does not check that the values in t fall in the range 0..SIZE-1 (but it should).
The parameter order you use is traditional, but there is at least nominally some advantage to using:
void modeScore(int num, int t[num])
to express explicitly that the array t has num elements in it. The size must precede its use in the array dimentson, though.
Since you say the array is sorted, you don't need to create a temporary array to count the values. Instead, you just need to traverse the input, keeping count of how many identical values you've seen in the current run. At the end of the run, then compare the length of the run to the previous longest run, and update if the new run is longer.
(Actually, we update whenever the current run is longer, so we don't forget to update if the mode is the very last value).
Notice that we no longer need SIZE to bound our values; we can now work with the full range of int if we wish.
#include <stdio.h>
static void modeScore(const int t[], int num)
{
int start = 0;
int mode = t[0];
int score = 0;
for (int i = 1; i < num; ++i) {
if (i - start > score) {
// a longer run than the previous candidate
score = i - start;
mode = t[start];
}
if (t[start] != t[i])
// we've reached a change in value
start = i;
}
printf("Part F: %3d is mode (count %d)\n", mode, score);
}
You didn't provide a main(), so I adapted Jonathan Leffler's:
int main(void)
{
int data[] =
{
/* random -n 40 0 9 | commalist -b ' ' -l 38 */
0, 0, 0, 0, 0, 0, 1, 1, 1, 2,
2, 3, 3, 3, 3, 3, 4, 4, 4, 5,
5, 5, 5, 5, 6, 6, 7, 7, 7, 8,
8, 8, 8, 8, 8, 8, 9, 9, 9, 9,
};
modeScore(data, sizeof data / sizeof data[0]);
return 0;
}

Resources