Search code examples
cnumbersconcatenationsquare

Square every digit of a number and concatenate them as a number using C (Program isn't dealing with 0 properly)


So i was asked to square every digit of the number and concatenate them and return as a number using C. But for some reason I am having problems dealing with 0 as digit and implement it in my algorithm. For example: when n = 3210987654, expected 9410816449362516, but got 941816449362516.

#include<math.h>
unsigned long long square_digits(unsigned n) {
    unsigned long long result = 0;
    int k = 0;
    int digits = (int)log10(n) + 1;
    for (int d = 0; d < digits; d++) {
        int digit = n % 10;
        int squared = digit * digit;
        n /= 10;
        if (d == 0) {
            result += squared * pow(10, k);
        }
        else {
            if (digit == 0) {
                k++;
            } 
            else if (digit < 4) {
                k++;
                result += squared * pow(10, k);
            } 
            else {
                k += 2;
                result += squared * pow(10, k);
            }
        }
    }
    return result;
}

So what i tried to do i use a variable k which will work as the power over 10 and function according to amount of digits needed to concatinate a squared digit. for the very first digit i kept it simple as i didn't change the value of k. and for others i checked first if the digits square takes 2 digits or not. if it takes then each time i have to increase power twice and once for single digit square. And as for digit 0, i can't multiply or concatinate accordingly instead i just move one step left by increasing the power. according to my hypothesis this should work perfectly but this isn't working right as it's having problem dealing with 0's in middle of the number.

For example: for n = 3210987654, expected 9410816449362516, but got 941816449362516


Solution

  • To address the manipulation of large numbers like this is often best done by evaluating the number as a string as is often done with large numbers such as credit card numbers. Once the number is converted to a string, each digit can be individually processed as necessary for the problem scenario. With that, following is a refactored version of the digit squaring function along with a test harness in the "main" function.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    unsigned long long square_digits(long long n)
    {
        char work[32];
        long long x = 1;
        long long result = 0;
    
        sprintf(work, "%lld", n);                               /* Store value in a string          */
    
        for (int i = (strlen(work) - 1); i >= 0; i--)           /* Evaluate each digit character    */
        {
            result += (work[i] - '0') * (work[i] - '0') * x;    /* Square the digit value and multiply by a succesive power of 10   */
    
            x *= 10;
    
            if (work[i] > '3')                                  /* Increase multiplier by 10 again for a two digit square           */
                x *= 10;
        }
    
        return result;
    }
    
    int main()
    {
        long long i;
    
        printf("Enter a value: ");
        scanf("%lld", &i);
    
        printf("Result for %lld is %lld\n", i, square_digits(i));
        return 0;
    }
    

    Following are the key points.

    • The integer value to be evaluated is converted into a string value.
    • Starting with the first digit, each character is squared and then multiplied by a work variable which is successively increased in value by either "10" or "100" depending upon the size of the squared digit which will accommodate encountering a "0".
    • Once all digits have been evaluated the result is returned

    Testing out this refactored code with your example, the following terminal output was created.

    craig@Vera:~/C_Programs/Console/SquareInt/bin/Release$ ./SquareInt 
    Enter a value: 3210987654
    Result for 3210987654 is 9410816449362516
    

    Go ahead and evaluate this possible route.