Perl weekly challenge 95

Palindromic numbers

You are given a number $N. Write a script to figure out if the given number is Palindrome. Print 1 if true otherwise 0.

There is an easy solution to this - to use "reverse" in string context to reverse the number and comparing the two strings:


sub is_palindrome_rev {
  return ( $_[0] eq reverse $_[0]) ? 1 : 0;
}

But this just seems a touch too easy - so let's see if we can find an alternative solution. Something that will potentially work in any base - not just base 10!


sub is_palindrome_array {
  my($n,$radix) = @_;
  $radix||=10;
  return 0 if $n < 0;
  my @digits  = $n%$radix;
  push @digits, $n%$radix while $n = int ($n/$radix);
  while( @digits>1 ) {
    return 0 if shift @digits != pop @digits;
  }
  return 1;
}
  • Bail out if the number is negative;
  • Chop the number of digits (in our "base").
    • Push the number (module the radix) onto an array of digits, repeatedly dividing by the radix until we have nothing left.
    • Technically this returns the digits in the reverse order (push is more efficient than unshift), but as we are interested in palindromes that isn't an issue.
  • Then we work through the array and seeing if the first and last digits are the same {if the array has only 1 entry then the first and the last digits are the same!}. Use pop/shift to return the numbers and take them from the array...

Stack

This is a simple case of creating a Stack object - basic OO coding. As this is a stack though we don't need to use a hashref as we would normally use - we can just bless an arrayref

Just a few notes on this one - mainly about good practice

  • We wish to use the standard names push/pop for the stack - but these are built-ins for clarity in the code we use CORE::push & CORE::pop to make certain we are using the built-in push and pop commands
  • Care needs to be taken as we may have an empty stack when making calls so should check for this in cases such as pop/min/top...

You can see my code on github at:

  • https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-095/james-smith/

2 Comments

Your initial function can be simplified further.

sub is_palindrome_rev {
  $_[0] eq reverse $_[0]
}

Any time you have something like:

if ( X ) {
  return true;
}
else {
  return false;
}

That should trigger your code smell senses. You can just replace it with:

return X;

Also, I'm not sure why you think this only works for base 10. It works for binary, octal, etc. If you lowercase everything, it'll work just fine for hexadecimal too.

Leave a comment

About James Curtis-Smith

user-pic Perl developer for nearly 30 years now, mainly in maintenance scripts and web pages, using mod_perl. I also code a lot in PHP (20+yrs), and also extensive experience in HTML (27+yrs), Javascript(25+yrs), CSS (24+yrs) and SASS.