Your network scanning tool is annoyingly picky about input, and immediately crashes if you feed it an IPv4 address that contains improper characters or isn't properly formatted.

An IPv4 address is a 32-bit numeric address written as four numbers separated by periods. Each number can be zero to 255.

We need to write a tool to pre-validate the input to avoid those crashes, and our specific tool is picky: A valid format will look like a.b.c.d where a, b, c and d:

  • Can be a 0 or a natural number with no leading zeros.
  • Should be between 0 - 255 (inclusive).
  • Should not contain special symbols like +, -, ,, and others.
  • Should be decimal (base 10)

Input: A string

Output: Truthy or Falsey value (arbitrary values also accepted)

Test Cases:

Input            |  Output  |  Reason
                 |          |
- 1.160.10.240   |  true    |
- 192.001.32.47  |  false   |  (leading zeros present)
- 1.2.3.         |  false   |  (only three digits)
- 1.2.3          |  false   |  (only three digits)
- 0.00.10.255    |  false   |  (leading zeros present)
- 1.2.$.4        |  false   |  (only three digits and a special symbol present)
- 255.160.0.34   |  true    |
- .1.1.1         |  false   |  (only three digits)
- 1..1.1.1       |  false   |  (more than three periods)
- 1.1.1.-0       |  false   |  (special symbol present)
- .1.1.+1        |  false   |  (special symbol present)
- 1 1 1 1        |  false   |  (no periods)
- 1              |  false   |  (only one digit)
- 10.300.4.0     |  false   |  (value over 255)
- 10.4F.10.99    |  false   |  (invalid characters)
- fruit loops    |  false   |  (umm...)
- 1.2.3.4.5      |  false   |  (too many periods/numbers)
- 0.0.0.0        |  true    |
- 0.0 0.0.       |  false   |  (periods misplaced)
- 1.23..4        |  false   |  (a typo of 1.2.3.4)

This is , so fewest bytes will win!

Note for the users - if you want to add some more test-cases, you're welcomed (by suggesting an edit). But, please make sure that the test-cases don't repeat themselves! Thanks

  • 9
    Suggest testcases: 1.1.1.1.1, 1.1.1.1., .1.1.1, 1..1.1, 1..1.1.1, 1.1.1.0, 1.1.1.-0, 1.1.1.+1, 1.1.1.1E1, 1.1.1.256, 1.1.1.0x1, 255.255.255.255, 0.0.0.0, 'or 1=1--, <empty string>, 1 1 1 1, 1,1,1,1. – tsh Oct 22 at 9:11
  • 5
    Suggest adding test cases "1.2.3.4.5" (to rule out too long IPs) and "999.0.0.0" (to rule out too large IPs). – Triggernometry Oct 22 at 15:50
  • 3
    Possibly slightly picky, but you should probably refer to "IPv4 addresses" rather than "IP addresses" - or at least, mention somewhere that you just mean IPv4 addresses - otherwise 1234:5678::1 ought to be a valid IP address (whereas from the description it's clear that that's not intended :) – psmears Oct 23 at 15:51
  • 3
    @Criggie The premise isn't to actually check all real IP4 rules (like the ones you mentioned), it's to ensure that the input string doesn't crash some other (presumably badly written) app that only allows input in a very specific form. Also, we're not going to change the rules of a challenge that already has 30+ answers. – BradC Oct 23 at 19:03
  • 2
    @Criggie Worth noting that the RFC declares that "Addresses are fixed length of four octets". I think the fringe cases you're referencing are more specialized than this challenge. – Poke Oct 23 at 19:12

36 Answers 36

X86_64 machine code: 18 16 bytes

Edit: This answer doesn't quite work, as

  1. I am using inet_pton from the standard C libraries, which means I need the extern. I didn't include the extern in my byte count though.
  2. I used the red zone as a result for the actual address, but called a function which also could've used the red zone. It fortunately doesn't on my machine, but some odd standard library build might use it which could cause undefined behavior.

And yeah, the whole thing is pretty much being done by an already written function

Anyway, this is what I got: 48 89 fe 6a 02 5f 48 8d 54 24 80 e9 00 00 00 00

Assembly:

section .text
    extern inet_pton
    global ipIsValid

ipIsValid:
    mov rsi, rdi
    ;mov rdi, 2 ; change to 10 for ipv6
    push 2
    pop rdi ; thank you peter
    lea rdx, [rsp - 128]
    jmp inet_pton

Explanation:

Take a look at inet_pton(3). It takes a string IP address and puts it in a buffer you can use with struct sockaddr. It takes 3 arguments: the address family (AF_INET (ipv4), 2, or AF_INET6 (ipv6), 10), the ip address's string, and a pointer to the output. It returns 1 on success, 0 for an invalid address, or -1 for when the address family is neither AF_INET or AF_INET6 (which will never occur because I'm passing a constant to it).

So I simply move the string to the register for the second argument, set the first register to 2, and set the third register to the red zone (128 bytes below the stack pointer) since I don't care about the result. Then I can simply jmp to inet_pton and let that return straight to the caller!

I spun up this quick test program to test your cases:

#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/ip.h>

extern int ipIsValid(char *);

int main(){
    char *addresses[] = {
        "1.160.10.240",
        "192.001.32.47",
        "1.2.3.",
        "1.2.3",
        "0.00.10.255",
        "1.2.$.4",
        "255.160.0.34",
        ".1.1.1",
        "1..1.1.1",
        "1.1.1.-0",
        ".1.1.+1",
        "1 1 1 1",
        "1",
        "10.300.4.0",
        "10.4F.10.99",
        "fruit loops",
        "1.2.3.4.5",
        NULL
    };

    for(size_t i = 0; addresses[i] != NULL; ++i){
        printf("Address %s:\t%s\n", addresses[i],
            ipIsValid(addresses[i]) ? "true" : "false");
    }
    return 0;
}

Assemble with nasm -felf64 assembly.asm, compile with gcc -no-pie test.c assembly.o, and you'll get:

Address 1.160.10.240:   true
Address 192.001.32.47:  false
Address 1.2.3.: false
Address 1.2.3:  false
Address 0.00.10.255:    false
Address 1.2.$.4:    false
Address 255.160.0.34:   true
Address .1.1.1: false
Address 1..1.1.1:   false
Address 1.1.1.-0:   false
Address .1.1.+1:    false
Address 1 1 1 1:    false
Address 1:  false
Address 10.300.4.0: false
Address 10.4F.10.99:    false
Address fruit loops:    false
Address 1.2.3.4.5:  false

I could make this much smaller if the caller was supposed to pass AF_INET or AF_INET6 to the function

  • 4
    I love that you did this in asm. And the fact you explained it to those who might not understand it (as well as test code) is even better. Which is not to say that I could have done it in asm; far too many years have passed but I remember enough to see exactly what your explanation (and therefore process) is saying (does). Good work. – Pryftan Oct 23 at 13:17
  • 3
    e9 00 00 00 00 is a jmp near $+5, not a jmp inet_pton. If you provide opcode, you should include the including inet_pton part, not leave a blank – l4m2 Oct 23 at 16:58
  • 1
    15 bytes-TIO 32bit x86 – Logern Oct 23 at 17:26
  • 3
    you should include the extern in the answer title, since the program requires it and it is not available on all platforms. – qwr Oct 23 at 20:07
  • 1
    the "mov rdi,2" can be "push 2/pop rdi" for -2 bytes. Note also that the disassembly is wrong or the code is wrong. It's either "mov edi" (not rdi) or there's a prefix missing. – peter ferrie Oct 26 at 18:42

PHP, 39 36 bytes

<?=+!!filter_var($argv[1],275,5**9);

Try it online!

275 resembles the constant FILTER_VALIDATE_IP

5**9 is being used instead of the constant FILTER_FLAG_IPV4. This is sufficient, because 5**9 & FILTER_FLAG_IPV4 is truthy, which is exactly what PHP does in the background, as Benoit Esnard pointed out.

Here, filter_var returns the first argument, if it's a valid IPv4 address, or false if it's not. With +!!, we produce the output required by the challenge.

  • 3
    Using 5**9 instead of 1048576 saves 3 bytes here: PHP uses & to test the IPv4 / IPv6 flags, so any number between 1048576 and 2097151 is valid. – Benoit Esnard Oct 22 at 10:12
  • I hereby downvote your answer for being (basically) my answer: codegolf.stackexchange.com/a/174470/14732 which was written at 2018-10-22 09:17:34UTC while yours was written on 2018-10-22 09:21:55UTC. Even if I revert the 1-byte optimization given by @BenoitEsnard, my answer is exactly the same as yours in functionality. – Ismael Miguel Oct 22 at 15:06
  • 2
    I have to apologise, I didn't see your answer, though at the time I was composing it, there was no submission in PHP on this question (as you said, the time difference is less than five minutes). – oktupol Oct 22 at 15:16
  • I know, and I understand it. I only noticed yours just now. I can roll back mine, and you keep the optimization. But I don't know if it makes the answer be different enough from eachother. – Ismael Miguel Oct 22 at 15:33
  • 17
    @IsmaelMiguel I wouldn't downvote somebody for that if it's plausible yours wasn't there when they started. With a 5 minute difference, not only is it plausible, it's almost certainly the case, which is apparent even without the author saying so himself. – Duncan X Simpson Oct 22 at 17:47

Java (JDK), 63 bytes

s->("."+s).matches("(\\.(25[0-5]|(2[0-4]|1\\d|[1-9])?\\d)){4}")

Try it online!

Credits

JavaScript (Node.js), 46 bytes

x=>x.split`.`.every(t=>k--&&[t&255]==t,k=4)*!k

Try it online!

used Arnauld's part

JavaScript (Node.js), 54 53 51 bytes

x=>x.split`.`.every(t=>k--*0+t<256&[~~t]==t,k=4)*!k

Try it online!

-2B for 0+t<256, -1B from Patrick Stephansen, +1B to avoid input 1.1.1.1e-80

RegExp solution 58 bytes

s=>+/^(\.(25[0-5]|(2[0-4]|1\d|[1-9])?\d)){4}$/.test('.'+s)
  • I have added some test cases! – rv7 Oct 22 at 6:22
  • This gives truthy for 0.0.0.0. Everything else seems to work fine. – Kevin Cruijssen Oct 22 at 9:35
  • 1
    @KevinCruijssen 0.0.0.0 is here true one. Just why SQL injection is here? – l4m2 Oct 22 at 9:37
  • Ah wait, I misinterpret the sentence in the challenge description. 0.0.0.0 is indeed truthy. That will golf my answer as well.. (And what do you mean by SQL injection? :S The link is to TIO with ALL test cases.) – Kevin Cruijssen Oct 22 at 9:40
  • 1
    @l4m2 I added it since we need some testcases that even not looks like an IP address. – tsh Oct 22 at 9:45

PHP, 36 Bytes

echo(ip2long($argv[1])===false?0:1);

ip2long is a well-known built-in function.

  • 3
    29 bytes – nwellnhof Oct 22 at 10:53
  • This seems to use uncodumented features present in newer versions (I presume it is from PHP7+). Keep in mind that, for PHP 4 and 5, this does accept incomplete IPs. – Ismael Miguel Oct 22 at 15:10
  • 27 bytes – Mark Oct 22 at 17:39
  • 1
    This will give success if you feed it any integer, such as 1 , 2 , etc. Don't think it should. And also if you feed it something as 100.100.100 – nl-x Oct 24 at 9:52

Perl 6, 22 21 20 bytes

-1 byte thanks to Phil H.

{?/^@(^256)**4%\.$/}

Try it online!

Explanation

{                  }  # Anonymous Block
  /               /   # Regex match
   ^             $    # Anchor to start/end
    @(    )           # Interpolate
      ^256            #   range 0..255,
                      #   effectively like (0|1|2|...|255)
           **4        # Repeated four times
              %\.     # Separated by dot
 ?                    # Convert match result to Bool
  • 3
    Man, I need to spend more time figuring out Perl 6's regexes. I had no either the % modifier existed. I wonder if it tries to checks all 256**4 possibilities? – Jo King Oct 22 at 10:57
  • Instead of <{^256}> you can just convert the range to an array @(^256) for -1 char TIO. By changing the code block to an array it also gets enormously faster (0.4s instead of >30). – Phil H Oct 25 at 13:37
  • @PhilH Cool, thanks. I tried $(^256) but now I realize why this didn't work. – nwellnhof Oct 25 at 15:11

05AB1E, 26 24 23 22 23 bytes

'.¡©g4Q₅Ý®å`®1šDïþJsJQP

-1 byte thanks to @Emigna.
+1 byte for bugfixing test case 1.1.1.1E1 incorrectly returning a truthy result.

Try it online or verify all test cases.

Explanation:

'.¡              '# Split the (implicit) input by "."
   ©              # Save it in the register (without popping)
    g4Q           # Check that there are exactly 4 numbers
    ₅Ý®å          # Check for each of the numbers that they are in the range [0,255],
        `         # and push the result for each number separated onto the stack
    ®1šDïþJsJQ    # Check that each number does NOT start with a "0" (excluding 0s itself),
                  # and that they consist of digits only
              P   # Check if all values on the stack are truthy (and output implicitly)
  • 1
    You should be able to use Ā instead of <d – Emigna Oct 22 at 9:14
  • @MagicOctopusUrn I'm afraid it fails for 1.1.1.1E1, 1..1.1.1, 1.1.1.1., 192.00.0.255, and 0.00.10.255. (PS: I've fixed the 1.1.1.1E1 by adding the þ to the join-and-equal check.) – Kevin Cruijssen Oct 22 at 12:32
  • Fair enough, figured I missed something. – Magic Octopus Urn Oct 22 at 12:33
  • @MagicOctopusUrn The main issue is 05AB1E seeing numbers with leading 0s equal to those without, even as string. Which is why I use the DïþJsJQ check where ï cast it to int to remove leading 0s, and þ only leaves digits removing things like E, -, etc. :) The is for test case 0.00.10.255, since 00010255 and 0010255 would be equal. – Kevin Cruijssen Oct 22 at 12:34
  • Yeah I went through the same nonsense, the reversal of all numbers worked pretty well though, except for those cases. Interesting when features beneficial for some problems become almost bug-like for others. – Magic Octopus Urn Oct 22 at 12:35

C (gcc) / POSIX, 26 bytes

f(s){s=inet_pton(2,s,&s);}

Try it online!

Works as 64-bit code on TIO but probably requires that sizeof(int) == sizeof(char*) on other platforms.

  • @TobySpeight Yes, if you're on x86, you should probably try in 32-bit mode (-m32). – nwellnhof Oct 22 at 13:23
  • I got it to work, by passing s as a char* (no access to a ILP32 system here), and yes, I was mixing up with inet_aton(). – Toby Speight Oct 22 at 13:26

Python 3: 81 78 70 69 66 bytes

['%d.%d.%d.%d'%(*x.to_bytes(4,'big'),)for x in range(16**8)].count

Loop over all possible IPv4 addresses, get the string representation and compare it to the input. It uh... takes a while to run.

EDIT: Removed 3 bytes by switching from full program to anonymous function.

EDIT2: Removed 8 bytes with help from xnor

EDIT3: Removed 1 byte by using an unpacked map instead of list comprehension

EDIT4: Removed 3 bytes by using list comprehension instead of the ipaddress module

  • 2
    I think your anonymous function can just be [str(ip_address(x))for x in range(256**4)].count. Also, 256**4 can be 16**8. – xnor Oct 22 at 23:45

Python 2, 85 82 81 bytes

-1 byte thanks to Kevin Cruijssen

from ipaddress import*
I=input()
try:r=I==str(IPv4Address(I))
except:r=0
print~~r

Try it online!

113 byte answer is deleted as it fails for 1.1.1.1e-80

  • 1
    You can golf print 1*r to print~~r. +1 though, since it seem to work for all possible test cases suggested thus far. PS: Your 113 byte answer fails for 1.1.1.1e-80. – Kevin Cruijssen Oct 22 at 10:52
  • @KevinCruijssen Thanks! Didn't think about such notation of numbers – Dead Possum Oct 22 at 11:11
  • Isn't ipaddress a Python 3 module? – Farhan.K Oct 24 at 12:55
  • @Farhan.K Dunno, but it works in TIO – Dead Possum Oct 24 at 13:51

Japt, 17 15 bytes

q.
ʶ4«Uk#ÿòs)Ê

Try it or run all test cases or verify additional test cases from challenge comments


Explanation

We split to an array on ., check that the length of that array is equal to 4 AND that the length when all elements in the range ["0","255"] are removed from it is falsey (0).

                 :Implicit input of string U
q.               :Split on "."
\n               :Reassign resulting array to U
Ê                :Length of U
 ¶4              :Equals 4?
   «             :&&!
    Uk           :Remove from U
      #ÿ         :  255
        ò        :  Range [0,255]
         s       :  Convert each to a string
          )      :End removal
           Ê     :Length of resulting array

PHP 7+, 37 35 32 bytes

This uses the builtin function filter_var, to validate that it is an IPv4 address.

For it to work, you need to pass the key i over a GET request.

<?=filter_var($_GET[i],275,5**9);

Will output nothing (for a falsy result) or the IP (for a truthy result), depending on the result.

You can try this on: http://sandbox.onlinephpfunctions.com/code/639c22281ea3ba753cf7431281486d8e6e66f68e http://sandbox.onlinephpfunctions.com/code/ff6aaeb2b2d0e0ac43f48125de0549320bc071b4


This uses the following values directly:

  • 275 = FILTER_VALIDATE_IP
  • 1<<20 = 1048576 = FILTER_FLAG_IPV4
  • 5**9 = 1953125 (which has the required bit as "1", for 1048576)

Thank you to Benoit Esnard for this tip that saved me 1 byte!

Thank you to Titus for reminding me of the changes to the challenge.


I've looked into using the function ip2long, but it works with non-complete IP addresses.

Non-complete IPv4 addresses are considered invalid in this challenge.

If they were allowed, this would be the final code (only for PHP 5.2.10):

<?=ip2long($_GET[i]);

Currently, it isn't explicit in the documentation that this will stop working (when passed an incomplete ip) with newer PHP versions.

After testing, confirmed that that was the case.

Thanks to nwellnhof for the tip!

  • Using 5**9 instead of 1<<20 saves one byte here: PHP uses & to test the IPv4 / IPv6 flags, so any number between 1048576 and 2097151 is valid. – Benoit Esnard Oct 22 at 10:09
  • In newer PHP versions, ip2long doesn't allow incomplete addresses. – nwellnhof Oct 22 at 10:46
  • @BenoitEsnard Thank you! I've added it to the answer – Ismael Miguel Oct 22 at 11:50
  • @nwellnhof After testing, I confirm that that is the case. However, I don't think it is a good idea to use it, since it isn't explicitly documented. – Ismael Miguel Oct 22 at 11:51
  • +!! is not required; the OP now accepts arbitrary truthy values. – Titus Oct 23 at 12:44

PowerShell, 59 51 49 bytes

-8 bytes, thanks @AdmBorkBork

-2 bytes, true or false allowed by author

try{"$args"-eq[IPAddress]::Parse($args)}catch{!1}

Test script:

$f = {

try{"$args"-eq[IPAddress]::Parse($args)}catch{!1}

}

@(
    ,("1.160.10.240" , $true)
    ,("192.001.32.47" , $false)
    ,("1.2.3." , $false)
    ,("1.2.3" , $false)
    ,("0.00.10.255" , $false)
    ,("192.168.1.1" , $true)
    ,("1.2.$.4" , $false)
    ,("255.160.0.34" , $true)
    ,(".1.1.1" , $false)
    ,("1..1.1.1" , $false)
    ,("1.1.1.-0" , $false)
    ,("1.1.1.+1" , $false)
    ,("1 1 1 1" , $false)
    ,("1"            ,$false)
    ,("10.300.4.0"   ,$false)
    ,("10.4F.10.99"  ,$false)
    ,("fruit loops"  ,$false)
    ,("1.2.3.4.5"    ,$false)

) | % {
    $s,$expected = $_
    $result = &$f $s
    "$($result-eq$expected): $result : $s"
}

Output:

True: True : 1.160.10.240
True: False : 192.001.32.47
True: False : 1.2.3.
True: False : 1.2.3
True: False : 0.00.10.255
True: True : 192.168.1.1
True: False : 1.2.$.4
True: True : 255.160.0.34
True: False : .1.1.1
True: False : 1..1.1.1
True: False : 1.1.1.-0
True: False : 1.1.1.+1
True: False : 1 1 1 1
True: False : 1
True: False : 10.300.4.0
True: False : 10.4F.10.99
True: False : fruit loops
True: False : 1.2.3.4.5

Explanation:

The script tries to parse an argument string, to construct a .NET object, IPAddress.

  • return $true if object created and the argument string is equal to a string representation of the object (normalized address by object.toString())
  • return $false otherwise

PowerShell, 59 56 bytes, 'don't use a .NET lib' alternative

-3 bytes, true or false allowed by author

".$args"-match'^(\.(25[0-5]|(2[0-4]|1\d|[1-9])?\d)){4}$'

Thanks @Olivier Grégoire for the regular expression.

  • 1
    You shouldn't need to call |% t*g since PowerShell will automatically cast the right-hand-side of -eq as a string, because the left-hand-side is a string. -- try{+("$args"-eq[IPAddress]::Parse($args))}catch{0} – AdmBorkBork Oct 22 at 16:05

Mathematica, 39 31 bytes

Original version:

¬FailureQ[Interpreter["IPAddress"][#]]&

Modified version (thanks to Misha Lavrov)

 AtomQ@*Interpreter["IPAddress"]

which returns True if the input is a valid IP address (try it).

In case you insist on getting 1 and 0 instead, then an additional 7 bytes would be necessary:

Boole/@AtomQ@*Interpreter["IPAddress"]
  • Since Interpreter["IPAddress"] returns a string for valid input, and some complicated failure object for invalid input, we can test for valid inputs with AtomQ[Interpreter["IPAddress"][#]]&, which can be further shortened to the function composition AtomQ@*Interpreter["IPAddress"]. Try it online! – Misha Lavrov Oct 22 at 17:45

JavaScript (ES6), 49 bytes

Returns a Boolean value.

s=>[0,1,2,3].map(i=>s.split`.`[i]&255).join`.`==s

Try it online!

Python 2, 93 89 67 53 bytes

[i==`int(i)&255`for i in input().split('.')]!=[1]*4>_

Try it online!

Thanks to Dennis for shaving another 14 bytes on the internal comparisons and exit code.

Special thanks to Jonathan Allan for shaving 22 bytes & a logic fix! Pesky try/except begone!

Taking properly formatted strings instead of raw bytes shaves off 4 bytes, thanks Jo King.

  • Your check can be golfed to i==`int(i)&255` . Also, you can force an error with [...]!=[1]*4>_, since you're using exit codes anyway. Try it online! – Dennis Oct 24 at 22:44
  • @Dennis I don't understand what >_ does. The bitwise and is quite ingenious though... I was unsuccessful in combining those myself. – TemporalWolf Oct 24 at 22:58
  • 2
    If the != returns False, Python short-circuits and nothing happens; the interpreter exits normally. If it returns True, >_ raises a NameError, because the variable _ is undefined. – Dennis Oct 24 at 23:00
  • Figures I chain comparisons in my answer and then miss the obvious result in your comment. Thanks for the explanation. – TemporalWolf Oct 24 at 23:13

Python3 Bash* 60

*Also other shells. Any one for which the truthy/falsy test passes on a program exit code

read I
python3 -c "from ipaddress import*;IPv4Address('$I')"

Explanation

The trouble with a pure Python solutions is that a program crashing is considered indeterminate. We could use a "lot" of code to convert an exception into a proper truthy/fasly value. However, at some point the Python interpreter handles this uncaught exception and returns a non-zero exit code. For the low-low cost of changing languages to your favourite Unix shell, we can save quite a bit of code!

Of course, this is vulnerable to injection attacks... Inputs such as 1.1.1.1'); print('Doing Something Evil are an unmitigated threat!

  • (Explanation it is (not Explaination).) – Peter Mortensen Oct 25 at 1:43
  • @PeterMortensen Yikes. It was even underlined in red. My browser tried to save me, but I wouldn't listen. Thanks for catching that! – Sompom Oct 25 at 14:50
  • Full programs are allowed to output via exit codes, therefore this could be 43 bytes. – BMO Nov 5 at 16:29
  • @BMO Interesting. Thanks for pointing that out! I think the problem definiiton changed from "Truthy/Falsy" to also allowing arbitrary output since I posted this, but I could have just not noticed before :) – Sompom Nov 5 at 16:40

C# (Visual C# Interactive Compiler), 84 bytes

s=>s.Count(c=>c==46)==3&!s.Split('.').Except(new int[256].Select((_,i)=>i+"")).Any()

Try it online!

The logic is to check if the number of dot is valid, then we generate a range from 0 to 255 and we verify that our ip is contained by the range.

# C# (Visual C# Interactive Compiler), 61 bytes

s=>s.Count(c=>c==46)==3&IPAddress.TryParse(s,out IPAddress i)

Try it online!

This is a work in progress. The code use System.Net (+17 bytes if you count it). if you wonder why I count and parse:

The limitation with IPAddress.TryParse method is that it verifies if a string could be converted to IP address, thus if it is supplied with a string value like "5", it consider it as "0.0.0.5".

source

As @milk said in comment, it will indeed fail on leading zeroes. So, the 61 bytes one is not working.

Red, 106 bytes

func[s][if error? try[t: load s][return off]if 4 <> length? t[return off]s =
form as-ipv4 t/1 t/2 t/3 t/4]

Try it online!

Returnd true or false

Explanation:

f: func [ s ] [
    if error? try [                  ; checks if the execution of the next block result in an error
        t: load s                    ; loading a string separated by '.' gives a tuple   
    ] [                              ; each part of which must be in the range 0..255
        return off                   ; if there's an error, return 'false' 
    ]
    if 4 <> length? t [              ; if the tuple doesn't have exactly 4 parts
        return off                   ; return 'false'  
    ]
    s = form as-ipv4 t/1 t/2 t/3 t/4 ; is the input equal to its parts converted to an IP adress
]

Stax, 14 bytes

∞n·Θ3ª&JH‼∙*~Γ

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

VB      constant 256
r       [0 .. 255]
'|*     coerce and string-join with "|"; i.e. "0|1|2|3 ... 254|255"
:{      parenthesize to "(0|1|2|3 ... 254|255)"
]4*     make 4-length array of number pattern
.\.*    string join with "\\."; this forms the complete regex
|Q      is the input a complete match for the regex?

Run this one

  • Surprised to know that you made the language Stax! it is working well. – rv7 Oct 22 at 17:14
  • Thanks! The space of golfing languages is surprisingly crowded, and I'm not sure if stax can justify its own existence on its merits, but my main goal was just to see if I could do it and maybe learn something. It ended up being more fun than expected. – recursive Oct 22 at 17:16

Python 3, 109 93 bytes

import re
lambda x:bool(re.match(r'^((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(\.(?!$)|$)){4}$',x))

Explanation

Each octet can be 0 - 255 :

  • starts with 25 and having 0-5 as last digit
  • start with 2, has 0-4 as second digit and any digit at the end
  • starts with 1, and 00 - 99 as rest digits
  • has only 2 digits - 1-9 being the first one and any digit thereafter
  • or just a single digit

An octet can end with a (.) or just end, with the condition that it cannot do both , the negative lookahead (?!$) takes care of this case

Thanks @Zachary for making me realize I can discard spaces (since it is code golf)
Thanks @DLosc for the improvements and making me realize my mistake, its been corrected now.

  • 2
    Some explanation for this might help. – Stephen Leppik Oct 22 at 12:04
  • x: re.match=>x:re.match; , x => ,x, and ) is => )is should save 3 bytes. Also, in the regex, you can use \d for each occurrence of [0-9], and [1]=>1. This seems like a great first post, though! – Zacharý Oct 22 at 14:08
  • [1-9][0-9]|[0-9] can become [1-9]\d|\d (per Zacharý's advice), which can become [1-9]?\d. Also, instead of testing re.match(...)is not None, you can do bool(re.match(...)) since match objects are truthy and None is falsey. :) – DLosc Oct 22 at 18:05
  • Hmm. Actually, this fails on the test case 1.2.3.4.5 (and also 1.2.3.4., which isn't in the official list of test cases), because it can match a period instead of end-of-string after the fourth number. – DLosc Oct 22 at 18:23

Charcoal, 45 21 bytes

I∧⁼№θ.³¬Φ⪪θ.¬№E²⁵⁶Iλι

Try it online! Link is to verbose version of code. Edit: Saved 24 bytes by porting @Shaggy's Japt answer. Explanation:

    θ                   Input string
   №                    Count occurrences of
     .                  Literal `.`
  ⁼                     Equal to
      ³                 Literal 3
 ∧                      Logical And
       ¬                Logical Not
          θ             Input string
         ⪪              Split on
           .            Literal `.`
        Φ               Filter by
            ¬           Logical Not
               ²⁵⁶      Literal 256
              E         Map over implicit range
                   λ    Map value
                  I     Cast to string
             №          Count occurrences of
                    ι   Filter value
I                       Cast to string
                        Implicitly print
  • Fails for test cases with negative integers like 123.-50.0.12 or 1.1.1.-80. Everything else seems to work fine. So the <256 check should be in [0,255] instead. – Kevin Cruijssen Oct 22 at 9:55
  • @KevinCruijssen Actually the code to filter out invalid characters wasn't working because I forgot to change the variable in the inner loop. Should be fixed now. – Neil Oct 22 at 12:21

Retina, 46 44 bytes

^
.
^(\.(25[0-5]|(2[0-4]|1\d|[1-9])?\d)){4}$

Port of @OlivierGrégoire's Java answer, so make sure to upvote him!
-2 bytes thanks to @Neil.

Try it online.

Explanation:

^
.                           # Prepend a dot "." before the (implicit) input
^...$                       # Check if the entire string matches the following regex
                            # exactly, resulting in 1/0 as truthy/falsey:
 (                          #  Open a capture group
  \.                        #   A dot "."
    (25[0-5]                #   Followed by a number in the range [250,255]
    |(2[0-4]|         ) \d) #   or by a number in the range [200,249]
    |(      |1\d|     ) \d) #   or by a number in the range [100,199]
    |(          |[1-9]) \d) #   or by a number in the range [10,99]
    |(                )?\d) #   or by a number in the range [0,9]
 )                          #  Close capture group
  {4}                       #  This capture group should match 4 times after each other
  • My attempt (which I didn't post because the question got put on hold at the time) was the same length, but didn't have the \d group optimisation, so you can save two bytes because you don't need the M specification on the last line. – Neil Oct 23 at 0:41
  • I managed to get Retina down to 42 bytes by porting the Perl 6 answer but this answer also works in 0.8.2 which my port doesn't. – Neil Oct 23 at 1:13

Jelly, 11 bytes

⁹ḶṾ€ṗ4j€”.ċ

A monadic link accepting a list of characters which yields \$1\$ if it's a valid address and \$0\$ otherwise. Builds a list of all \$256^4=4294967296\$ addresses and then counts the number of occurrences of the input therein.

Here's similar @ Try it online! that uses \$16\$ () rather than \$256\$ (), since the method is so inefficient!

How?

⁹ḶṾ€ṗ4j€”.ċ - Link: list of characters, S
⁹           - literal 256
 Ḷ          - lowered range = [0,1,2,...,254,255]
  Ṿ€        - unevaluate €ach = ['0','1',...,['2','5','4'],['2','5','5']]
    ṗ4      - 4th Cartesian power = ALL 256^4 lists of 4 of them
            -               (e.g.: ['0',['2','5','5'],'9',['1','0']])
        ”.  - literal '.' character
      j€    - join for €ach (e.g. ['0','.','2','5','5','.','9','.','1','0'] = "0.255.9.10")
          ċ - count occurrences of right (S) in left (that big list)
  • Why does the version with 65,536 IPs take 1.8 seconds? o_O – Dennis Oct 24 at 14:41

sfk, 176 bytes

* was originally Bash + SFK but TIO has since added a proper SFK wrapper

xex -i "_[lstart][1.3 digits].[1.3 digits].[1.3 digits].[1.3 digits][lend]_[part2]\n[part4]\n[part6]\n[part8]_" +xed _[lstart]0[digit]_999_ +hex +linelen +filt -+1 -+2 +linelen

Try it online!

  • Would first checking the error printout from nc [addr] 1 -w1 shorten this? – Rogem Oct 22 at 9:23
  • @Rogem nc accepts leading zeroes as well as IPv6 addresses, so I'd still have to handle those - and this is intended more as a sfk answer than a shell answer anyway. – Οurous Oct 22 at 9:30

Pip, 25 16 bytes

a~=X,256RL4J"\."

Takes the candidate IP address as a command-line argument. Try it online! or Verify all test cases

Explanation

Regex solution, essentially a port of recursive's Stax answer.

                  a is 1st cmdline arg (implicit)
    ,256          Range(256), i.e. [0 1 2 ... 255]
   X              To regex: creates a regex that matches any item from that list
                  i.e. essentially `(0|1|2|...|255)`
        RL4       Create a list with 4 copies of that regex
           J"\."  Join on this string
 ~=               Regex full-match
a                 against the input

Bash, 30 bytes

ipcalc -c `cat`;echo $(($?^1))

Try it online!

  • The echo $(($?)) part is not needed since programs are allowed to output their result via exit code. – BMO Nov 5 at 16:35

Retina, 42 bytes

~(K`

255*
|'|L$`
$.`
.+
^(($&)\.){3}($&)$

Try it online! Port of @nwellnhof's Perl 6 answer. Explanation:

K`

Clear the work area.

255*

Insert 255 characters.

|'|L$`
$.`

Generate the range 0..255 separated with |s.

.+
^(($&)\.){3}($&)$

Build the regular expression ^((0|1|...255)\.){3}(0|1|...255)$.

~(

Evaluate that on the original input.

JavaScript, 89 bytes

(_,r=`(${[...Array(256).keys()].join`|`})`)=>RegExp(`^${(r+'\\.').repeat(3)+r}$`).test(_)

Try it online!

Create RegExp capture groups from indexes of an array having length 256 for range 0-255 joined with | and followed by escaped . character (^(0|1...|255)\.(0|1...|255)\.(0|1...|255)\.(0|1...|255)$) repeated 3 times closing with joined array followed by $ to match end of string, return true or false result of input passed to RegExp.prototype.test().

Perl 5 -pF/\./, 47 bytes

$\=@F==4&&!/[^0-9.]/;$\&&=!/^0./&&$_<256for@F}{

Try it online!

  • Fixed it with 8 bytes more – Xcali Oct 23 at 15:34

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.