HiveBrain v1.2.0
Get Started
← Back to all entries
patterncMinor

Reverse an integer, find the absolute difference, then reverse again

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thereverseabsolutedifferencethenfindagaininteger

Problem

For one of my university assignments, we were asked to take an unsigned int, reverse its digits, find the absolute difference between the original and reversed, then reverse that, and you receive the "Magic Number".

$$ R(\ \lvert R(A) - A\rvert\ )$$

where \$A\$ is a positive integer and \$R(n)\$ means reverse.

We were also asked to take multiple inputs at once and keep track of the largest absolute difference between all inputs.

#include 

// Reverse an unsigned integer
unsigned int reverseInteger(unsigned int input) {

    unsigned int output = 0;

    while (input != 0) { // Terminate when input is 0
        output = output * 10 + input % 10; // Can't use =* here, order of operations!
        input /= 10;
    }

    return output;
}

// Find the absolute differnece between a reversed number, then reverse the absolute difference
unsigned int generateMagicNumber(unsigned int input) {

    /* Find Absolute Difference */
    if (input  keep) ? (keep = input) : keep; // If the input is greater than the current, store the input. Else, keep the current.

}

int main() {

    int inputs;
    printf("Enter number of inputs: ");
    scanf("%d", &inputs);
    printf("Enter space separated: ");

    for (int i = 0; i < inputs; i++) {
        unsigned int num;
        scanf("%u", &num);

        if (i == 0) { printf("\nOutput: "); } // Append label only on first iteration

        printf("%u ", generateMagicNumber(num)); // Generate and print the magic number
    }

    printf("\nLargest Absolute Difference: %u\n", largestAbsoluteDifference(0)); // Must pass 0 into largestAbsoluteDifference

}


Example Input / Output

Enter number of inputs: 5
Enter space separated: 23 512 454 94 100

Output: 9 792 0 54 99
Largest Absolute Difference: 297


Notes / Concerns

  • The way I wrote the largestAbsoluteDifference seems slimy me to (having to pass 0 to get the result).



  • I've got in the habit of calling functions inside a printf instead of storing the value in a va

Solution

You write unsigned int enough times that it's probably worthwhile to typedef it, in caseunsigned int turns out to be too small. (Keep in mind that it is only guaranteed to go up to 65535.)

typedef unsigned int number;
#define NUMBER_FMT "%u"


The reverseInteger() function is fine. I'd rename it for clarity, then remove the superfluous comments.

/**
 * Reverse the digits of a number
 */
number reverseDigits(number input) {
    number output = 0;

    while (input != 0) {
        output = output * 10 + input % 10;
        input /= 10;
    }

    return output;
}


The code in generateMagicNumber() was really hard to follow. The call reverseInteger(input) appears five times in that function. One codepath has four of those calls, and the other has three. Not only is that suboptimal1, it's also confusing because the input refers to a different number each time even though they all look the same. Please avoid repurposing variables like that.

/**
 * The reverse of the absolute difference between a number and its reverse
 */
number magic(number input) {
    number rev = reverseDigits(input);
    number absDiffWithReverse = (rev > input) ? rev - input : input - rev;
    return reverseDigits(absDiffWithReverse);
}


The ugly part of the problem is the requirement to keep track of the largest \$\lvert R(A) - A \rvert\$. I see four unpalatable options:

-
As you have done, insert code inside generateMagicNumber() to capture the intermediate computational result.

The disadvantages are that you are doing this as a side-effect, and using static (or global) state. That kind of statefulness would become a maintenance headache on larger projects. You also had to use a funny hack of calling largestAbsoluteDifference(0) to read out the maximum.

-
Instead of defining generateMagicNumber(), define absDiffWithReverse() to calculate \$\lvert R(A) - A \rvert\$. Then, let main() be responsible for tracking the maximum of those.

To get the magic numbers, main() would need to finish the job by reversing them. It's a bit dissatisfying that, for a program whose primary purpose is to compute "magic numbers", there is no magic-number-computing function.

-
Define a function to compute both the magic number and the \$\lvert R(A) - A \rvert\$ intermediate result.

Since C only allows one return value, you could either return a struct with two numbers or pass back one of the values as an out-parameter. I find both techniques aesthetically unpleasing, especially since those two results can be trivially derived from each other.

-
Define a function to compute the magic number. To get the \$\lvert R(A) - A \rvert\$, reverse the magic number again.

As @MatthieuM has pointed out, reversing the digits twice could change the result, due to the possibility of trailing or leading zeroes.

I think I would prefer option 3:

number magic(number input, number *absDiffWithReverse) {
    number rev = reverseDigits(input);
    *absDiffWithReverse = (rev > input) ? rev - input : input - rev;
    return reverseDigits(*absDiffWithReverse);
}

number max(number a, number b) {
    return a > b ? a : b;
}

int main() {
    int inputs;
    printf("Enter number of inputs: ");
    scanf("%d", &inputs);
    printf("Enter space separated: ");

    number maxDiffRev = 0;
    for (int i = 0; i < inputs; i++) {
        number n, nMagic, absDiffRev;
        scanf(NUMBER_FMT, &n);
        // Print label only on first iteration
        if (i == 0) { printf("\nOutput: "); }

        nMagic = magic(n, *absDiffRev);
        printf(NUMBER_FMT " ", nMagic);
        maxDiffRev = max(maxDiffRev, *absDiffRev);
    }

    printf("\nLargest Absolute Difference: " NUMBER_FMT "\n", maxDiffRev);
}


To address your specific concerns:

  • Yes, calling largestAbsoluteDifference(0) to read the maximum is slimy. Ideally, static state should be avoided altogether.



  • Calling functions inside printf() calls is fine if they are pure functions with no side-effects. It's not as good a practice if the function being called has side-effects. I wouldn't worry about it in your case. What I wrote above, with a variable assignment inside a printf() call, is probably far more controversial.



  • Your technique is arithmetically correct, but not recommended due to the input variable shifting its meaning.



1 Not that performance really matters here. What I'm pointing out is silliness more than a serious efficiency problem.

Code Snippets

typedef unsigned int number;
#define NUMBER_FMT "%u"
/**
 * Reverse the digits of a number
 */
number reverseDigits(number input) {
    number output = 0;

    while (input != 0) {
        output = output * 10 + input % 10;
        input /= 10;
    }

    return output;
}
/**
 * The reverse of the absolute difference between a number and its reverse
 */
number magic(number input) {
    number rev = reverseDigits(input);
    number absDiffWithReverse = (rev > input) ? rev - input : input - rev;
    return reverseDigits(absDiffWithReverse);
}
number magic(number input, number *absDiffWithReverse) {
    number rev = reverseDigits(input);
    *absDiffWithReverse = (rev > input) ? rev - input : input - rev;
    return reverseDigits(*absDiffWithReverse);
}

number max(number a, number b) {
    return a > b ? a : b;
}

int main() {
    int inputs;
    printf("Enter number of inputs: ");
    scanf("%d", &inputs);
    printf("Enter space separated: ");

    number maxDiffRev = 0;
    for (int i = 0; i < inputs; i++) {
        number n, nMagic, absDiffRev;
        scanf(NUMBER_FMT, &n);
        // Print label only on first iteration
        if (i == 0) { printf("\nOutput: "); }

        nMagic = magic(n, *absDiffRev);
        printf(NUMBER_FMT " ", nMagic);
        maxDiffRev = max(maxDiffRev, *absDiffRev);
    }

    printf("\nLargest Absolute Difference: " NUMBER_FMT "\n", maxDiffRev);
}

Context

StackExchange Code Review Q#118119, answer score: 8

Revisions (0)

No revisions yet.