25
\$\begingroup\$

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)
- 1:1:1:1:1:1:1:1|  false   |  (an IPv6 address, not IPv4)

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

\$\endgroup\$
  • 10
    \$\begingroup\$ 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. \$\endgroup\$ – tsh Oct 22 '18 at 9:11
  • 5
    \$\begingroup\$ 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). \$\endgroup\$ – Triggernometry Oct 22 '18 at 15:50
  • 5
    \$\begingroup\$ 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 :) \$\endgroup\$ – psmears Oct 23 '18 at 15:51
  • 3
    \$\begingroup\$ @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. \$\endgroup\$ – BradC Oct 23 '18 at 19:03
  • 2
    \$\begingroup\$ @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. \$\endgroup\$ – Poke Oct 23 '18 at 19:12

37 Answers 37

1
\$\begingroup\$

Perl 5 -pF/\./, 47 bytes

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

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Fixed it with 8 bytes more \$\endgroup\$ – Xcali Oct 23 '18 at 15:34
1
\$\begingroup\$

R, 59 bytes

Passes special cases not in test with periods at start/end

function(s)length(a<-scan(,t=s,s,,,"."))==4&all(a%in%0:255)

Try it online!

\$\endgroup\$
1
\$\begingroup\$

C (gcc), 287 197 bytes

#import<regex.h>
g;f(char*s){regex_t r;g=regcomp(&r,"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$",1);g=regexec(&r,s,0,0,0);return !g;}

Try it online!

Thanks to Logern for the big save !

\$\endgroup\$
  • \$\begingroup\$ 197 bytes Try it online!Saved bytes by removing types, replacing REG_EXTENDED with its int value, removing some of the includes, instead using import, renaming variables and removing the ternary in the return. \$\endgroup\$ – Logern Oct 22 '18 at 23:13
1
\$\begingroup\$

Ruby, 123 107 bytes

Try it online!

a=gets.chomp
e=a.split'.'
(p 0;exit)if(e.map(&:to_i).join'.')!=a
p(e.all?{|i|(0..255)===i.to_i}&&e.size==4)

This could definitely be shorter, probably with a regex of some sort, but I wanted to do it without a regex.

Thanks to MegaTom for Array#all?

0 or false is falsy; true is truthy.

Explanation:

The input is taken from stdin. It's split into an array of the numbers (as strings) on the periods.

If the array isn't the same as it is with the elements converted to numbers and back to strings, the program outputs 0 and exits. This eliminates cases with leading zeros and illegal characters.

The array is converted to an array of true/false values representing whether the value is between 0 and 255, inclusive.

true is outputted if the array is only true values, meaning that all the numbers were between 0 and 255, and only if it has exactly 4 elements, meaning that there were 4 original numbers. false is outputted otherwise, meaning invalid numbers (higher than 255) or too many numbers.

\$\endgroup\$
  • \$\begingroup\$ Hello and welcome to PPCG. Could you possibly provide a link to an online interpreter for ease of verifying your solution? \$\endgroup\$ – Jonathan Frech Jan 27 at 13:15
  • \$\begingroup\$ I've added a TIO link. The default input is 255.255.255.255. \$\endgroup\$ – CG One Handed Jan 28 at 2:52
  • \$\begingroup\$ I think the all? method could make this code a good bit shorter. \$\endgroup\$ – MegaTom Jan 28 at 4:59
  • \$\begingroup\$ Thanks! I didn't think of that. \$\endgroup\$ – CG One Handed Jan 28 at 5:03
0
\$\begingroup\$

Batch, 53 bytes

@(ping -4 %1&echo g 255.255.255.255 w)|find/c"g %1 w"

Disconnect your Internet connection first to avoid the standard loophole.

I can't find information on how to avoid ^".

\$\endgroup\$
  • \$\begingroup\$ Deleted cuz can't handle 255.255.255.255 \$\endgroup\$ – l4m2 Oct 22 '18 at 12:03
0
\$\begingroup\$

APL(NARS) 50 chars, 100 bytes

{'...'≢⍵∼⎕D:0⋄4≠≢w←⍵⊂⍨⍵≠'.':0⋄w≢⍕¨m←⍎¨w:0⋄256>⌈/m}

test:

  p←{'...'≢⍵∼⎕D:0⋄4≠≢w←⍵⊂⍨⍵≠'.':0⋄w≢⍕¨m←⍎¨w:0⋄256>⌈/m}
  {⍞←'[',⍵,'=',(p ⍵),']'⋄⍬}¨a 
[1.160.10.240= 1 ][192.001.32.47= 0 ][1.2.3.= 0 ][0.00.10.255= 0 ][1.2.$.4= 0 ][255.160.0.34= 1 ][.1.1.1= 0 ][1..1.1.1= 0 ][1.1.1.-0= 0 ][.1.1.+1= 0 ][1 1 1 1= 0 ][1= 0 ][10.300.4.0= 0 ][10.4F.10.99= 0 ][fruit loops= 0 ][1.2.3.4.5= 0 ][0.0.0.0= 1 ][0.0 0.0.= 0 ][1.23..4= 0 ][1:1:1:1:1:1:1:1= 0 ]  
\$\endgroup\$
-1
\$\begingroup\$

PHP, 27 26 24 Bytes

<?=+!!ip2long($argv[1]);

Based on @rexkogitans and @nwellnhof solutions Fails for 0.0.0.0 because PHP internal function 0.0.0.0 is not considered a valid IP address Try it!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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