Generating random numbers in conditions - c

I'm trying to generate three random numbers in three conditions and the three numbers must be from 0 to 100:
an odd number
an even number
a number larger than 50
Here is my code:
#include <stdio.h>
#include <time.h>
int main (void) {
int num1 = 0, num2 = 0, num3 = 0;
srand(time(NULL));
num1 = rand() % 100;
while (num1 % 2 != 0) {
num1 = rand() % 100;
}
num2 = rand() % 100;
while (num2 % 2 == 0) {
num2 = rand() % 100;
}
num3 = rand() % 100;
while (num3 > 50) {
num3 = rand() % 100;
}
printf("your numbers\n%d\n%d\n%d\n", num1, num2, num3);
return 0;
}
the compiler answers me:
warning: implicit declaration of function 'srand' [-Wimplicit-function-declaration]
srand(time(NULL));
and I do have stand in the requirements of the school:
it must be in loops
I cannot use break nor TRUE nor FALSE

Your srand() issue is simply because you haven't included stdlib.h, where that call (and rand() for that matter) is declared.
In any case, there's no real need to use a loop while discarding "invalid" numbers, you can use math for this :-) (a)
Assuming 0 to 100 inclusive:
num1 = rand() % 50 * 2 + 1 // 1, 3, 5, ..., 99
num2 = rand() % 51 * 2 // 0, 2, 4, ..., 100
num3 = rand() % 50 + 51 // 51, 52, ..., 100
For num1, the % gives a value 0..49 which, when doubled and incremented, gives you an odd number in the desired range. The second one is similar but with the range expanded slightly since there are even numbers at both ends. The third simply gives a number 0..49 which maps to 51..100 when 51 is added.
Similar results can be obtained if the range is only half-open (0..99 inclusive):
num1 = rand() % 50 * 2 + 1 // 1, 3, 5, ..., 99
num2 = rand() % 50 * 2 // 0, 2, 4, ..., 98
num3 = rand() % 49 + 51 // 51, 52, ..., 99
If, for some bizarre reason it has to use a loop (despite the inefficiencies), you have some problems with the conditions you use - they're basically all the wrong sense. In other words, you want (for example) the first loop to run while the number is even so that it will eventually produce an odd number.
You should be able to use something like the following. Each block consists of initialising the variable to a value that will force the loop to start then the loop that continues until a value with the desired properties is found:
int num1 = 0; // even forces loop entry
while ((num1 % 2) == 0) // wait for odd
num1 = rand() % 100;
int num2 = 1; // odd forces loop entry
while ((num2 % 2) == 1) // wait for even
num2 = rand() % 100;
int num3 = 1; // 50 or less forces loop entry
while (num3 <= 50) // wait for 51+
num3 = rand() % 100;
All of these limit the range of potential values to 0..99 inclusive, If you want to include 100, simply change the expressions to be rand() % 101.
(a) I'm actually not a fan of these sorts of limitations when set by educators. They're actually teaching inefficient ways to code. It would be far better if it was something that was a lot harder to do with a simple mathematical operation (like ensuring the number was neither 11, 17, 43 nor 97).
I suspect you could find a mathematical way to detect that but it would be far easier just to use a series of conditionals. Now I'm just waiting for someone to show me up by providing the mathematical formula for detecting those four :-)

There are some mistakes in the posted code:
a missing #include <stdlib.h>
the first test should be while (num1 % 2 == 0)
the second test should be while (num2 % 2 != 0)
the third test should be while (num3 <= 50)
Here is a modified version with loops but without looping :)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main (void) {
int num1, num2, num3;
srand(time(NULL)); /* or better randomness with srand(clock()); */
num1 = 1 + rand() % 50 * 2; /* 1, 3, ..., 99 */
while (num1 % 2 == 0) {
num1 = rand() % 100;
}
num2 = rand() % 50 * 2; /* 0, 2, ..., 98 */
while (num2 % 2 != 0) {
num2 = rand() % 100;
}
num3 = 51 + rand() % 49; /* 51, 52, ..., 99 */
while (num3 <= 50) {
num3 = rand() % 100;
}
printf("your numbers\n%d\n%d\n%d\n", num1, num2, num3);
return 0;
}
For those interested, both gcc and clang detect that the first 2 loops can be eliminated, but not the third as they do not make the assumption that rand() return a non negative number: https://godbolt.org/z/ucpV-y

You need to #include <stdlib.h> to get rid of this warning.
However, there's a bigger problem with your code: you have all the conditions inverted.
This will loop until the number is odd:
while (num1 % 2 != 0) {
This will loop until the number is even:
while (num2 % 2 == 0) {
And this will loop until the number is less than or equal to 50:
while (num3 > 50) {
To fix that, simply invert the conditions:
while (num1 % 2 == 0) { /* until we get an even number */
/* ... */
while (num2 % 2 != 0) { /* until we get an odd number */
/* ... */
while (num3 <= 50) { /* until num3 is greater than 50 */

Related

Trying to implement Luhn's Algorithm in C

Iam trying to implement Luhn's algorithm in the C language to check credit card validity, for those who don't know... this is it:
Multiply every other digit by 2, starting with the number’s
second-to-last digit, and then add those products’ digits together.
Add the sum to the sum of the digits that weren’t multiplied by 2.
If the total’s last digit is 0 (or, put more formally, if the total
modulo 10 is congruent to 0), the number is valid!
and to implement that, I looped through the whole number and if the number place I was in had a modulo 2 equal to 0 then I would multiply by two and add to a variable called totalEven.
if that wasn't the case I would add the number I was in to totalOdd without multiplication.
I would then increment the place by one and check the other numbers until I reach 16 (the max digits for a card).
I would later add both variables and check if the total modulo ten was equal to 0. If it means the credit card number is correct, else it is false.
here is the code:
#include <stdio.h>
#include <cs50.h>
//list of variables
//is the card valid
bool isValid = true;
// the creditcard number
long input;
//mod stands for modules, and is used to single out each number as seen later
int mod = 10;
//the location at which number I am checking
int place = 1;
//num is the number I am checking that has been singled out
int num = 0;
//total of numbers * 2 located at locations numbered with even numbers
int totalEven = 0;
//total of numbers located at locations numbered with odd numbers
int totalOdd = 0;
//gets input and stores it in well.. input
input = get_long("Number: ");
// a formula to single out a number, starting with the ones and then as you can see, mod is muliplied by 10 to go over the second number.
num = ((input % mod) - (input % (mod /10))) / (mod/10);
//loops 16 times
for(int i = 0; i < 16; i++)
{
// if the place is even execute below
if(place % 2 == 0)
{
totalEven = totalEven + num * 2;
}
//else do this
else if (place % 2 != 0)
{
totalOdd = totalOdd + num;
}
//moves to the next number
mod = mod * 10;
place++;
}
//fufils the last step of the algorithm
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
}
problem is that this block of code gives me invalid or !isValid even though the credit card number is supposed to be correct and I checked my "formula" and it works just fine...
I have absolutely no idea what to do... I am a humble hobbyist so plz don't roast me for the monstrosity above.
here is a complete version of the code
#include <stdio.h>
#include <cs50.h>
long power();
int main(void)
{
//AMERX 15 STRT 34 OR 37
//MC 16 STRT 51, 52, 53, 54, 55
//VZA 13 OR 16 STRT 4
long input;
bool isValid = true;
string type;
int mod = 10;
int place = 1;
int num = 0;
int totalEven = 0;
int totalOdd = 0;
do
{
input = get_long("Number: ");
}
while(input < 0);
for(int i = 0; i < 16; i++)
{
num = ((input % mod) - (input % (mod /10))) / (mod/10);
if(place % 2 == 0)
{
totalEven = totalEven + num * 2;
}
else
{
totalOdd = totalOdd + num;
}
mod = mod * 10;
place++;
}
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
printf("%i , %i", totalEven, totalOdd);
}
if (isValid == true){
if((input < (38 * power(10, 13)) && input >=(37 * power(10, 13))) || (input < (35 * power(10,13)) && input >= (34 * power(10, 13))))
{
type = "AMEX\n";
}
else if(input >= (51 * power(10, 14)) && input < (56 * power(10, 14)))
{
type = "MASTERCARD\n";
}
else if((input < (5 * power(10, 12)) && input >= (4 * power(10, 12))) || (input < (5 * power(10, 15)) && input >= (4 * power(10, 15))))
{
type = "VISA\n";
}
else{
type = "error\n";
}
}
else
{
type = "INVALID\n";
}
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
}
printf("%s", type);
}
long power(int n, int p)
{
long result = 1;
for(int i = 0; i<p; i++)
{
result = result * n;
}
return result;
I'm not an expert in Luhn algorithm but when I read https://en.wikipedia.org/wiki/Luhn_algorithm it seems to me that you are doing it wrong.
Quote from https://en.wikipedia.org/wiki/Luhn_algorithm :
From the rightmost digit (excluding the check digit) and moving left, double the value of every second digit. The check digit is neither doubled nor included in this calculation; the first digit doubled is the digit located immediately left of the check digit. If the result of this doubling operation is greater than 9 (e.g., 8 × 2 = 16), then add the digits of the result (e.g., 16: 1 + 6 = 7, 18: 1 + 8 = 9) or, alternatively, the same final result can be found by subtracting 9 from that result (e.g., 16: 16 − 9 = 7, 18: 18 − 9 = 9).
I don't see anywhere in your code where you handle that bolded part.
Instead of
totalEven = totalEven + num * 2;
I think you need
int tmp = num * 2;
if (tmp > 9) tmp = tmp - 9;
totalEven = totalEven + tmp;
That said - I think you are making the implementation much more complex than needed by storing the input as a number. Instead of a number you could use an array of digits.
That is - instead of
long input = 1122334455667788
use
int digits[] = {8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1};
// Notice that index zero is the rightmost digit
In this way the algorithm is much more simple:
// Double every second element and check for overflow
for (idx = 1; idx < 16; idx += 2)
{
digits[idx] = 2 * digits[idx];
if (digits[idx] > 9) digits[idx] = digits[idx] - 9;
}
// Calculate the sum
sum = 0;
for (idx = 0; idx < 16; ++idx)
{
sum = sum + digits[idx];
}
If you must receive the input as a number, start by calling a function that converts the number to an array of digits. You can find many, many examples of how that conversion is done here on SO. Here Converting integer into array of digits is just one of many examples.
As I was looking at your code, there some mistakes I want to point out.
You forgot: #include <string.h> as you did declare string type in the code.
input = get_long("Number: "); should have its own do-while loop in case user inputs letters or incorrect numbers.
if(place % 2 == 0){
totalEven = totalEven + num * 2;
}
else if (place % 2 != 0){
totalEven = totalEven + num;
} should totalOdd = totalOdd + num for the second part
totalEven = totalEven + num * 2 is right and wrong at the same time. It only works if the number multiplied by 2 is less than 10. If the num * 2 >= 10, lets say num = 6, then 6 * 2 is 12 which would then be 1 + 2 + totalEven.
num = ((input % mod) - (input % (mod /10))) / (mod/10); This should be in the first for loop.
In #include <math.h>, there is a power function called pow which does exactly as your power() function.
Caution: I have made use of CS50X Library as the question seems to be the one from the same.
#include <stdio.h>
#include <cs50.h>
// Luhn's Algorithm
int main(void)
{
long cardNumber = get_long("Please, enter your card number: ");
int sum1 = 0, num = 0, remainder = 0, sum2 = 0;
long temp = cardNumber;
while (temp > 0)
{
num = ((temp / 10) % 10) * 2; // Multiplying every other digit by 2, starting with the number’s second-to-last digit
while (num > 0)
{
remainder = num % 10;
sum1 += remainder; // Adding those products’ digits together
num /= 10;
}
temp /= 100;
}
// So as to restore the initial values of remainder and temp for the use in next loop
remainder = 0;
temp = cardNumber;
while (temp > 0)
{
remainder = temp % 10;
sum2 += remainder; // Sum of the digits that weren’t multiplied by 2
temp /= 100;
}
((sum1 + sum2) % 10) == 0 ? printf("Valid\n") : printf("Invalid\n");
return 0;
}

Error code randomly appears when trying to run slot machine program

I am writing a program for a basic slot machine, randomly generating numbers and displaying the corresponding "symbols" for them from an array. The program executes most of the time but randomly I get an error code -1073741819 (0xC0000005). I'm extremely new to C so I'm unfamiliar with a lot of things, including what exactly can be causing this error in my code.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand(time(NULL));
char *symbols[] = {"Pineapple", "Kiwi", "Orange", "Lime", "Peach",
"Lemon", "Pear", "Banana", "Cherry", "Grape", "Blueberry",
"Blackberry", "Apricot"};
int num1, num2, num3;
int balance;
printf("Enter initial balance (in cents): ");
scanf("%d", &balance);
num1 = (rand() % (13 - 0 + 1)) + 0;
num2 = (rand() % (13 - 0 + 1)) + 0;
num3 = (rand() % (13 - 0 + 1)) + 0;
printf("%s ", symbols[num1]);
printf("%s ", symbols[num2]);
printf("%s ", symbols[num3]);
printf("\n");
if ((num1 == num2) && (num1 == num3))
{
printf("Congratulations! You have won $1");
balance += 100;
printf("\n");
}
balance -= 5;
printf("Remaining Balance: %d", balance);
return 0;
}
The error as I said happens randomly and I haven't been able to reliably reproduce it. Sometimes only 1/3 fruit names prints and I get the error code, sometimes it's 2 and sometimes none prints.
This:
num1 = (rand() % (13 - 0 + 1)) + 0;
Is the same as:
num1 = rand() % 14;
Which means you're generating a number from 0 to 13. Your symbols array has 13 elements with indexes from 0 to 12. So when you randomly generate the value 13, you're reading past the end of the array. Doing so invokes [undefined behavior]9https://en.wikipedia.org/wiki/Undefined_behavior), which in this case causes your program to crash.
Change that line and the two that follow to:
num1 = (rand() % 13;
num2 = (rand() % 13;
num3 = (rand() % 13;
That way you get a number from 0 to 12.
The statement (rand() % (13 - 0 + 1)) + 0; is equivalent to rand() % 14 which will generate random numbers from 0-13 INCLUSIVE. The problem is that you only have 13 strings, so when the rng spits out a 13, the fruit at index 13 doesn't exist.
This can be fixed by either adding another fruit or by changing your rng to rand() % 13
You are randomly accessing an invalid 14th element of symbols array (which has 13 elements).
When you write
num1 = (rand() % (13 - 0 + 1)) + 0;
you are trying to calculate symbols index. But this could lead to index 13... and symbols[13] does not exist, and it will translate in accessing a memory location you are not supposed to access.
Write simply
num1 = rand() % 13;
and everything will be fine.

Generating random number between 2 variables

I'm struggling to find a way to generate a random number only between 20 and 30. I have this so far but its getting numbers below 20.
int num1 = 30;
int num2 = 20;
int num_random = rand()%num1;
while (num_random < num2){
num_random = rand()%30;
}
To get numbers between 20 and 30 use:
(rand() % 10) + 20
General formula would be:
(rand() % (difference_between_upper_and_lower_limit)) + lower_limit
The resultant of Difference between upper and lower limit will be:
(0, no_of_numbers_between_upper_and_lower_limit)
Maybe you can try rand()/10 + 20.
Try this:
int num1 = 30;
int num2 = 20;
int num_random;
while (1){
num_random = rand()%num1;
if(num_random < num2)
break;
}

Decryption - Get back the number after splitting C programming

I've just did an encryption using a simple C code. The encryption works like this, "Your application should read a 4 digit integer entered by the user and replace each digit with the result of adding 7 to the digit and getting the remainder after diving the new value by 10:
Let say I've entered 1234, the value after encryption will be 8,9,0,1.
I'm doing the encryption with the following code below:
num1 = ((digits/1000) + 7) % 10;
num2 = ((digits/100) + 7) % 10;
num3 = ((digits/10) + 7) % 10;
num4 = ((digits/1) + 7) % 10;
Now I would like to do a decryption, getting back the value I've entered. I'm wondering if I'm able to do a reverse modulo? A backwards calculation for %?
Meaning if a = 3 + 4, a = 7.. So what is 7 = b + 4 which is b = 7-4. I'm
What I've attempted so far is this:
dNum1= (digits/1000) % 10;
dNum2= (digits/100) %10;
dNum3= (digits/10) %10;
dNum4= (digits % 10) ;
The question is now: How do I retrieve the original value from the decrypted value(8,9,0,1)? (Original Value: 1234)
Since you encoded each digit by adding 7, you need to decode by subtracting 7. Then if the value is negative, add 10 to get back the expected value.
num1 = (digits/1000) - 7;
num2 = (digits/100) - 7;
num3 = (digits/10) - 7;
num4 = (digits % 10) - 7;
if (num1 < 0) num1+=10;
if (num2 < 0) num2+=10;
if (num3 < 0) num3+=10;
if (num4 < 0) num4+=10;
EDIT:
Better yet, you can add 3 and then mod by 10, which does the same thing. Thanks to psmears for suggesting this.
num1 = ((digits/1000) + 3) % 10;
num2 = ((digits/100) + 3) % 10;
num3 = ((digits/10) + 3) % 10;
num4 = ((digits/1) + 3) % 10;
EDIT2:
If you're translating the decoded digits directly from the encoded digits without moving the values back to digits first, do this:
dNum1 = (num1 + 3) % 10;
dNum2 = (num2 + 3) % 10;
dNum3 = (num3 + 3) % 10;
dNum4 = (num4 + 3) % 10;
that's an interesting question #stack. One thing I see is that you are using individual statements to assign values to num1,num2,num3,num4
but every encryption follows a defined pattern and implicit is that
every decryption does
And if you are successful in finding such pattern(Which I prefer to say mystery!), then these kind of encryption are near solved!
So I decided to find the pattern and I was successful in finding it for your encryption. ones you find pattern, for loop is very useful to repeat the process and thus encode given number.(same for the decoding too)
Note: I Don't know whether you require such a solution, but this is more useful as there are less number of variables which is a characteristic of any good program. and this code is only for 4 digit numbers... feel free to ask me if you want to extend it to n digited numbers :)
so! Here is my code:
#include<stdio.h>
#include<math.h>
int main()
{
//encryrption
int num,num1,i,e=0,d=0;
printf("enter 4 digit number:\n");
scanf("%d",&num);
num1=num;
for(i=3;i>=0;i--)
{
num1=(num)/(pow(10,i));
num1=(num1+7)%10;
e=(10*e)+num1;
}
printf("encryption = %d\n",e);
//decryption:
for(i=3;i>=0;i--)
{
num1=e/pow(10,i);
num1=((num1-7)%10);
d=(10*d)+num1;
}
printf("decryption = %d",d);
return 0;
}

Find the sum of all the even-valued terms in the sequence which do not exceed four million

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
I made the program but my answer doesnt match.
#include<stdio.h>
int main()
{
long unsigned int i,sum=0,x=1,y=2,num;
for(i=0;i<4000000;i++)
{
num=x+y;
if(i%2==0)
sum+=num;
x=y;
y=num;
}
printf("%lu\n",sum);
getchar();
return 0;
}
Three problems I can see:
You should start with x = 1, y = 1, since otherwise you skip the first even-valued Fibonacci;
Your loop condition should be (x + y) <= 4000000
You should test num for even-ness, not i.
(After these changes, it should be obvious that you can omit i entirely, and therefore replace the for loop with a while loop)
In your code you find the sum of fibonacci numbers with even index, not even numbers themselves + you search the first 4000000 numbers in sequence, not the numbers with values <= 4000000. Your code should be something like
while ( y < 4000000){
...
if (y %2 == 0)
sum += y;
}
I've made a minimal set of corrections and now get the right answer. You may learn more by reading this (after all, it was yours, to start with) than by me rambling on about it...
#include <stdio.h>
#define LIMIT (4 * 1000 * 1000)
int main() {
long unsigned int sum = 0, x = 1, y = 2, num;
while (x <= LIMIT) {
if ((x & 1) == 0 && x <= LIMIT)
sum += x;
num = x + y;
x = y;
y = num;
}
printf("%lu\n", sum);
return 0;
}
I think the following line
if(i%2==0)
might instead be
if( num % 2 == 0)
On further thinking, I think you don't actually need the variable i. Instead, your loop can be controlled by num as:
enum { LIMIT = 4 * 1000 * 1000 };
num = x + y;
while( num <= LIMIT ) {
print num inside the loop, for debugging
for(i=0;i<4000000;i++)
{
num=x+y;
printf("num is %lu\n", num); /* DEBUGGING */
if(i%2==0)
sum+=num;
x=y;
y=num;
}

Resources