patterncMinor
Reverse an integer, find the absolute difference, then reverse again
Viewed 0 times
thereverseabsolutedifferencethenfindagaininteger
Problem
For one of my university assignments, we were asked to take an
$$ 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.
Example Input / Output
Notes / Concerns
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
largestAbsoluteDifferenceseems slimy me to (having to pass 0 to get the result).
- I've got in the habit of calling functions inside a
printfinstead of storing the value in a va
Solution
You write
The
The code in
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
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
-
Instead of defining
To get the magic numbers,
-
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
-
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:
To address your specific concerns:
1 Not that performance really matters here. What I'm pointing out is silliness more than a serious efficiency problem.
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 aprintf()call, is probably far more controversial.
- Your technique is arithmetically correct, but not recommended due to the
inputvariable 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.