Problem with continue instruction after rand() function - c

I just wanted to solve an exercise that asks me to write a routine to generate a set of even random numbers between 2 to 10.
The problem is when printing, because I want the last number not to be followed by a comma.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i, a, b, c;
i = a = b = c = 0;
srand(time(NULL));
for (i = 2; i <= 10; i++)
{
a = rand() % 8 + 2;
if ((i <= 10) && (a % 2) != 0)
{
continue;
}
printf((i < 10) ? "%d, " : "%d\n", a);
}
return 0;
}
And these are two execution examples:
4, 4, 2, 8,
2, 8, 6, 4, 2
In one the comma does not appear at the end but in another it does. When debugging I see that the error happens when the last number is odd, because the continue statement causes it to go to the next iteration.

As Retired Ninja has said, there are many unnecessary conditionals that can be avoided. I have revised your code so that a will always generate an even number between 2 and 10, thereby removing the need for the logic you implemented. This is what I have assigned this new a value as:
a = ((rand() % 4) * 2 + 2);
This generates a random value between [0,4], multiplies it by 2, and adds 2, for an integer between 2 and 10, noninclusive. Since your new a is always even, I removed your logic to check whether the number is even.
Revised code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i, a, b, c;
i = a = b = c = 0;
srand(time(NULL));
for (i = 2; i <= 10; i++)
{
a = ((rand() % 4) * 2 + 2);
printf((i < 10) ? "%d, " : "%d\n", a);
}
return 0;
}
Note that this code will always produce 9 numbers, as you have not specified how many values to print each time, just that you need to "write a routine to generate a set of even random numbers between 2 to 10". You can always change the amount of numbers printed by changing the value of i in the for loop. The comma issue, however, is not a problem anymore.
If my solution has helped you, please mark my answer as the correct answer :)

Related

Time optimization with C? In a simple input reading algorithm

I'm reading a file with a set format so I'm sort of aware of what to expect from the file, however, when I try to print all the input, just to make sure that the code works, the console crashes with a timeout exception. I've got a nested for loop, since I find it the easiest way to handle the file format. But I don't know if there's a better way to handle this.
The problem is a geeks for geeks coding challenge. I noticed that when I change the for variable use in the for loop the code compiles, but this way I wouldn't be able to handle different file formats. As long as I have a constant in the for loop as my parameter it runs. Any idea as to why that is?
the first line is the number of cases, every first line after that tells me the number of node and the number of links, and the following line has linking nodes.
The expected output would be 4 and 3 but I haven't made it that far yet, I'm still making sure that I'm able to read in file properly.
#include <stdio.h>
#include <ctype.h>
int nextInt();
int main() {
int c = getchar() - '0';
printf("%d\n", c);
while(c > 0){
int x, y;
x = nextInt();
y = nextInt();
printf("%d%4d\n", x, y);
int i, a, b;
for(i = 0;i<2*y; i++){
a = nextInt();
printf("%4d", a);
}
printf("\n");
c--;
}
return 0;
}
int nextInt(){
int c, n;
int num;
while(isspace(c=getchar())){;}
num = c - '0';
while(!isspace(n = getchar())){
num = (num * 10) + (n - '0');
}
return num;
}
An example for the input looks something like this:
2
4 4
0 2 0 3 1 3 2 3
4 3
0 2 0 1 0 3
output
4
3
The while loop in nextInt() doesn't stop when it reads EOF. If the last line doesn't end with a newline, you'll go into an infinite loop, because it will never find the delimiter after the last number.
int nextInt(){
int c, n;
int num;
while(isspace(c=getchar())){;}
num = c - '0';
while(!isspace(n = getchar()) && n != EOF){
num = (num * 10) + (n - '0');
}
return num;
}

Why is my pthread program missing prime numbers?

I am working on a program that utilizes pthreads in C. The function of the thread is to compute prime numbers based on a maximum number entered by the user at the CLI. Thus say for instance, the user enters ./ComputePrimes 20, the output should be 2, 3, 5, 7, 11, 13, 17, 19.
However, for some reason, my program only outputs 2 to 13 (thus my output is 2, 3, 5, 7, 11, 13).
I am using a formula based off of Wilson's Theorem for computing primes:
https://en.wikipedia.org/wiki/Formula_for_primes
I know from a Discrete Mathematics class I have taken in the past that there is no solid formula for computing primes. The purpose of this program however is to demonstrate pthreads which I believe I have done successfully. Here is my program:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *generatePrimeNumbers(void *primenum) {
int i, j, a, b;
int primeNumbers[] = {};
int limit = (int *)primenum;
for (i = 1; i <= limit; i++) {
j = 0;
int a = (factorial(i) % (i + 1));
int b = (i - 1) + 2;
if (((a / i) * b) != 0) {
primeNumbers[j] = ((a / i) * b);
printf("%d ", primeNumbers[j]);
j++;
}
}
printf("\n");
return NULL;
}
int factorial(int n) {
if (n == 1) {
return 1;
} else return n * factorial(n - 1);
}
int main(int argc, char *argv[]) {
int numLimit;
pthread_t primethread;
if (argc != 2) {
printf("You need to enter a valid number!\n");
exit(-1);
}
else {
int i = 0;
numLimit = atoi(argv[1]);
if (numLimit < 2) {
printf("Please enter a number greater than or equal to 2.\n");
exit(-1);
}
}
pthread_create(&primethread, NULL, generatePrimeNumbers, (void *)numLimit);
pthread_exit(NULL);
}
As you can see below, I successfully create a thread, however some of the prime numbers are missing. I believe that I might have messed up somewhere in my called threads function. Thanks!
In many environment, int can only store integers only upto 2147483647 (2**31 - 1) while 20! = 2432902008176640000. Therefore, factorial(20) cannot be calculated correctly.
Making the return type of factorial to long long will make the output for input 20 correct (supposing that long long can save upto 2**63 - 1), but for larger number, you should consider other method such as taking modulo inside factorial method before the number gets too big.
Also note that the line
int limit = (int *)primenum;
looks weird. The cast should be int, not int *.
Another point is that you are assigning numbers to 0-element array as Retired Ninja said.
In this code, primeNumbers isn't used other than the printing point, so the printing should be done directly like
printf("%d ", ((a / i) * b));

C How to Keep a Random Variable From Repeating the Same Number

So I'm just learning C and I would like to know how you could prevent a variable randomized with the rand() function from repeating the same number. I have a script which simply randomizes and prints a variable in a for loop 4 times. How could I make it so the variable never gets the same number after each time it uses the rand() function?
#include <stdio.h>
#include <stdlib.h>
int randomInt;
int main()
{
srand(time(0));
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4;
printf("%d\n", randomInt);
}
return 0;
}
On most machines, int is 32 bits. So after 232 iterations, you are sure that you'll get some repetition (and probably much before).
If you restrict yourself to much less loops, consider e.g. keeping an array of previously met random numbers (or some hash table, or some binary tree, or some other container).
For a loop repeated only 4 times, keeping an array of (at most 4-1) previously emitted numbers is quite simple, and efficient enough.
Read also about the pigeonhole principle.
A slightly different approach.
int set[] = {0, 1, 2, 3 } ;
srand(time(0));
shuffle(set,4);
using the shuffle algorithm given in this question
https://stackoverflow.com/a/6127606/9288531
I'm guessing that you are getting the same numbers because your are running your program multiple times within the same second. If time(0) hasn't changed, you will have the same seed and the same random numbers generated. Unless your program runs extremely quickly, I imagine using a seed based on microseconds instead of seconds would work:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int randomInt;
int main()
{
struct timeval my_microtimer;
gettimeofday(&t1, NULL);
srand(t1.tv_sec * my_microtimer.tv_usec);
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4;
printf("%d\n", randomInt);
}
return 0;
}
What you could do is keeping track of each number you already generated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int hasMyNumberAlreadyBeenGenerated(int number, int generatedNumbers[], int size){
for(int i = 0; i < size + 1; i++){
//If you already generated the number, it should be present somewhere in your array
if(generatedNumbers[i] == number) return 1;
//If you did not, find the first available space in your array, and put the number you generated into that space
if(generatedNumbers[i] == 0){
generatedNumbers[i] = number;
break; //No need to continue to check the array
}
}
return 0;
}
int main()
{
int randomInt;
int generatedNumbers[4];
//We set "0" in all the array, to be sure that the array doesn't contain unknown datas when we create it
memset(generatedNumbers, 0x0, sizeof(generatedNumbers));
srand(time(0));
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4 + 1;
//As long as the number you generate has already been generated, generate a new one
while(hasMyNumberAlreadyBeenGenerated(randomInt, generatedNumbers, i) == 1){
randomInt = rand() % 4 + 1;
}
printf("generated : %d\n", randomInt);
}
return 0;
}
The problem with this method is that you can't generate a 0, because if you do you'll endlessly loop.
You can bypass this problem using a dynamic array using malloc() function.
If you want to write clean code you should define how many numbers you want to generate with a #define.
What you seem to be asking is a non-random set of numbers 0 to 3 in a random order. Given that;
int set[] = {0, 1, 2, 3 } ;
int remaining = sizeof(set) / sizeof(*set) ;
while( remaining != 0 )
{
int index = rand() % sizeof(set) / sizeof(*set) ;
if( set[index] > 0 )
{
printf( "%d\n", set[index] ) ;
set[index] = -1 ;
remaining-- ;
}
}
For very large sets, this approach may not be practical - the number of iterations necessary to exhaust the set is non-deterministic.

Project Euler Palindrome #4 with C

I found few posts regarding this problem using C. Most of the elements in my code work on their own but the iteration at the beginning is causing problems for some reason. First, I'm getting an "exited with non-zero status" error message. When I run the program with a smaller range for a and b, I don't get that message. I'm guessing there's a problem with the rev_array and for_array variables I created. I'm sure I'm doing something really dumb right here so I apologize in advance for that.
But when I use a smaller range for a and b (like 10 to 25), the program is still showing that all two-digit numbers (even 11, 22, 33, 44) are not the same forward and backward. I used printf to check for this.
I made a similar program that used fixed values for a and b instead of iterating over a range of values and it worked fine. But I couldn't figure out why this one isn't working.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int max;
int a;
int b;
int prod;
int m = 0;
int rev_array[10000];
int for_array[10000];
int c;
int d;
int same = 0;
int main(void)
{
// iterate over all 3 digit numbers in lines 19-21
for(a = 10; a <= 25; a++)
{
for(b = 10; b <= 25; b++)
{
max = 0;
prod = a * b;
/* thanks to Zach Scrivena for the following formula converting an integer to an array of integers posted on stackoverflow on February 5, 2009 under the subject "convert an integer number into an array"
*/
int n = prod;
while(n != 0)
{
rev_array[m] = n % 10;
n /= 10;
m++;
}
/* thanks to Jordan Lewis for the following int length formula posted to stackoverflow on June 18, 2010 in response to "Finding the length of an integer in C"
*/
int length = floor(log10(abs(prod))) + 1;
// create the forward array of the ints in prod
for(c = length - 1, d = 0; c >= 0; c--, d++)
{
for_array[d] = rev_array[c];
}
// compare the forward and reverse arrays to see if they match exactly
for(int e = 0; e < length; e++)
{
if(for_array[e] != rev_array[e])
{
// if they don't match then set same equal to 1 for following step
same = 1;
}
}
/* if prod is greater than max and the forward and reverse arrays are identical, then replace max with prod
*/
if(prod > max && same == 0)
{
max = prod;
}
// reset same and repeat the process
same = 0;
}
}
// print the final, greatest number that fits the preceding criteria
printf("new max: %i \n", max);
return 0;
}
Answers provided in comments:
You need to reset m to zero each time. – Johnny Mopp
You also don't need to calculate length, since m should contain the length after the while loop (but you need to reset it to 0 at the top). And all these variables should be local, and most of them (like m, n, prod) should be defined inside the inner loop, with a limited scope. max is the only one which needs to be preserved between iterations. – Groo

Time Exceeded for a project Euler test

I just got into problem solving on project Euler (and a beginner with C code).
Problem 1 states: If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000. I'm pretty sure my code is correct (or maybe not). Now when I compile my code on a website like codepad.org or ideone.com, it says "time exceeded". I'm guessing the code takes too long to run? Why is this the case?
My solution:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
int main (int argc, char *argv[]){
int i, j = 0;
for (i = 1; i <= 1000; i++){ //Traverses all the positive numbers under 1000
while ( (i % 5 == 0) || (i % 3 == 0)){
j = j + i; //If it's a multiple of 3 or 5 add it to the sum
}
}
printf("The sum of all multiples of 3 and 5 under 1000 is: %d", j);
return 0;
}
You have a while statement in there which should be an if statement. while takes you into an infinite loop as you never change the value of i inside the loop when the condition you are testing for is met.

Resources