Inspired by Regexp to match IP address, I thought of golfing the smallest Perl expression (not necessarily a regular expression) that, when using strict and warnings, evaluates to true if $_ is a valid numeric IPv4 decimal address.

Those addresses can be:

    A single decimal number between 0 and 256 ** 4 - 1
    Two decimal numbers separated by a dot, the first between 0 and 255 and the second between 0 and 256 ** 3 - 1
    Three decimal numbers separated by a dot, the first two between 0 and 255 and the third between 0 and 65535
    The more usual four decimal numbers between 0 and 255 separated by a dot

Here is the first naive attempt to get the ball rolling. It's 24 + 39 + 54 + 64 = 181 characters, easy to beat!

Update: It looks like I didn't make myself clear, when I said "smallest expression" I meant "smallest valid Perl expression", I didn't mean "regular expression"

# 1 2 3 4 5 6 #234567890123456789012345678901234567890123456789012345678901234 (/^(\d+)$/&&$1<256**4)|| (/^(\d+)\.(\d+)$/&&$1<256&&$2<256**3)|| (/^(\d+)\.(\d+)\.(\d+)$/&&$1<256&&$2<256&&$3<256**2)|| (/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/&&$1<256&&$2<256&&$3<256&&$4<256)

Replies are listed 'Best First'.
Re: (Golf) Expression for matching numeric IP addresses
by BrowserUk (Patriarch) on Aug 06, 2004 at 18:12 UTC

    Not a regex, but it works fine for decimal encoded IPs.

    sub validIP{ use List::Util qw[ reduce ]; $a = $b; $_[0] =~ m[^[\d\.]+$] and 2**32 > reduce{ $a * 256 + ($b < 256 ? $b : 1e99) } reverse split '\.', $_[0] }

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re: (Golf) Expression for matching numeric IP addresses
by hv (Prior) on Aug 10, 2004 at 13:32 UTC

    Here's a different approach specifically for the 4-element dotted form:


    This requires perl-5.6.0 or later; extending it for the other forms becomes rather uglier:

    (eval"0.0.$_")=~/^\0\0(.|[\0-\xff]([\0-\x{ffffff}]|[\0-\xff]([\0-\x{ +ffff}]|[\0-\xff]{2})))\z/s

    Of course the usual caveats about eval apply, but this is golf ...


Re: (Golf) Expression for matching numeric IP addresses
by Aristotle (Chancellor) on Aug 06, 2004 at 21:47 UTC

    To be honest, I don't have the patience to do this manually, right now. A much more interesting problem would be writing a somewhat generic algorithm to create such regexes. I posted a regex generator for a closely related problem to the fun-with-perl list a while ago. Since adapting it to your question would take more fiddling than I currently have the stamina for, I'll simply outline the structure of the resulting regex (written in /x syntax for the purposes of this post):

    0* (?: 1\d? | 2 (?: [0-4]\d? | 5[0-5]? ) ) (?: (?: # since we got here, the first 1-3 digits formed a number +< 256 # so allow a dot \. # a near-copy of the surrounding regex goes here to match +next octet ) | # no dot matched: allow digit-only strings forming numbers up +to 2**32-1 # (and remember we might already have matched up to 3 digits!) # this bit needs adjusting to smaller ranges in the nested cop +ies )

    You can see that it's highly formulaic.

    It might make an interesting project to generalize a few numeral-matching pattern builders sufficiently to make them into a module (if such a thing doesn't already exist). I've built such regexen by hand often enough that I've gotten thoroughly sick of doing it; it's a nearly trivial but mind numbingly tedious task.

    Makeshifts last the longest.

Re: (Golf) Expression for matching numeric IP addresses
by naChoZ (Curate) on Aug 10, 2004 at 12:26 UTC

    For some interesting reading on this topic, you should probably check out the Don't Use Regular Expressions To Parse IP Addresses! node. It's quite detailed and informative.

    "A long habit of not thinking a thing wrong, gives it a superficial appearance of being right." -- Thomas Paine