Seven thieves & diamonds riddle C program - c

I recently wrote a C program for the following 'Seven thieves and diamonds' puzzle:
"There are seven thieves, They steal diamonds from a diamond merchant and run away in jungle. While running, night sets in and they decide to rest in the jungle When everybody’s sleeping, two of the best friends get up and decide to distribute the diamonds among themselves and run away. So they start distributing but find that one diamond was extra. So they decide to wake up 3rd one and divide the diamonds again …..only to their surprise they still find one diamond extra. So they decide to wake up fourth one. Again one diamond is spare. 5th woken up……still one extra. 6th still one extra. Now they wake up 7th and diamonds are distributed equally."
Although the logic is quite simple to understand, my program seems to be quite buggy. It only seems to run for the numbers 3, 5 and 7.
I am new to programming in general and I feel that my program is not very sophisticated:
#include<stdio.h>
int main()
{
int n,i,j,k;
int a[30];
printf("Enter the number of thieves\n");
scanf("%d",&n);
i=n+1;
while(1)
{
j=2;
k=0;
while(j<n)
{
if(i%j == 1 && i%n==0)
{
a[k]=1;
}
else
{
a[k]=0;
}
if(k==n-2)
{
k=0;
}
j++;
k++;
}
for(j=0;j<n-1;j++)
{
if(a[j]==0)
{
break;
}
else if(j==n-3 && a[j] == 1)
{
printf("The number of diamonds = %d\n",i);
return;
}
}
i++;
}
}
It would be great if someone could help me develop this code into something more nonspecific, such that it could return an output for all values of 'n.' Also, any feedback in general would be highly appreciated.

Your code is very hard to follow, so I wrote my own code to debug this and your program although obscure and hard to follow is completely correct for valid inputs, you are just not handling all the cases very well thus you are in a while loop forever. Not every input will work for this problem only prime numbers will give you an answer for this problem so inputs like 2, 4, and 6 will not work so they need to be handled.
Here is a test comparing your outputs with the test I wrote for valid inputs.
#Of Theives Your Code Test Code
3 3 3
5 25 25
7 301 301
11 25201 25201
13 83161 83161
You can write a quick function to test for this care of this like this:
int isPrime(int tmp)
{
int i;
for(i = 2; i <= tmp/2; i++)
{
if(tmp % i == 0)
return 0;
}
return 1;
}
Then you can check for valid inputs which numbers greater than 1 (because then there would not be enough thiefs for the story to happen) and prime like so:
#include<stdio.h>
int isPrime(int tmp)
{
int i;
for(i = 2; i <= tmp/2; i++)
{
if(tmp % i == 0)
return 0;
}
return 1;
}
int main()
{
int n,i,j,k;
int a[30];
printf("Enter the number of thieves that is prime and greater than 1\n");
scanf("%d",&n);
i=n+1;
if(isPrime(n) && n > 1)
{
while(1)
{
j=2;
k=0;
while(j<n)
{
if(i%j == 1 && i%n==0)
{
a[k]=1;
}
else
{
a[k]=0;
}
if(k==n-2)
{
k=0;
}
j++;
k++;
}
for(j=0;j<n-1;j++)
{
if(a[j]==0)
{
break;
}
else if(j==n-3 && a[j] == 1)
{
printf("The number of diamonds = %d\n",i);
return;
}
}
i++;
}
}
else
{
printf("Input Invalid.\n");
}
}
The code I wrote to test the riddle:
#include<stdio.h>
int isPrime(int tmp)
{
int i;
for(i = 2; i <= tmp/2; i++)
{
if(tmp % i == 0)
return 0;
}
return 1;
}
long gcd(long a, long b) {
if (b == 0) {
return a;
}
else {
return gcd(b, a % b);
}
}
int main()
{
int thieves, i;
long diamonds, lcm = 1;
printf("Enter the number of thieves that is prime and greater than 1:\n");
scanf("%d",&thieves);
if(isPrime(thieves) && thieves > 1)
{
for(i = 2;i < thieves;i++)
{
lcm = (lcm*i)/gcd(i,lcm);
}
i = 1;
dimonds = lcm*i + 1;
while(dimonds % thieves != 0)
{
dimonds = lcm*++i + 1;
}
printf("There are a minimum of diamonds is: %d\n",diamonds);
}
else
{
printf("Input inv\n");
}
}

Related

Certain values give incorrect results for prime number checking function

I recently wrote a program in C for a calculator. To produce a function that checks if the user input is a prime number or not (amongst other functions).
I essentially used this code (excluding all other functions):
#include <stdio.h>
#include <math.h>
int testForPrime(int);
int main(void) {
int ioperand1 = 0;
printf("\nEnter the value to check if prime (positive integer): ");
scanf("%d", &ioperand1);
if (testForPrime(ioperand1) != 0)
printf("\nThis number is prime.\n");
else
printf("\nThis number is not prime.\n");
return 0;
}
int testForPrime(int operand1) {
int i = 0;
for (i = 2; i <= sqrt(operand1); i++) {
if (operand1 == 0 || operand1 == 1)
return 0;
else if (operand1 % i == 0)
return 0;
else
return 1;
}
}
^
This code above produces the errors
I am not sure why the code produces an error for the value 9 (I fixed that above by adding the condition: if (operand1 == 9), but I don't understand why 9 is seemingly the only value that results in an incorrect solution (It would say 9 was prime, but not any other number give an incorrect result).
One other bug that I remidied with an extra condition statement was the value of 2.
Before adding the extra conditional statement in the main function: if (ioperand1 == 2), the value 2 would always come up as a non prime number.
I originally found this solution to check for prime numbers online, and I still don't understand why the for loop starts from 2.
#include <stdio.h>
#include <math.h>
int testForPrime(int);
int main(void) {
int ioperand1 = 0;
printf("\nEnter the value to check if prime (positive integer): ");
scanf("%d", &ioperand1);
if (testForPrime(ioperand1) != 0 || ioperand1 == 2)
printf("\nThis number is prime.\n");
else
printf("\nThis number is not prime.\n");
return 0;
}
int testForPrime(int operand1) {
int i = 0;
for (i = 2; i <= sqrt(operand1); i++) {
if (operand1 == 0 || operand1 == 1 || operand1 == 9)
return 0;
else if (operand1 % i == 0)
return 0;
else
return 1;
}
}
^This code above fixed the problem, though I don't undesttand why the problem existed in the first place.
TL;DR:
I don't know why this code doesn't work without the extra conditional statements:
if (operand1 == 9) in function definition,
and
if (ioperand1 == 2) in main function.
If anyone could help clear this up, I'd appreciate it.
It is because your prime checking loop does not iterate. It always returns on the first iteration. It must run to completion, and then the number will be prime. So
int testForPrime(int operand1) {
if(operand1 < 2) {
return 0;
}
int sr = (int)round(sqrt(operand1));
for(int i = 2; i <= sr; i++) {
if (operand1 % i == 0) {
return 0;
}
}
return 1;
}

its works perfectly except when i enter the integer '2'

#include <stdio.h>
#include <stdlib.h>
//this function checks if the given number prime or not
int prime_check(int number) {
for (int i = 2; i < number; i++) {
if (number % i == 0) {
return 1;
} else if (number == 2) {
return 0;
} else {
return 0;
}
}
}
//the problem is that when i entered the integer 2 i got that "the number is not prime" output
int main() {
int user_n;
printf("pls enter the number \n");
scanf("%d", & user_n);
if (prime_check(user_n) == 0) {
printf("the number is prime \n");
} else {
printf("its not prime.. \n");
}
}
If the selected number is 2, the for loop is never entered because i < number is initially false. The function then reaches the end without returning a value.
If a function is declared to return a value but does not, and the calling function attempts to use the return value, this triggers undefined behavior in your program, which basically means that no particular result is guaranteed.
Related to this, you have a logic error. The body of the for loop has a return statement in every path so no more that one iteration of the loop will occur. This causes all odd numbers to be reported as prime.
You only need to perform the % check inside of the loop. If that condition is not met, then continue on with the loop. If the loop exits, then you know you have a prime number and can return 0.
int prime_check(int number)
{
for (int i = 2;i<number;i++){
if (number % i == 0){
return 1;
}
}
return 0;
}
Also, you can reduce the number of loop iterations by changing the condition to i<=number/i (which is mathematically the same as i*i<=number but avoids overflow), since you don't need to check values greater than the square root of the number in question.
You can't enter to for loop only if the condition i < number is TRUE
SO you should check if number = 2 and number < 2 before your for loop
The new version of your code:
#include <stdio.h>
#include <stdlib.h>
int prime_check(int number) {
if (number == 2) {
return 0;
} else if (number < 2) {
return 1;
} else {
for (int i = 2; i < number; i++) {
if (number % i == 0) {
return 1;
} else if (number == 2) {
return 0;
} else {
return 0;
}
}
}
}
int main() {
int user_n;
printf("pls enter the number \n");
scanf("%d", & user_n);
if (prime_check(user_n) == 0) {
printf("the number is prime \n");
} else {
printf("its not prime.. \n");
}
}

Programming C - Debugging Numbers-Strings Conversion Problems

I'm working on an exercise problem for a programming class and I'm a bit out of my depth debugging it. My main problem is that I have had to convert strings into integers and vice-versa and I don't understand well how that works. I'll attach a copy of the exercise and another of my code. Any and all help is appreciated.
CODE:
#include <cs50.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
string Company_Check(long number);
bool Luhn (long number);
int main(void)
{
//Prompt for card Number
long card = get_long("Number:");
//Applying Luhn's Algorithm
bool validity = Luhn(card);
if (validity==true) //The card passed the test
{
//Finding and printing company name
printf("\nCompany: %s\n", Company_Check(card));
} else //The card didn't pass the test
{
printf("INVALID (Luhn’s Algorith)\n");
}
}
string Company_Check(long number)
{
//Declaring variables
char num[30];
char char_first_two[3]; //This is where I'll save the first two digits of the number
int int_first_two;
char char_first_one[3]; //This is where I'll save the first one digit of the number
int int_first_one;
//Creating the two 'First digits' var
int first_two = 10*(atoi(num[0]))+ atoi([num[1]);
int fist_one = atoi(num[0]);
//Analizing cases
if (first_two == 34 || first_two == 37)
{
printf("American Express\n");
} else if (first_two == 51 || first_two == 52 || first_two == 53 || first_two == 54 || first_two == 55)
{
printf("Mastercard\n");
} else{
//Could be (1) Visa or (2) INVALID
if (first_one == 4)
{
printf("Visa\n");
} else
{
printf("INVALID\n");
}
}
}
bool Luhn (long number) //Done
{
int i; //Used in the for loops
int sum1; //Used to tally the sums in Step 4
int sum2; //Used to tally the sums in Step 4
int total; //Used to tally the sums in Step 4
int cod; //Counter of Digits
int lastnumber; //Used in Steps 5 and 6
char num[30]; //Card number & total in String format
char fot[30]; //First Every-Other number list
char sot[30]; //Second Every-Other number list
//1. Converting the long NUMBER to a string NUM
sprintf(num, "%d", number);
//2. Calculating the number of digits of the number
cod = 0;
for(i=0; num[i+1]!= '\0' ; i++)
{
cod++;
}
//3. Creating two CHAR arrays of the first and second every-other number list
if (cod%2==0)//number of digits is even
{
for(i=0; num[i+1]!= '\0' ; i++)
{
if (i%2==0) //We're dealing with the FIRST set of every other numbers
{
fot[i/2]=num[i];
}
else //We're dealing with the SECOND set of every other numbers
{
sot[((int)(i/2))+1]=num[i];
}
}
fot[(cod/2)+1]= '\0';
sot[(cod/2)+1]= '\0';
} else //number of digits is odd
{
for(i=0; num[i+1]!= '\0' ; i++)
{
if (i%2==0) //We're dealing with the SECOND set of every other numbers
{
sot[i/2]=num[i];
}
else //We're dealing with the FIRST set of every other numbers
{
fot[((int)(i/2))+1]=num[i];
}
}
sot[(cod/2)+1]= '\0';
fot[(cod/2)+1]= '\0';
}
//4. Sum Algorithm
sum1=0;
sum2=0;
total=0;
for(i=0 ; fot[i+1]!= '\0' ; i++)
{
sum1 =+ atoi(fot[i]);
}
for(i=0 ; sot[i+1]!= '\0' ; i++)
{
sum2 =+ atoi(sot[i]);
}
total = sum1 + sum2;
//5. Isolating the last number
//converting the total into a string (using var NUM because its no longer needed)
sprintf(num, "%d", total);
//Calculating the number of digits
cod = 0;
for(i=0; num[i+1]!= '\0' ; i++)
{
cod++;
}
//putting the last number in a var
lastnumber = atoi(num[cod-1]);
//6. Studying cases
if (lastnumber==0)
{
return true;
}
else
{
return false;
}
}
Problem:
Problem

How can I compute if a value is prime or not faster?

My programs runs well in my compiler but it shows time limit exceeds in online contest compiler.
First line of input will contain a number N = number of test cases. Next N lines will contain number n as test case where 0<=n<=1000000000
Here is my code.
#include<stdio.h>
void main()
{
long t,n,i;
int f = 0;
scanf("%lu",&t);
while(t--)
{
scanf("%lu",&n);
f=0;
if(n==0 || n==1)
{
printf("NOT PRIME\n");
}
else
{
for(i=2;i<=n/2;i++)
{
if(n%i == 0)
{
printf("NOT PRIME\n");
f =1;
break;
}
}
if(f==0)
{
printf("PRIME\n");
}
}
}
}
How can I execute this program faster. Help me. Thanks in advance.
You can iterate to square root of n instead of n/2. Also you can pre-calculate all the prime factors in the range of square root of 1000000000 before the while loop. Then try to divide n with the prime factors that are less than or equal to sqrt(n) to check if it is prime or not.
The for loop:
(i = 3; i <= sqrt(n); i += 2) // skip 2 because it's the only even prime
Also you only need to test odd numbers for primality (two being the only even prime).
And compile with optimization, e.g. -O3 if using gcc.
You can make with increment 2:
My function to verify if a number is prime:
bool check(int n)
{
int i, j;
bool isprime;
if(n%2 == 0 || n == 0 || n == 1)
{
isprime = false;
}
else if(n == 2 || n == 3)
{
isprime = true;
}
else
{
for(i = 3; i<n; i+=2)
{
if(n%i == 0)
{
isprime = false;
break;
}
else if(i == n-2)
{
isprime = true;
break;
}
}
}
return isprime;
}
Remembering that call a function is less fast than use directly in main function.
Without changing your algorithm:
for(i=2;i<=n/2;i++)
might be faster as:
for(i=2, m=n/2; i<=m; ++i)
you only calculate the end value once, and preincrement doesn' compute an intermediate value like the post increment does.
However, with decent compiler optimizations, both of these will already be done.
Without looking at the generate assembly, it is hard to do any aggressive optimization.

dividing two array elements

main()
{
int prime_array[2339],prime1_count=0,mul1_count=0;
int i, prime, lim_up, lim_low, n,j=0;
int mul,count=0;
int mul_count[65026]={0},number[7096];
printf("\n ENTER THE LOWER LIMIT…: ");
scanf("%d", &lim_low);
printf("\n ENTER THE UPPER LIMIT…: ");
scanf("%d", &lim_up);
for(n=lim_low+1; n<lim_up; n++)
{
prime = 1;
for(i=2; i<n; i++)
if(n%i == 0)
{
prime = 0;
break;
}
if(prime)
{
prime_array[j]=n;
j++;
}
}
for(i=1;i<=255;i++)
{
for(j=1;j<=255;j++)
{
mul = j*i;
mul_count[mul]++;
}
}
for(i=1;i<=65025;i++)
if( mul_count[i]!=2 && mul_count[i]!=0 )
{
number[count]=i;
count++;
}
for(prime1_count=0;prime1_count<2339;prime1_count++)
{
printf("\nprime number used is:%d",prime_array[prime1_count]);
for(mul1_count=0;mul1_count<7096;mul1_count++)
{
printf("\n%d\t",number[mul1_count] % prime_array[prime1_count]);
}
}
}
I want to find the modulus of (number[mul1_count] % prime_array[prime1_count] ), but the output which I get is wrong. What is the mistake here. The prime number should be in the range 40000 to 65025. What changes should i make here?
I don't really know what you are trying to do but when running your program I am getting a Floating Point Exception and thats because of the number[mul1_count] % prime_array[prime1_count] when prime_array[prime1_count] is 0
Wrap your inner for loop with an if(prime_array[prime1_count] != 0)
for(prime1_count=0;prime1_count<2339;prime1_count++)
{
if(prime_array[prime1_count] != 0)
{
printf("\nprime number used is:%d",prime_array[prime1_count]);
for(mul1_count=0;mul1_count<7096;mul1_count++)
{
printf("\n%d\t",number[mul1_count] % prime_array[prime1_count]);
}
}
}
It would be good to also try to explain what you want to do, what you expect, what you get, etc...
Edit :
Also, as a sidenote. You should slightly change the loop which calculates the prime numbers. The reason is that you do not keep track of how many prime numbers you calculated. and then you
for(prime1_count=0;prime1_count<2339;prime1_count++)
iterate through the whole prime_array[].
Imagine the situation where you only calculated 5 prime numbers, this means that the remaining array is left with whatever. No reason to do the extra calculation, leaving asside that the prime_array is not initialized to zero nowhere in the code which means it (afaik) contains garbage value, in the indeces where no prime number was allocated with your algorithm. This means that the
if(prime_array[prime1_count] != 0)
will probably fail if you think that garbage value exist there.
Either initialize the prime_array[2339] = { 0 };
OR
I would do that :
int number_of_primes=0;
for(n=lim_low+1; n<lim_up; n++)
{
prime = 1;
for(i=2; i<n; i++)
if(n%i == 0)
{
prime = 0;
break;
}
if(prime)
{
if(number_of_primes < 2338)
{
prime_array[number_of_primes]=n;
number_of_primes++;
}else
{
break;
}
}
}
....
for(prime1_count=0 ; prime1_count < number_of_primes+1 ; prime1_count++)
{
printf("\nprime number used is:%d",prime_array[prime1_count]);
for(mul1_count=0;mul1_count<7096;mul1_count++)
{
printf("\n%d\t",number[mul1_count] % prime_array[prime1_count]);
}
}

Resources