kaprekar number calculation fails for more than two digits - c

why is the code not working? i cant get a valid output. Please help me to find whether the input is a Kaprekar number or not.I think i made it too complicated. Any suggestions for a simple method??
For example:
9 is a Kaprekar number since 9² = 81 & 8+1=9.
297 is a Kaprekar number since 297² = 88209 & 88+209 = 297. Below is the code.
Here is the code:
#include <stdio.h>
int main() {
int n, a, temp, length, sum = 0, s, i, rem, temp1, length1, sum1[10], sum2[10];
printf("n");
scanf("%d", &n);
a = n * n;
printf("%d\n", a);
temp = a;
length = 0;
while (temp > 0) {
length++;
temp = temp / 10;
}
temp1 = n;
length1 = 0;
while (temp1 > 0) {
length1++;
temp1 = temp1 / 10;
}
if (length1 == 1) {
for (i = 0; i < length; i++) {
rem = a % 10;
sum = sum + rem;
a = a / 10;
}
if (sum == n) {
printf("Kaprekar number");
} else {
printf("not a kaprekar number");
}
}
if (length1 > 1) {
s = length / 2;
for (i = 0; i < s; i++) {
printf("%d\n", sum1[i]);
}
for (i = s; i < length; i++) {
printf("%d\n", sum2[i]);
}
for (i = 0; i < length; i++) {
sum3[i] = sum1[i] + sum2[i];
}
}
return 0;
}

Here's my suggestion to simplify your code, and hopefully make it easier to debug.
Define a function that returns the number of digits.
Define a function that divides the square into to numbers, given the number of digits in the original number.
Compute the sum of the divided parts of the square and compare it with the original number.
int getNumberOfDigits(int n)
{
if ( n == 0 )
{
return 1;
}
int count = 0;
while ( n / 10 > 0 )
{
n /= 10;
++count;
}
return count;
}
void divideSquare(int square, int originalDigitCount, int out[2])
{
int left = square;
int right = 0;
for ( int = 0; i < originalDigitCount; ++i )
{
right = right*10 + left%10;
left /= 10;
}
out[0] = left;
out[1] = right;
}
int main()
{
for (int n = 0; n < 10000; ++n )
{
int square = n * n;
int out[2];
int count = getNumberOfDigits(n);
divideSquare(square, count, out);
if ( out[0] + out[1] == n )
{
printf("%d is a Kaprekar number\n", n);
}
}
}

According to this Wikipedia article, Kaprekar numbers are defined this way:
In mathematics, a non-negative integer is called a Kaprekar number for a given base if the representation of its square in that base can be split into two parts that add up to the original number, with the proviso that the part formed from the low-order digits of the square must be non-zero, although it is allowed to include leading zeroes. For instance, 45 is a Kaprekar number, because 452 = 2025 and 20 + 25 = 45. The number 1 is Kaprekar in every base, because 12 = 01 in any base, and 0 + 1 = 1. Kaprekar numbers are named after D. R. Kaprekar.
Your method seems too complicated and broken beyond repair. Here is a simpler approach:
square the number. I would recommend using a larger type such as unsigned long long to avoid arithmetic overflow during this computation.
iterate in a loop, dividing the square by increasing powers of 10 until the dividend is smaller than 10. If the remainder is non zero and the sum of the quotient and dividend of the square divided by the power of 10 equals the original number, you have a Kaprekar number.
Here is a simple implementation:
#include <stdio.h>
int test_kaprekar(unsigned long long n) {
unsigned long long quo, rem, pow10, square = n * n;
int i;
for (i = 1, pow10 = 10;; i++, pow10 *= 10) {
quo = square / pow10;
rem = square % pow10;
if (quo + rem == n && rem != 0) {
printf("%llu is a Kaprekar number: %llu*%llu = %llu, %llu+%.*llu = %llu\n",
n, n, n, square, quo, i, rem, n);
return 1;
}
if (quo < 10)
break;
}
return 0;
}
int main() {
unsigned long long i, start = 0, stop = 4294967295, count = 0;
for (i = start; i <= stop; i++) {
count += test_kaprekar(i);
}
printf("%llu Kaprekar numbers between %llu and %llu\n", count, start, stop);
return 0;
}
Output:
1 is a Kaprekar number: 1*1 = 1, 0+1 = 1
9 is a Kaprekar number: 9*9 = 81, 8+1 = 9
45 is a Kaprekar number: 45*45 = 2025, 20+25 = 45
55 is a Kaprekar number: 55*55 = 3025, 30+25 = 55
99 is a Kaprekar number: 99*99 = 9801, 98+01 = 99
297 is a Kaprekar number: 297*297 = 88209, 88+209 = 297
703 is a Kaprekar number: 703*703 = 494209, 494+209 = 703
999 is a Kaprekar number: 999*999 = 998001, 998+001 = 999
2223 is a Kaprekar number: 2223*2223 = 4941729, 494+1729 = 2223
2728 is a Kaprekar number: 2728*2728 = 7441984, 744+1984 = 2728
4879 is a Kaprekar number: 4879*4879 = 23804641, 238+04641 = 4879
4950 is a Kaprekar number: 4950*4950 = 24502500, 2450+2500 = 4950
5050 is a Kaprekar number: 5050*5050 = 25502500, 2550+2500 = 5050
5292 is a Kaprekar number: 5292*5292 = 28005264, 28+005264 = 5292
7272 is a Kaprekar number: 7272*7272 = 52881984, 5288+1984 = 7272
7777 is a Kaprekar number: 7777*7777 = 60481729, 6048+1729 = 7777
9999 is a Kaprekar number: 9999*9999 = 99980001, 9998+0001 = 9999
17344 is a Kaprekar number: 17344*17344 = 300814336, 3008+14336 = 17344
22222 is a Kaprekar number: 22222*22222 = 493817284, 4938+17284 = 22222
38962 is a Kaprekar number: 38962*38962 = 1518037444, 1518+037444 = 38962
77778 is a Kaprekar number: 77778*77778 = 6049417284, 60494+17284 = 77778
82656 is a Kaprekar number: 82656*82656 = 6832014336, 68320+14336 = 82656
95121 is a Kaprekar number: 95121*95121 = 9048004641, 90480+04641 = 95121
99999 is a Kaprekar number: 99999*99999 = 9999800001, 99998+00001 = 99999
...
86358636 is a Kaprekar number: 86358636*86358636 = 7457814011780496, 74578140+11780496 = 86358636
88888888 is a Kaprekar number: 88888888*88888888 = 7901234409876544, 79012344+09876544 = 88888888
91838088 is a Kaprekar number: 91838088*91838088 = 8434234407495744, 84342344+07495744 = 91838088
94520547 is a Kaprekar number: 94520547*94520547 = 8934133805179209, 89341338+05179209 = 94520547
99999999 is a Kaprekar number: 99999999*99999999 = 9999999800000001, 99999998+00000001 = 99999999
234567901 is a Kaprekar number: 234567901*234567901 = 55022100179545801, 55022100+179545801 = 234567901
243902440 is a Kaprekar number: 243902440*243902440 = 59488400237953600, 5948840+0237953600 = 243902440
332999667 is a Kaprekar number: 332999667*332999667 = 110888778222110889, 110888778+222110889 = 332999667
432432432 is a Kaprekar number: 432432432*432432432 = 186997808245434624, 186997808+245434624 = 432432432
567567568 is a Kaprekar number: 567567568*567567568 = 322132944245434624, 322132944+245434624 = 567567568
665188470 is a Kaprekar number: 665188470*665188470 = 442475700620940900, 44247570+0620940900 = 665188470
667000333 is a Kaprekar number: 667000333*667000333 = 444889444222110889, 444889444+222110889 = 667000333
765432099 is a Kaprekar number: 765432099*765432099 = 585886298179545801, 585886298+179545801 = 765432099
867208672 is a Kaprekar number: 867208672*867208672 = 752050880792003584, 75205088+0792003584 = 867208672
909090909 is a Kaprekar number: 909090909*909090909 = 826446280826446281, 82644628+0826446281 = 909090909
999999999 is a Kaprekar number: 999999999*999999999 = 999999998000000001, 999999998+000000001 = 999999999
1111111111 is a Kaprekar number: 1111111111*1111111111 = 1234567900987654321, 123456790+0987654321 = 1111111111
1776299581 is a Kaprekar number: 1776299581*1776299581 = 3155240201460775561, 315524020+1460775561 = 1776299581
2020202020 is a Kaprekar number: 2020202020*2020202020 = 4081216201612080400, 408121620+1612080400 = 2020202020
2646002646 is a Kaprekar number: 2646002646*2646002646 = 7001330002639001316, 7001330+002639001316 = 2646002646
3846956652 is a Kaprekar number: 3846956652*3846956652 = 14799075482367049104, 1479907548+2367049104 = 3846956652
3888938889 is a Kaprekar number: 3888938889*3888938889 = 15123845682376554321, 1512384568+2376554321 = 3888938889
4090859091 is a Kaprekar number: 4090859091*4090859091 = 16735128102417346281, 1673512810+2417346281 = 4090859091
4132841328 is a Kaprekar number: 4132841328*4132841328 = 17080377442424803584, 1708037744+2424803584 = 4132841328
110 Kaprekar numbers between 0 and 4294967295
All powers of 10 minus 1 are Kaprekar numbers in base 10, other Kaprekar numbers are quite rare around log10(n) between 10n and 10n+1.

There are a few mistakes with your code, for once you haven't initialized arrays of sum1 and sum2 which you use for printing and adding. secondly, array sum3[] isn't defined. also if your numbers are more than 2,147,483,647 which means you get an overflow if a is more than about 46340.
I was interested in the problem, so here's my implementation
#include <stdio.h>
#include <math.h>
int get_length(long long n){
int s = 0;
while (n>0){
s++;
n /= 10;
}
return s;
}
int is_kaprekar (long long n){
long long t, n2=n*n;
int i,s = get_length(n2);
t = pow(10,s);
for (i=0 ; i<s ; i++){
long long left,right;
left = n2/t;
right = n2%t;
if ((long long)(left+right) == n && left != t){
printf("%lld\n",n); // print n
printf("%lld\n",n2); // print n^2
printf("%lld\n",left);
printf("%lld\n",right);
printf("Kaprekar number\n");
return 1;
}
t/=10;
}
printf("not a kaprekar number");
return 0;
}
int main()
{
long long n,i,n2;
printf("n ");
scanf("%d",&n); // get n
is_kaprekar(n);
return 0;
}

Related

finding out if all the digits of a number are equal

So I want to start by saying that I already solved the problem, but there is something that is bugging me,
Here is the code first:
#include <stdio.h>
int flag = 1;
int controlNumber(int);
int main() {
int array[10] = { 233, 45, 777, 81, 999999, 36, 90, 88, 11, 61 };
int i;
int c;
for (i = 0; i < 10; i++) {
printf("%d >> ", array[i]);
c = controlNumber(array[i]);
if (c == 1) {
printf("all digits are equal\n");
} else {
printf("not all digits are equal\n");
}
}
return 0;
}
int controlNumber(int a) {
int q = a;
int r = a % 10;
int temp;
while (q != 0) {
temp = q % 10;
if (temp == r) {
q = q / 10;
} else {
flag = 0;
return flag;
}
}
return flag;
}
The code works only if the global variable flag is made local inside the scope of the function controlNumber with a value of 1, and I can't really figure out why that is the case since the logic should still be the same.
Also, I'm still a beginner to some extend so I apologize for any indentation errors.
For starters it is a very bad idea to define a function that depends on a global variable. In fact it is the reason of the bug of your program. You forgot to reset the global variable flag to 1 each time before calling the function.
The function can be defined the following way without any redundant global variable
int controlNumber( int n )
{
const int Base = 10;
int digit = n % Base;
while ( ( n /= Base ) && ( n % Base == digit ) );
return n == 0;
}
Here is a demonstrative program.
#include <stdio.h>
int controlNumber( int n )
{
const int Base = 10;
int digit = n % Base;
while ( ( n /= Base ) && ( n % Base == digit ) );
return n == 0;
}
int main(void)
{
int array[] = { 233, 45, 777, 81, 999999, 36, 90, 88, 11, 61 };
const size_t N = sizeof( array ) / sizeof( *array );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d >> ", array[i] );
if ( controlNumber( array[i] ) )
{
printf( "all digits are equal\n");
}
else
{
printf( "not all digits are equal\n" );
}
}
return 0;
}
The program output is
233 >> not all digits are equal
45 >> not all digits are equal
777 >> all digits are equal
81 >> not all digits are equal
999999 >> all digits are equal
36 >> not all digits are equal
90 >> not all digits are equal
88 >> all digits are equal
11 >> all digits are equal
61 >> not all digits are equal
If for example you will change the constant Base in the function and make it equal to 8
int controlNumber( int n )
{
const int Base = 8; //10;
int digit = n % Base;
while ( ( n /= Base ) && ( n % Base == digit ) );
return n == 0;
}
then you will get the following result.
233 >> not all digits are equal
45 >> all digits are equal
777 >> not all digits are equal
81 >> not all digits are equal
999999 >> not all digits are equal
36 >> all digits are equal
90 >> not all digits are equal
88 >> not all digits are equal
11 >> not all digits are equal
61 >> not all digits are equal
In this case for example the number 45 has the same digits in the octal representation because in the octal representation the number is written like 055.
Global variables retain their value. In your case, if flag is global, once set to 0 (within controlNumber) it will keep that value. There is no other place in the code to make it 1 again.
Making it a local variable to the function will cause it to initialize to 1 every time the function is called.
Edit: if you want to have it as global, you could set it to 1 every time controlNumber returns 0, i.e., before or after printf("not all digits are equal\n");.

Exercise in C with loop statements: Write code to reverse numbers with do-while statement

I have a task (currently studying the loop statement so I'm in the beginner phase)that asks to make a program to reverse an integer number so it must have the do statement .
The output should be (example):
Enter a number: 4568
The reversal is: 8654
Please put in mind that since I'm following my book so far I've studied and know the very basics + selection and loop statements. I have very limited choices so no arrays.
The book suggests to make a do loop to divide repeatedly the number by 10 until it reaches 0 this is what I did so far (code not completed) :
int main(void)
{
int n,x;
printf("Enter a number: ");
scanf("%d", &n);
printf("The reversal is: ");
x = n % 10;
printf("%d",x); /*outputs the last number digit in the first place*/
do{
....
n /= 10; /* for example if I divide the number 56222 by ten the output would come out as
5622 562 56 5*/
....
}while (n!=0);
return 0;
}
I found a way to put the last digit in the first place as you can see but
I'm struggling to figure out how to reverse the rest of the numbers after dividing the number by 10 repeadetly with this very limited choices.
What should I put in the do statement?
Many thanks in advance .
int main(void)
{
int n,x;
printf("Enter a number: ");
scanf("%d", &n);
printf("The reversal is: ");
int rev = 0;
do{
x = n % 10;
rev = rev * 10 + x;
n /= 10;
}while (n!=0);
printf ("%d", rev);
return 0;
}
here you need a new integer rev whose value is 0 initially. Lets take
example of 432
n = 432
when you do x = n % 10 x = 2
so when you do rev = rev * 10 + x rev is 0 and value of rev will be 2
n /= 10 make n = 43
-->so in the next iteration
n = 43
x = n % 10 results in x = 3
rev value now is 2
so rev = rev * 10 + x results in 2 * 10 + 3
so rev = 23
n /= 10 results in n = 4
-->in the last iteration n = 4
x = n % 10 results in x = 4 rev value now is 23
so rev = rev * 10 + x results in 23 * 10 + 4 so rev = 234
n /= 10 results in n = 0
so when you print rev you get the answer 234 reverse of 432

I don't understand why my for loop gives an awkward output

unfortunately... I asked about exactly this question yesterday about another error, hopefully, I don't have those errors anymore but I still have this awkward output, like some sort of numbers depending on the array element like -4221565 or -4647963, etc... Until now I think that my array appending part works correctly, I tried that. But I guess something wrong about the -1 in the condition but I can't name it. For loop is also another place I would say ok. I am trying to solve this since 3.00 AM then procrastinate it, then tried it... And the deadline is 7.04.2020(TODAY) 22.00 so I am starting to getting crazy. Any help would be appreciated.Thanks.So this is the question(İnputs does not have to be 15 it can be up to 15):
You have to transport a maximum of 15 different loads from one port to another. The carrying capacity of a cargo ship, which will transport those loads, is 50 tons. Loads are enumerated and the information about the weight of every load is given as input.
Suppose that the weight of every load is smaller than or equal to 50 tons and greater than 0.
You will read the weight of every load from the input in a single line. Your input will end with a -1. You will print the number of trips necessary.
Sample Input:
50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 -1
Output:15
Input:
20 25 25 36 37 25 20 10 50 9 16 45 32 10 25 -1
Output:
11
Input:
14 16 50 10 10 19 45 40 32 24 25 47 10 12 25 -1
Output:
9
Input:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -1
Output:
3
Here is my code:
#include <stdio.h>
int main()
{ int w,i,sum,index;
int list[15];
w = 1;
index = 0;
do
{ scanf("%d",&w);
list[index] = w;
index++;
}while(w != -1);
sum = 0;
for(i = 0;i < 15;i++)
{
sum +=list[i];
}
sum = sum / 50;
printf("%d",sum);
return 0;
}
in your code you are passing boundaries of array -1 will be 16th element of array which wrong. you need at least int list[16];.
but your solution is wrong , you are divining loads to place them in cargo ship which judging by given input and output. for example if there are 30 and 10 in one ship you can't divide a 20 load to two 10 loads in order to place max of 50 ton in the ship.
what you need is :
consider a ship with 0 ton
add load to it while sum of load are lower or equal to 50
if with new load added sum of current ship goes upper than 50 counter_ship++ and then add that load to a new load.
int main(void) {
int w;
int sum = 0;
int ship_counter = 0;
scanf("%d", &w);
while (w != -1) {
if (sum + w > 50)
{
ship_counter++;
sum = 0;
}
sum += w;
scanf("%d", &w);
}
if (sum != 50)
ship_counter++;
printf("%d", ship_counter);
return 0;
}
You need to sort the array. Then you need to check against a threshold amount. If it surpasses that you add a container.
#include <stdio.h>
void swap(int* xp, int* yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
}
// Function to perform Selection Sort
void selectionSort(int arr[], int n)
{
int i, j, min_idx;
// One by one move boundary of unsorted subarray
for (i = 0; i < n - 2; i++) {
// Find the minimum element in unsorted array
min_idx = i;
for (j = i + 1; j < n-1; j++)
if (arr[j] < arr[min_idx])
min_idx = j;
// Swap the found minimum element
// with the first element
swap(&arr[min_idx], &arr[i]);
}
}
int main()
{ int w,i,sum,index;
int list[15];
w = 1;
index = 0;
do
{ scanf("%d",&w);
list[index] = w;
index++;
}while(w != -1);
selectionSort(list,index);
for (int i = 0; i < index; i++)
printf("%d ", list[i]);
printf("\n");
int ans=0;
int threshold=0;
for(int i=0; i<index; ++i){
if(threshold + list[i]<=50){
threshold+=list[i];
}
else {
threshold = list[i];
++ans;
}
}
ans++;
printf("%d", ans);
return 0;
}
Change the do-while loop to a while like this:
while(w != -1 && index < 15)
{ scanf("%d",&w);
list[index] = w;
index++;
}
This way you avoid writing beyond array's boundary.
Then, the condition of the for loop could be:
for(i = 0;i < index; i++)
(value of index comes from the previous loop, and it's only up to the next item of the last inserted).
So you 're summing up the items that actually had an input, not the whole array.
Of course you could do without an array, as others commented.
Hope that helps
Your code has several issues, and I didn´t felt well to improve what still got logical issues in it, so I do something I normally do not (because apparently you seem to be very stressed about that and you are in a hurry) and provide you my own version of how I did the task:
#include <stdio.h>
#define MAX_LOADS 15
#define MAX_CAP 50
int main()
{
int w[MAX_LOADS+1];
int trips = 0;
int i = 0;
int sum = 0;
int max = 0;
int loads = 0;
int rest = 0;
printf("Enter the Weights of the Loads:\n");
while(i < (MAX_LOADS + 1))
{
scanf(" %d",&w[i]);
printf(" ");
if(w[i] == -1)
{
break;
}
sum = sum + w[i];
loads++;
i++;
}
printf("\n");
printf("%d Loads have a weight of %d tons.\n", loads, sum);
if(sum <= MAX_CAP)
{
printf("The amount of needed trips are: 1");
}
else
{
for(int i = 0; i < loads; i++)
{
if(w[i] == MAX_CAP)
{
w[i] = 0;
trips++;
continue;
}
else if(w[i] < MAX_CAP && w[i] > 0)
{
rest = MAX_CAP - w[i];
w[i] = 0;
for(int j = 0; j < loads; j++)
{
if(i == j)
continue;
if(w[j] == rest)
{
w[j] = 0;
break;
}
else if(w[j] < rest && w[j] > 0)
{
rest = rest - w[j];
w[j] = 0;
}
if(rest == 0)
{
break;
}
}
trips++;
}
}
printf("The amount of needed trips are: %d", trips);
}
return 0;
}
Output / Execution 1:
Enter the Weights of the Loads:
10 20 40 -1
3 Loads have a weight of 70 tons.
The amount of needed trips are: 2
Output / Execution 2:
Enter the Weights of the Loads:
50 50 50 50 50 -1
5 Loads have a weight of 250 tons.
The amount of needed trips are: 5
Output / Execution 3:
Enter the Weights of the Loads:
10 10 10 10 10 -1
5 Loads have a weight of 50 tons.
The amount of needed trips are: 1
#include <stdio.h>
#define MAX_SIZE 15
int main()
{
/* Let's define variables here. */
int i=0,j=0 ;
int input;
int weights[MAX_SIZE];
int numberOfTrips = 0;
int sum = 0;
/* Inputs is taken here from usre, Max = 15 */
printf("Input:\n");
scanf("%d",&input);
while(input != -1){
if (i< MAX_SIZE){
if (input <= 50 && input>= 0){
weights[i] = input;
i = i +1;
} else printf("Wrong Input! \nPlease Enter value between 0 and 50\n");
}
else printf("You reach MAX_SIZE, please Enter -1 to see the Output");
scanf("%d",&input);
}
printf("\n");
/* We are going will count the number of trips necessary*/
if(input == -1){
if (weights[0] != 0){
/* Let's test the first value*/
numberOfTrips = numberOfTrips +1;
}
sum= weights[0];
for (j = 1; j<i; ++j){
sum = sum +weights[j];
if (sum>50){
numberOfTrips = numberOfTrips +1;
sum = weights[j];
}
}
}
/*Finally, let's print the output here.*/
printf("Output:\n");
printf("%d",numberOfTrips);
return 0;
}

C-greatest prime factor of a given number

I have written the following code to compute the greatest prime factor of a number supplied
through standard input but it is taking ages to execute.How can i reduce the execution time of the program?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
bool is_prime(unsigned long long num)
{
if (num == 0 || num == 1)
return false;
if (num == 2)
return true;
for (unsigned long long j = 2; j < num; j++)
if(num%j==0)
return false;
return true;
}
int main(void)
{
unsigned long long n,i;
printf("enter the number: ");
scanf("%llu",&n);
for(i=n-1;i>1;i--)
if((is_prime(i)) && n%i==0)
break;
printf("%llu\n",i);
return 0;
}
Number in the input is 600851475143.
bool is_prime(unsigned long long num)
{
if (num < 2) return false; /* Reject border cases */
if (num == 2) return true; /* Accept the largest even prime */
if ((num & (~1)) == num) return false; /* Reject all other evens */
unsigned long long limit = sqrt(num) + 1; /* Limit the range of the search */
for (unsigned long long j = 3; j < limit; j += 2) /* Loop through odds only */
if(num % j==0)
return false; /* Reject factors */
return true; /* No factors, hence it is prime */
}
Have fun...one function for all prime factors, one for maximum prime factor:
#include <stdio.h>
#include <stdlib.h>
typedef unsigned long long u64_t;
static size_t prime_factors(u64_t value, u64_t *array)
{
size_t n_factors = 0;
u64_t n = value;
u64_t i;
while (n % 2 == 0)
{
n /= 2;
//printf("Factor: %llu (n = %llu)\n", 2ULL, n);
array[n_factors++] = 2;
}
while (n % 3 == 0)
{
n /= 3;
//printf("Factor: %llu (n = %llu)\n", 3ULL, n);
array[n_factors++] = 3;
}
for (i = 6; (i - 1) * (i - 1) <= n; i += 6)
{
while (n % (i-1) == 0)
{
n /= (i-1);
//printf("Factor: %llu (n = %llu)\n", (i-1), n);
array[n_factors++] = (i-1);
}
while (n % (i+1) == 0)
{
n /= (i+1);
//printf("Factor: %llu (n = %llu)\n", (i+1), n);
array[n_factors++] = (i+1);
}
}
if (n != 1)
array[n_factors++] = n;
return n_factors;
}
static u64_t max_prime_factor(u64_t value)
{
u64_t n = value;
u64_t i;
u64_t max = n;
while (n % 2 == 0)
{
n /= 2;
//printf("Factor: %llu (n = %llu)\n", 2ULL, n);
max = 2;
}
while (n % 3 == 0)
{
n /= 3;
//printf("Factor: %llu (n = %llu)\n", 3ULL, n);
max = 3;
}
for (i = 6; (i - 1) * (i - 1) <= n; i += 6)
{
while (n % (i-1) == 0)
{
n /= (i-1);
//printf("Factor: %llu (n = %llu)\n", (i-1), n);
max = (i-1);
}
while (n % (i+1) == 0)
{
n /= (i+1);
//printf("Factor: %llu (n = %llu)\n", (i+1), n);
max = (i+1);
}
}
//printf("Max Factor = %llu\n", (n == 1) ? max : n);
return (n == 1) ? max : n;
}
static void print_factors(u64_t value, size_t n_factors, u64_t *factors)
{
printf("%20llu:", value);
int len = 21;
for (size_t i = 0; i < n_factors; i++)
{
if (len == 0)
len = printf("%.21s", "");
len += printf(" %llu", factors[i]);
if (len >= 60)
{
putchar('\n');
len = 0;
}
}
if (len > 0)
putchar('\n');
}
void builtin_tests(void)
{
u64_t tests[] =
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 25, 49, 63, 69, 71, 73, 825, 829, 1000, 6857, 73112,
731122, 7311229, 73112293, 731122935, 7311229357, 73112293571,
600851475143, 731122935711, 7311229357111,
18446744073709551610ULL, 18446744073709551611ULL,
18446744073709551612ULL, 18446744073709551613ULL,
18446744073709551614ULL, 18446744073709551615ULL,
};
u64_t factors[64];
for (size_t i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
{
u64_t max = max_prime_factor(tests[i]);
printf("%20llu -> Max Prime Factor = %llu\n", tests[i], max);
size_t n_factors = prime_factors(tests[i], factors);
print_factors(tests[i], n_factors, factors);
}
}
int main(int argc, char **argv)
{
if (argc == 1)
builtin_tests();
else
{
for (int i = 1; i < argc; i++)
{
u64_t factors[64];
u64_t value = strtoull(argv[i], 0, 0);
u64_t max = max_prime_factor(value);
printf("%20llu -> Max Prime Factor = %llu\n", value, max);
size_t n_factors = prime_factors(value, factors);
print_factors(value, n_factors, factors);
}
}
return 0;
}
Results
1 -> Max Prime Factor = 1
1:
2 -> Max Prime Factor = 2
2: 2
3 -> Max Prime Factor = 3
3: 3
4 -> Max Prime Factor = 2
4: 2 2
5 -> Max Prime Factor = 5
5: 5
6 -> Max Prime Factor = 3
6: 2 3
7 -> Max Prime Factor = 7
7: 7
8 -> Max Prime Factor = 2
8: 2 2 2
9 -> Max Prime Factor = 3
9: 3 3
10 -> Max Prime Factor = 5
10: 2 5
11 -> Max Prime Factor = 11
11: 11
12 -> Max Prime Factor = 3
12: 2 2 3
13 -> Max Prime Factor = 13
13: 13
14 -> Max Prime Factor = 7
14: 2 7
15 -> Max Prime Factor = 5
15: 3 5
16 -> Max Prime Factor = 2
16: 2 2 2 2
17 -> Max Prime Factor = 17
17: 17
18 -> Max Prime Factor = 3
18: 2 3 3
19 -> Max Prime Factor = 19
19: 19
20 -> Max Prime Factor = 5
20: 2 2 5
25 -> Max Prime Factor = 5
25: 5 5
49 -> Max Prime Factor = 7
49: 7 7
63 -> Max Prime Factor = 7
63: 3 3 7
69 -> Max Prime Factor = 23
69: 3 23
71 -> Max Prime Factor = 71
71: 71
73 -> Max Prime Factor = 73
73: 73
825 -> Max Prime Factor = 11
825: 3 5 5 11
829 -> Max Prime Factor = 829
829: 829
1000 -> Max Prime Factor = 5
1000: 2 2 2 5 5 5
6857 -> Max Prime Factor = 6857
6857: 6857
73112 -> Max Prime Factor = 37
73112: 2 2 2 13 19 37
731122 -> Max Prime Factor = 52223
731122: 2 7 52223
7311229 -> Max Prime Factor = 24953
7311229: 293 24953
73112293 -> Max Prime Factor = 880871
73112293: 83 880871
731122935 -> Max Prime Factor = 89107
731122935: 3 5 547 89107
7311229357 -> Max Prime Factor = 7311229357
7311229357: 7311229357
73112293571 -> Max Prime Factor = 8058227
73112293571: 43 211 8058227
600851475143 -> Max Prime Factor = 6857
600851475143: 71 839 1471 6857
731122935711 -> Max Prime Factor = 4973625413
731122935711: 3 7 7 4973625413
7311229357111 -> Max Prime Factor = 12939061
7311229357111: 547 1033 12939061
18446744073709551610 -> Max Prime Factor = 1504703107
18446744073709551610: 2 5 23 53301701 1504703107
18446744073709551611 -> Max Prime Factor = 287630261
18446744073709551611: 11 59 98818999 287630261
18446744073709551612 -> Max Prime Factor = 2147483647
18446744073709551612: 2 2 3 715827883 2147483647
18446744073709551613 -> Max Prime Factor = 364870227143809
18446744073709551613: 13 3889 364870227143809
18446744073709551614 -> Max Prime Factor = 649657
18446744073709551614: 2 7 7 73 127 337 92737 649657
18446744073709551615 -> Max Prime Factor = 6700417
18446744073709551615: 3 5 17 257 641 65537 6700417
The if statement in the loop in main() should check n%i==0 first so that non-factors are not checked for primeness. This alone makes the program over 200 times faster on all the numbers from 1 to 2000 on a simple test case I ran on a modern Intel CPU. The mod below just to main() (I broke it out into a function returning the largest prime factor) improves the speed significantly more. I also consider the number itself as a possible factor (not done in the original).
unsigned long long largest_prime_factor(unsigned long long n)
{
unsigned long long i,sqrtn,maxprime;
if (is_prime(n))
return(n);
sqrtn=(unsigned long long)sqrt((double)n);
maxprime=1;
for (i=2;i<=sqrtn;i++)
{
if (n%i==0)
{
unsigned long long f;
f=n/i;
if (is_prime(f))
return(f);
if (is_prime(i))
maxprime=i;
}
}
return(maxprime);
}
keeping the same logic you can reduce time by executing loop till sqrt(num) only.
because if it is not prime, there would be at least one divisor which is less then sqrt(num).
Let's take num is not prime. so for some 1< a < num, a*b = num.
so either a or b should be less than sqrt(num).
Hence your code be for is_prime should be changed to the one as follows
bool is_prime(unsigned long long num)
{
if (num == 0 || num == 1)
return false;
if (num == 2)
return true;
long long root_num = sqrt(num);
for (unsigned long long j = 2; j < root_num; j++)
if(num%j==0)
return false;
return true;
}
Now if you want to change your logic, then there is an algorithm called sieve method which finds all prime numbers which are less than given number. check this out Sieve Algorithm
Its better to start for loop from square root of number to 3,
again you can skip even numbers.
so that you can get answer within small time..

Count total number of digits from a given positive number without looping in C

How to count total number of digits from a given positive number without looping in C?
For integers, take the log10 of the number, round down, and add one.
TEST:
#include <math.h>
#include <stdio.h>
int
num_digits(unsigned long number)
{
return (int)(floor(log10((double)number)) + 1.0);
}
int
main(int argc, char **argv)
{
unsigned long test_numbers[] = {
1, 9, 10, 99, 100, 999, 1000, 9999, 10000, 99999, 100000, 999999,
123456789ul,
999999999ul,
0
};
unsigned long *ptr;
for(ptr = test_numbers; *ptr; ptr++)
{
printf("Number of digits in %lu: %d\n", *ptr, num_digits(*ptr));
}
return 0;
}
Output:
Number of digits in 1: 1
Number of digits in 9: 1
Number of digits in 10: 2
Number of digits in 99: 2
Number of digits in 100: 3
Number of digits in 999: 3
Number of digits in 1000: 4
Number of digits in 9999: 4
Number of digits in 10000: 5
Number of digits in 99999: 5
Number of digits in 100000: 6
Number of digits in 999999: 6
Number of digits in 123456789: 9
Number of digits in 999999999: 9
One possible solutions, assuming 16-bit integer values and logical expressions evaluating to 0 or 1. You could replace the conditions with (u > 99) ? 1 : 0 if you're worried about portability.
int digits( unsigned u)
{
return 1 + (u > 9) + (u > 99) + (u > 999) + (u > 9999);
}
Two solutions for you!
int digit_count(unsigned int n)
{
if (n < 10)
return 1;
else
return (1 + digit_count(n / 10));
}
and
unsigned int n = 50;
int i = 0;
HACK:
i++;
if (n < 10)
{
printf("Digits: %d\n", i);
}
else
{
n /= 10;
goto HACK;
}
Don't hate me for the last one :(
return snprintf(0, 0, "%d", num);

Resources