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

Reverse digits and add until a palindrome appears

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

Problem

The following code is a C solution to the following problem UVA 10018.


The Problem


The "reverse and add" method is simple: choose a number, reverse its
digits and add it to the original. If the sum is not a palindrome
(which means, it is not the same number from left to right and right
to left), repeat this procedure.


For example:

195 Initial number
591

786
687

1473
3741

5214
4125

9339 Resulting palindrome



In this particular case the palindrome 9339 appeared after the 4th
addition. This method leads to palindromes in a few step for almost
all of the integers. But there are interesting exceptions. 196 is the
first number for which no palindrome has been found. It is not proven
though, that there is no such a palindrome.


Task


You must write a program that give the resulting palindrome and the
number of iterations (additions) to compute the palindrome.


You might assume that all tests data on this problem:



  • will have an answer



  • will be computable with less than 1000 iterations (additions)



  • will yield a palindrome that is not greater than 4,294,967,295.





The Input


The first line will have a number N with the number of test cases, the
next N lines will have a number P to compute its palindrome.


The Output


For each of the N tests you will have to write a line with the
following data : minimum number of iterations (additions) to get to
the palindrome and the resulting palindrome itself separated by one
space.


Sample Input

3
195
265
750




Sample Output

4 9339
5 45254
3 6666


My solution is as follows:

```
#include

/ only works for unsigned longs /
unsigned long reverse(unsigned long original)
{
unsigned long number = original;
unsigned long reversed = 0;
unsigned long place = 1;
unsigned long i, q;

for(i = 1000000000; i > 0; i = i / 10) {

q = number / i;

if ((q > 0) || (reversed > 0)) {
reversed =

Solution

reverse()

Your reverse() function only works for numbers below 1010. Although that upper bound may be good enough to solve this particular challenge, it's not correct in general. (Keep in mind that the standard says that an unsigned long is at least 32 bits — possibly larger.)

Here is a simpler implementation that works in general:

unsigned long reverse(unsigned long original) {
    unsigned long reversed = 0;
    for (; original; original /= 10) {
        reversed = (10 * reversed) + (original % 10);
    }
    return reversed;
}


is_palindrome()

For every iteration, you end up calling reverse() twice: once to test whether a palindrome has appeared, and again to obtain the next number to add. You would be better off eliminating this function, and rolling the palindrome check into the reverse_add() loop itself.

reverse_add()

For clarity, I would rename the function to reverse_add_until_paindrome().

Conventionally, C functions are designed so that a status code is returned, and the data being manipulated are passed by reference. I recommend redesigning the interface so that it returns the number of iterations, as that is closer in spirit to a status code. The number itself can be passed by reference. Notice what happens then: it becomes an in-out parameter! The rationale for the convention makes itself apparent.

int reverse_add_until_palindrome(unsigned long *n) {
    int i;
    unsigned long rev;
    for (i = 0; (rev = reverse(*n)) != *n; i++) {
        *n += rev;
    }
    return i;
}


The problem statement guarantees that you will never be given a P that will require more than 1000 iterations. That's just for your information; I don't think you need to verify that fact. (If you do want to bail out, you should add code in main() to detect that the computation was aborted.)

main()

The way you try to use one scanf() to read both N and the Pi is awkward. Not only does that make the code less clear, it also imposes a penalty of an extra conditional on every subsequent loop. In addition, it's wrong: the format string for an int is "%d", whereas the format string for an unsigned long is "%lu".

You read n, but never make use of it. That works, I suppose. I prefer to use it to see whether all of the expected input was received.

#include 
#include 

int main() {
    int n;
    unsigned long p;

    if (1 != scanf("%d", &n)) {
        return EXIT_FAILURE;
    }
    while (n-- && scanf("%lu", &p)) {
        int iterations = reverse_add_until_palindrome(&p);
        printf("%d %lu\n", iterations, p);
    }
    return (n == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

Code Snippets

unsigned long reverse(unsigned long original) {
    unsigned long reversed = 0;
    for (; original; original /= 10) {
        reversed = (10 * reversed) + (original % 10);
    }
    return reversed;
}
int reverse_add_until_palindrome(unsigned long *n) {
    int i;
    unsigned long rev;
    for (i = 0; (rev = reverse(*n)) != *n; i++) {
        *n += rev;
    }
    return i;
}
#include <stdio.h>
#include <stdlib.h>

int main() {
    int n;
    unsigned long p;

    if (1 != scanf("%d", &n)) {
        return EXIT_FAILURE;
    }
    while (n-- && scanf("%lu", &p)) {
        int iterations = reverse_add_until_palindrome(&p);
        printf("%d %lu\n", iterations, p);
    }
    return (n == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

Context

StackExchange Code Review Q#121644, answer score: 6

Revisions (0)

No revisions yet.