## Perl Weekly Challenge 288: Closest Palindrome

These are some answers to the Week 288, Task 1, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

*Spoiler Alert:* This weekly challenge deadline is due in a few days from now (on September 29, 2024, at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

## Task 1: Closest Palindrome

*You are given a string, $str, which is an integer.*

*Write a script to find out the closest palindrome, not including itself. If there are more than one then return the smallest.*

The closest is defined as the absolute difference minimized between two integers.

*Example 1*

```
Input: $str = "123"
Output: "121"
```

*Example 2*

```
Input: $str = "2"
Output: "1"
There are two closest palindrome "1" and "3". Therefore we return the smallest "1".
```

*Example 3*

```
Input: $str = "1400"
Output: "1441"
```

*Example 4*

```
Input: $str = "1001"
Output: "999"
```

### Closest Palindrome in Raku

To find if a number is a palindrome, we simply flip it and check whether the result is equal to the original number. We start with a *gap* equal to 1, and check whether the original number minus the gap is a palindrome or whether the original number plus the gap is a palindrome. If any is a palindrome, we return it to the caller. If not, we continue with a gap of 2, and then 3, 4, etc.

```
sub closest-palindrome ($in) {
for 1..Inf -> $i {
return $in - $i if ($in - $i).flip eq $in - $i;
return $in + $i if ($in + $i).flip eq $in + $i;
}
}
my @tests = 123, 2, 1400, 1001;
for @tests -> $test {
printf "%-6d => ", $test;
say closest-palindrome $test;
}
```

This program displays the following output:

```
$ raku ./closest-palindrome.raku
123 => 121
2 => 1
1400 => 1441
1001 => 999
```

### Closest Palindrome in Raku

This is a port to Perl of the above Raku program. Please see the previous section if you need further explanation. The equivalent of `flip`

in Perl is `reverse`

(in scalar context).

```
use strict;
use warnings;
use feature 'say';
sub closest_palindrome {
my $in = shift;
my $i = 1;
while (1) {
return $in - $i if reverse($in - $i) eq $in - $i;
return $in + $i if reverse($in + $i) eq $in + $i;
$i++;
}
}
my @tests = (123, 2, 1400, 1001);
for my $test (@tests) {
printf "%-6d => ", $test;
say closest_palindrome $test;
}
```

This program displays the following output:

```
$ perl ./closest-palindrome.pl
123 => 121
2 => 1
1400 => 1441
1001 => 999
```

## Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on October 6, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.

## Leave a comment