aboutsummaryrefslogtreecommitdiff
path: root/challenge-095/jo-37/perl/ch-1.pl
blob: f3c19491d60d4d67702b3faeb6e5aeab974077eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/perl -s

use v5.16;
use Test2::V0;
use warnings FATAL => 'all';
use Scalar::Util 'looks_like_number';
use experimental 'signatures';

our ($tests, $examples, $verbose);

run_tests() if $tests || $examples;    # does not return

say(<<EOS), exit unless @ARGV;
usage: $0 [-examples] [-tests] [--] [string]

-examples
    run the examples from the challenge
 
-tests
    run some tests

-verbose
    print diagnostic information

string
    string to test if it represents a palindrome number

EOS

### Input and Output

my $ret = palindrome_number($ARGV[0]);

if ($verbose) {
    say "got $ARGV[0]" if $verbose;
    if (!defined $ret) {
        say 'is not a number';
    } else {
        say "has value ", 0 + $ARGV[0];
        if ($ret eq '') {
            say 'reverse value is not a number';
        } elsif ($ret) {
            say "is palindrome";
        } else {
            say "is not palindrome";
        }
    }
}

say 0 + !!$ret;

### Implementation

# The concept of "number palindromes" needs further specifications to be
# well defined because "palindromic" is a string property and there is no
# unique string representation of a number.  Following the examples I'll
# take the decimal representation of a number that has to form a palindrome.
# Though there seems to be some consensus on considering integer numbers
# only, *any* numeric value is allowed here.
#
# A string shall be considered as palindromic number, iff the
# transformation chain
#   numify->stringify->reverse->numify->stringify 
# resembles the input string. (All transformations from a Perl view.)
#
# This sub uses different false return values to signal the failed test:
# - undef for a non-numeric input string
# - the empty string for a non-numeric reversed numified input string
# - zero for a numeric forward and backward value that is not a palindrome
#   number
sub palindrome_number ($str) {
    return unless looks_like_number $str;
    my $reverse = reverse $str + 0;
    return '' unless looks_like_number $reverse;

    0 + ($str eq $reverse + 0);
}

### Examples and tests

sub run_tests {
    SKIP: {
        skip "examples" unless $examples;
        ok palindrome_number(1221), 'example 1: 1221 is palindrome';
        ok !palindrome_number(-101), 'example 2: -101 is not palindrome';
        ok !palindrome_number(90), 'example 3: 90 is not palindrome';
    }

    SKIP: {
        skip "tests" unless $tests;
        for my $str (qw(21e12 1.221e3 0012100 00121 0012.2100)) {
            ok !palindrome_number($str), "$str is not palindrome";
        }
        for my $str (qw(12.21 1221)) {
            ok palindrome_number($str), "$str is palindrome";
        }

        # specific return codes
        is palindrome_number('1O2O1'), U(), 'not a number';
        is palindrome_number('-101'), '', 'reverse not a number';
        is palindrome_number('1e-21'), '', 'reverse not a number';
        is palindrome_number('12327'), 0, 'not palindrome';
        is palindrome_number('+121.0'), 0, 'not palindrome';
        is palindrome_number('121'), 1, 'palindrome';

        # exotic cases: NaN vs. nan
        is palindrome_number('NaN'), 0, 'NaN is numeric';
        is palindrome_number('nan'), 1, 'possibly the strangest case';
    }

    done_testing;
    exit;
}