how to print 5 unique strings from array of 10 strings - c

I am writing a code which will print 5 unique and random strings from an array of 10 strings. But my code doesn't print it uniquely, there are always some repetitions.
Here is my code, can anyone suggest how to make it print unique?
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void main(void){
char arr[10][10]={"abc","def","ghi","klm","nop","qrs","tuv","wxy","zab","cde"};
int i=0,j=0;
srand(time(0));
for(i=0;i<5;i++){
j=rand()%10;
printf("%d\n",j);
}
}

Just remember idices that have already been printed out:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
char arr[10][10] = {"abc","def","ghi","klm","nop","qrs","tuv","wxy","zab","cde"};
int i = 0, j = 0;
int done[10] = { 0 };
srand(time(0));
for (i = 0; i < 5; ++i)
{
do
{
j = rand()%10;
}
while (done[j] == 1);
done[j] = 1;
printf("%s\n", arr[j]);
}
return 0;
}

Your rand() function may evaluate to the same string index multiple times. There are different ways to resolve that. Most of them will be a take off on bit vector approach. You can create a Boolean array and initialize it to false. Whenever a number is printed, you can change the element in the Boolean array for that index to true. If an element is selected, you can check in the Boolean array if it has already been printed. If yes, you can regenerate the random number, or move to the next unprinted element, making sure that the corresponding Boolean entry is changed to true when you print that element.

Your random function gives the repetition, e.g. your dice throw '3' two time out of 4 throws.
What you could do to make it simple, create an array [0..9],
and let the random function swap a[i] with a[j].
Then you get a random permutation. Take the first 5 elements of the permutated array.

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <time.h>
int main(){
char arr[10][10]={"abc","def","ghi","klm","nop","qrs","tuv","wxy","zab","cde"};
int found[10] = { 0 };
int i = 0,j = 0;
srand(time(NULL));
for(i = 0; i < 5; i++){
j = rand() % 10;
while(1){
if(!found[j]) break;
j = rand() % 10;
}
found[j] = 1;
printf("%s\n", arr[j]);
}
return 0;
}

Related

Double arrays in C

Im in the process of learning C and the basis of the class is C primer plus(6th edition). We use Eclipse as an IDE.
For an project we have to create to arrays. One array that takes numbers in a loop and another array that display the cumulative value. So if array 1 has values 1, 5 and 3(out of 10 inputs total) then the resulting input in array 2 should be 9(on the 3th input because of the 3 inputs in array 1).
Im having trouble getting started the right way - anyone here has ideas how I could proceed?
So far I have this for starters but forgive me for it it very weak:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
void doublearrays (double usernumber);
int main(void)
{
double usernumbers = 0.0;
int loop1 = 1;
while(loop1)
{
printf("Type numbers as doubles. \n");
fflush(stdout);
loop1 = scanf("%lf", &usernumber);
if(loop1)
{
doublearrays(usernumber);
}
}
return 0;
}
All the text in a homework assignment shall be read:
For a project we have to create two arrays... 10 inputs total...
Why on earth do not you declare them?... You already have defined SIZE so
double usernumbers[SIZE];
double cumulnumbers[SIZE];
Next do yourself a favour and handle one problem at a time:
One array that takes numbers in a loop...
Ok, so write a loop up to 10 reading floats directly into the array and note how many numbers were received
int n;
for(n=0; n<SIZE; n++) {
if (scanf("%lf", &usernumbers[n]) != 1) break;
}
// ok we now have n number in the first array
Let us go on
and another array that display the cumulative value.
Ok cumul is initially 0. and is incremented on each value from the first array:
double cumul = 0.;
for(int i=0; i<n; i++) {
cumul += usernumbers[i];
cumulnumbers[i] = cumul;
}
(your current code isn't what you need... delete it and then...)
anyone here has ideas how I could proceed?
Well the first step would be to actually define some arrays.
double input[SIZE];
double cum[SIZE];
The next step would be a loop to read input.
for (int i = 0; i < SIZE; ++i)
{
if (scanf("%lf", &input[i]) != 1)
{
// Input error - add error handling - or just exit
exit(1);
}
}
The next step is to add code for calculating the the cumulative value.
I'll leave that for you as an exercise.
The last step is to print the array which I also will leave to you as an exercise.
The straight forward way of doing this, which would also use two arrays and a loop construct would be to create something like this.. I've changed the doubles to integers. (and i am also ignoring any errors from scanf()).
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
static void
print_array(int *arr, const char *arr_name)
{
int i;
printf("%s = [");
for (i = 0; i < SIZE; i++)
printf("%d%s", arr[i], i < SIZE -1 ? ",":"");
printf("]\n");
}
int main(int argc, char **argv)
{
int i;
int input[SIZE];
int cumsum[SIZE];
for (i = 0; i < SIZE; i++)
{
int _input;
printf("Give me numbers!\n");
fflush(stdout);
scanf("%d", &_input); /* assuming integer */
input[i] = _input;
cumsum[i] = i > 0 ? cumsum[i-1] + _input : _input;
}
print_array(input, "input");
print_array(cumsum, "cumulative");
return 0;
}
or If you'd like to play around with pointers and have a bit more compact version.. perhaps this could be something to study to help you understand pointers, it does the same thing as my code above
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
static int data[SIZE*2];
int main(int argc, char *argv[])
{
int *input_p = &data[0];
int *cumsum_p = &data[0] + SIZE;
for (; input_p != &data[0] + SIZE; input_p++, cumsum_p++)
{
printf("Give me numbers!\n");
scanf("%d", input_p);
*cumsum_p = input_p == &data[0] ? *input_p : *(cumsum_p-1) + *input_p;
}
}

How could I avoid the pc to pick the same number?

If I have an array like this
int numbers[10] = {1,1,3,3,5,5,7,7,8,8};
And I want to pick one randomly
i = numbers[rand()% 10];
How could I avoid the pc to pick the same number more than twice for this example. Because like you can see in the array the same number is repeated 2 times. So I would like, for example, the number 8 to be choose just twice and same for the other numbers.
I know that I could do something like mark an element as "deleted", e.g., by setting it to 0, then if the number chosen has been deleted, you choose again. But I don't know how to do it properly, so If anyone here can help me I would be very grateful.
You can generate the random number so it's equal to the yet unused number of elements and move unused elements to the front of the array.
#define SZ 10
int numbers[SZ] = {1,1,3,3,5,5,7,7,8,8};
for (int i = 0; i < SZ; ++i)
{
// Generate the random number in the range [0 .. UNUSED-ELEMENTS]
// First loop in range [0..9]
// Second loop in range [0..8]
// and so on
int r = rand() % (SZ-i);
int d = numbers[r];
printf("%d ", d);
// Overwrite the used element with an unused element, i.e. last unused,
// so that unused elements are always at the lowest array index
numbers[r] = numbers[SZ-i-1];
}
printf("\n");
Implemented with an array + "swap and pop":
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static int pick_number(int *numbers, int max)
{
int index = rand() % max;
int result = numbers[index];
// Swap
numbers[index] = numbers[max-1];
return result;
}
int main(int argc, char *argv[])
{
srand(time(NULL));
int numbers[10] = {1,1,3,3,5,5,7,7,8,8};
for (int i = 10; i > 0; i--) {
printf("got: %d\n", pick_number(numbers, i));
}
return 0;
}

How can I use the rand() function to generate a different number that hasn't been generated before?

// What I mean by this is shown by my example:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int i;
int a;
for (a = 0;a <10;a ++) {
i = (rand()%10)+1; // generates a number from 1-10
printf("%d\n", i);
}
// I would like for the loop to generate a number that gives a number that was not generated before. For example, an output such as:
1,3,6,2,8,9,4,10,5,7
instead of:
3,9,10,3,7,9,2,7,10,1
In other words, I would like no copies.
You obviously don't just want no copies, but you want every number in a given set exactly once. This is, as commented by Robert, similar to shuffling a deck of cards. You don't have "decks" in C, but you can model one as an array:
int deck[] = {1,1,1,1,1,1,1,1,1,1};
This should represent 10 different "cards" (identified by their index in the array), each available one time. Now, just write code that "draws" cards:
int i = 0; // starting point for searching for the next card to draw
for (int n = 10; n > 0; --n) // how many cards are left
{
int skip = rand() % n; // randomly skip 0 .. n cards
while (1)
{
if (deck[i]) // card still available?
{
if (!skip) break; // none more to skip -> done
--skip; // else one less to skip
}
if (++i > 9) i = 0; // advance index, wrapping around to 0
}
deck[i] = 0; // draw the card
printf("%d\n", i+1); // and print it out
}
of course, seed the PRNG (e.g. srand(time(0))) first, so you don't get the same sequence every time.
The idea shown in the question is to print numbers within a range, without repetition. Here is one way to do that, by putting each value into an array and swapping its elements around.
A variation could be that you don't want to use all the possible numbers, in that case just change PICKED.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ARRLEN 10
#define PICKED 10
int main(void) {
int array[ARRLEN];
srand((unsigned)time(NULL)); // seed the PRNG
for(int i = 0; i < ARRLEN; i++) { // generate the numbers
array[i] = i + 1;
}
for(int i = 0; i < ARRLEN; i++) { // shuffle the array
int index = rand() % ARRLEN;
int temp = array[i];
array[i] = array[index]; // by randomly swapping
array[index] = temp;
}
for(int i = 0; i < PICKED; i++) { // output the numbers
printf("%d ", array[i]);
}
printf("\n");
}
Program output:
9 8 4 5 1 10 7 3 6 2
The library's PRNG is not very random, but for many cases that is not important. If it is, better algorithms are available.

Find missing number between 1 to 100

This question has been asked here on SO before with below code
find3missing(int* array)
{
int newarray[100] = {0};
For i = 0 to 99
++newarray[array[i]] ;
For i = 0 to 99
If newarray[i] != 1
Cout << “the missing number is ” << i+1 << endl ;
}
But when I checked this code, it doesn't seem to work. Suppose I have an array of {1,2,6}. The output should be 3,4,5 but with the code above I get 1,4,5,6 instead. Below is my implementation of pseudo code with array size 6.
main()
{
int a[6]={1,2,6};
int tmp[6]={0},i;
for(i=0;i<6;i++)
{
++tmp[a[i]];
}
for(i=0;i<6;i++)
{
if(tmp[i]!=1)
{
printf("%d",i+1);
}
}
}
Is this the right code?
This ++newarray[array[i]] should be ++newarray[array[i] - 1]. This because you are interested in a sequence of 1-100 numbers, so no 0, but C arrays are 0 based. If you then look at the cout: the missing number is ” << i+1 here you "unshift" the number by adding 1.
There is another problem: you should pass the number of elements of the array, something like:
find3missing(int* array, int length) {
int newarray[100] = {0};
for (int i = 0; i < length; i++) {
++newarray[array[i] - 1] ;
}
C/C++ arrays are zero based, as A[i] is equivalent to *(A+i). So change ++newarray[array[i]] to ++newarray[array[i]-1]. Also use malloc, free and memset to use an array of dynamic size.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void find3missing(int* pArray, size_t size, int min, int max){
int* newarray;
int i;
unsigned int j;
int range = max - min;
if(range < 0)
return;
newarray = (int*) malloc(range*sizeof(int)); // allocate enough memory
memset(newarray,0,range*sizeof(int)); // set that block to zero
for(j = 0; j < size; ++j){
++newarray[pArray[j]-min];
}
for(i = 0; i < range; ++i){
if(!newarray[i])
printf("%d is missing!\n",min+i);
}
free(newarray);
}
int main(){
int test[] = {1,3,6};
find3missing(test,sizeof(test)/sizeof(int),1,6);
return 0;
}
Please note that this solution is very inefficient if your array is sorted. In this case have a look at Jimmy Gustafsson's answer.
This algoritm will be quite simple, since you're using a sorted array. Simply check if the current value +1 equals the nextvalue like below:
find3missing(){
int array[arraySize]; // the array with integers
for(i=0;i<arraySize;i++)
if(array[i]+1 != array[i+1]) // if value array[i]+1 is not equal the next index
// value, then it's a missing number
printf("A missing number: %i", i+1);
}

C programming - A array and a random number combined question?

this is the part of my code I'm having trouble with. I can't understand why its doing it wrong. I have an array where it stores numbers 0 - 25 which are cases. The numbers are to be randomized and overwritten into the array. Only condition is is that no number can be doulbes, there can only be one of that number. I'm not asking you to do my code but do hint me or point me in the write directions. I am trying to learn :)
The problem lies within the second do loop. I can get the numbers to be randomized, but I get doubles. I have created a loop to check and fix this, but it's not working. The code does run, and doubles do still happen and I can't see why. It looks correct to me. Please look, thank you (:
This is what I have done originally (at the very end is where I am at now):
int check_double = 0;
int i = 0;
int counter = 0;
int array_adder = 0;
int random_number = 0;
int cases[] = {
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
};
float money[] = {
0.01,1,5,10,25,50,75,100,200,300,400,500,750,1000,5000,10000,25000,50000,750000,100000,200000,300000,400000,500000,750000,1000000
};
//Randomize all case number and realine them in the array
srand ( time(NULL) );
do
{
cases[counter]= rand() % 26;
counter += 1;
printf("%d\n", cases[counter]);
}
while (counter <= 25);
//make sure there are no doubles in the array, just 0 - 25 and not a single number repeated twice
do
{
check_double = 0;
for (i = 0; i < counter; i++)
{
if (cases[counter] == cases[i])
{
cases[counter] = rand()% 26;
check_double == 1;
}
}
}
while (check_double != 0);
Currently, what I had achived after that was combing both loops and check for doubles as the array goes. This is what I made, it still has doubles and im not sure why, I only posted the cose with both loops combined:
do
{
cases[counter]= rand() % 26;
if (cases[counter]>=1);
for(i=0;i<=counter;i++)
if (cases[counter]==cases[i])
{
cases[counter]=rand()% 26;
}
printf("%d\n",cases[counter]);
counter+=1;
}
Robsta, you could try the following piece of code, I have run this in Dev-C++, any changes that you require can be made from your side. But, I assure you that this code generates what you intend.
int check_double = 0;
int i = 0;
int counter = 0;
int cases[] = {
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
};
//Randomize all case number and realine them in the array
srand ( time(NULL) );
do
{
cases[counter]= rand() % 26;
for(i=0;i<counter;i++)
if (cases[counter]==cases[i]){
while (cases[counter]==cases[i])
{
cases[counter]=rand()% 26;
}
i=0;
}
printf("%d\t%d\n",counter,cases[counter]);
counter+=1;
}while (counter <= 25);
If you have any clarifications required, I would love to discuss with you.
-Sandip
You're only ever writing over the last value in the array:
for(i=0;i<counter;i++)
if (cases[counter]==cases[i])
You need to loop through as you are, then have an inner loop, where you compare all the other entries to the current one.
Even easier would be to do the loop where you set each random number, so when you set cases[3] for example, loop from 0 to 2 and check to see if your new value for 3 clashes, if so, wash - rinse - repeat!
You have this line of code:
check_double==1;
That doesn't change check_double because it's ==, not =. == compares; it doesn't assign. Change that line to this:
check_double=1;
A helpful compiler (clang in this example) will give you a warning about this:
test.c:5:14: warning: expression result unused [-Wunused-value]
check_double==1;
~~~~~~~~~~~~^ ~
You can't check for duplicates with a single loop. You need to at least compare every possible pair of elements to be able to see if there's a duplicate. I'm guessing you forgot to loop over counter somewhere inside the second do...while?
Note that your method is not guaranteed to terminate. (Very, very likely but not certain.) Why don't you simply shuffle the cases array? Shuffling is simple but tricky; see Fisher-Yates (or Knuth) Shuffle for a simple algorithm.
If you are asking how to randomly sequence the number 1-25 then you could do something like this. This is a very brute-force way of generating the sequence, but it does work and might give you a starting point for something more optimized.
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
#include <conio.h>
const int LastNumber = 25;
bool HasEmpty(int available[LastNumber][2])
{
bool result = false;
for(int i = 0; i < LastNumber; i++)
{
if (available[i][1] == 0)
{
result = true;
break;
}
}
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
int available[LastNumber][2];
int newSequence[LastNumber];
srand((unsigned int)time(NULL));
for(int i = 0; i < LastNumber; i++)
{
available[i][0]=i;
available[i][1]=0;
}
int usedIndex = 0;
while (HasEmpty(available))
{
int temp = rand() % (LastNumber + 1);
if (available[temp][1] == 0)
{
newSequence[usedIndex++] = available[temp][0];
available[temp][1] = 1;
}
}
for(int i = 0; i < LastNumber; i++)
{
printf("%d\n",newSequence[i]);
}
getch();
return 0;
}

Resources