Mask an IP address and give its broadcast

12

Background

Inspired by this Unix.SE question (and of course my own answer).

When an IP address is specified for an interface, it is often given in this dotted-decimal form:

a.b.c.d e.f.g.h

where a.b.c.d is the actual address and e.f.g.h is the netmask.

The netmask, when represented in binary, is basically a bunch of 1 bits followed by a bunch of 0 bits. When the netmask is bitwise ANDed against the given IP address, result will be the network portion of the address, or simply the network address. This will be programmed into the host's route table so that the host knows to send anything destined for this network out this interface.

The broadcast address for a network is derived by taking the network address (from above) and setting all the host-bits to 1. The broadcast address is used to send to all addresses within the given network.

Challenge

Given a dotted-decimal IP address and valid netmask as input, provide the network address and broadcast address as output, also in dotted-decimal format.

  • Input must be address and mask as two strings in dotted-decimal format. You may pass this as 2 separate strings, as list or array of 2 string elements or a single string with the address and mask separated by some sensible separator.
  • Output format is subject to the same constraints as input format.

Examples

Input                              Output

192.168.0.1 255.255.255.0          192.168.0.0 192.168.0.255
192.168.0.0 255.255.255.0          192.168.0.0 192.168.0.255
192.168.0.255 255.255.255.0        192.168.0.0 192.168.0.255
100.200.100.200 255.255.255.255    100.200.100.200 100.200.100.200
1.2.3.4 0.0.0.0                    0.0.0.0 255.255.255.255
10.25.30.40 255.252.0.0            10.24.0.0 10.27.255.255

Digital Trauma

Posted 2015-12-25T01:24:41.963

Reputation: 64 644

2Will the netmask only have 255s and 0s? – xnor – 2015-12-25T01:51:27.277

1@xnor The last example has 252 in it. – user81655 – 2015-12-25T01:54:24.817

2Shouldn't the last output be 10.24.0.0 10.27.255.255? – PurkkaKoodari – 2015-12-25T02:01:40.233

1@xnor no, the net masks can be any length from 0 to 32 – Digital Trauma – 2015-12-25T03:24:23.323

2@Pietu1998 no, 255.252.0.0 is a valid mask. In binary it is 11111111.11111100.00000000.00000000 – Digital Trauma – 2015-12-25T03:26:09.480

1Yeah, but I mean that the given broadcast output is 00001010000110110000000000000000 (the last bits are not 1's). – PurkkaKoodari – 2015-12-25T03:28:10.090

2@Pietu1998 Oh yeah - sorry - its fixed now. – Digital Trauma – 2015-12-25T03:53:31.397

Answers

5

JavaScript (ES6), 92 bytes

(a,m)=>a.split`.`.map((n,i)=>(v=m[i],m[i]=n&v|v^255,n&v),m=m.split`.`).join`.`+" "+m.join`.`

Explanation

(a,m)=>
  a.split`.`
  .map((n,i)=>(
      v=m[i],
      m[i]=n&v|v^255,
      n&v
    ),
    m=m.split`.`
  ).join`.`
  +" "+m.join`.`

Test

var solution = (a,m)=>a.split`.`.map((n,i)=>(v=m[i],m[i]=n&v|v^255,n&v),m=m.split`.`).join`.`+" "+m.join`.`
<input type="text" id="input" value="10.25.30.40 255.252.0.0" />
<button onclick="result.textContent=solution.apply(null,input.value.split` `)">Go</button>
<pre id="result"></pre>

user81655

Posted 2015-12-25T01:24:41.963

Reputation: 10 181

4

MATL, 47 bytes

This answer uses current version (4.0.0) of the language.

'%i.%i.%i.%i't32whh2:"j'\d+'XXU]tbZ&tb255Z~+hYD

Example

>> matl
 > '%i.%i.%i.%i't32whh2:"j'\d+'XXU]tbZ&tb255Z~+hYD
 > 
> 192.168.0.1
> 255.255.255.0
192.168.0.0 192.168.0.255

Explanation

'%i.%i.%i.%i't32whh      % format string: '%i.%i.%i.%i %i.%i.%i.%i'
2:"                      % for loop: do this twice
    j'\d+'XXU            % input string and parse into 4-vector with the numbers
]                        % end
tbZ&                     % compute network address
tb255Z~+                 % compute broadcast address
hYD                      % concatenate into 8-vector and apply format string

Luis Mendo

Posted 2015-12-25T01:24:41.963

Reputation: 87 464

4

Pyth, 44 42 bytes

LisMcb\.256Lj\..[04jb256'J.&yzKyw'+JxKt^2 32

Try it online. Test suite.

Expects the input as an array, like ["10.25.30.40", "255.252.0.0"].

PurkkaKoodari

Posted 2015-12-25T01:24:41.963

Reputation: 16 699

0

PHP, 74 bytes

<?=long2ip($i=ip2long($argv[1])&$m=ip2long($argv[2])),' ',long2ip($i|~$m);

As a standalone, input is via command line:

$ php ip.php 192.168.0.1 255.255.255.0
192.168.0.0 192.168.0.255

Try it online!

Or as a function, 80 bytes:

function($a,$b){return[long2ip($i=ip2long($a)&$m=ip2long($b)),long2ip($i|~$m)];}

Try it online!

Ungolfed

function ip( $a, $b ) {
    $i = ip2long( $a );          // string IP to 32 bit int
    $m = ip2long( $b );          // string netmask to 32 bit int
    $n = $i & $m;                // network is bitwise AND of IP and netmask
    $c = $i | ~$m;               // broadcast is bitwise OR of IP and inverse netmask
    return [ long2ip( $n ), long2ip( $c ) ];
}

PHP has nice (albeit with long function names) built-ins to handle IPv4 dotted-string to binary and back.

Output

192.168.0.1 255.255.255.0   => 192.168.0.0 192.168.0.255
192.168.0.0 255.255.255.0   => 192.168.0.0 192.168.0.255
192.168.0.255 255.255.255.0 => 192.168.0.0 192.168.0.255
100.200.100.200 255.255.255.255 => 100.200.100.200 100.200.100.200
1.2.3.4 0.0.0.0 => 0.0.0.0 255.255.255.255
10.25.30.40 255.252.0.0 => 10.24.0.0 10.27.255.255

640KB

Posted 2015-12-25T01:24:41.963

Reputation: 7 149

0

PHP, 126 bytes

With input in $n:

preg_filter(~Ð×£ÔÖÐ,~Û¤¢Â×ÛÎÖÑ×ÛÔÔÁÌÀ×ÛÑÂ×ÛÂÛÁÊÀÝÑÝÅÝÝÖÑ×Û¤ÛÒÊ¢ÙÛÎÖÖÑ×ÛÑÂÛÑ×Û¤ÛÒÊ¢ÍÊÊÙÛÎÖÖÅÝÝÖ,$n);echo"$c $b";

Hexdump:

0000000: 7072 6567 5f66 696c 7465 7228 7ed0 d7a3  preg_filter(~...
0000010: 9bd4 d6d0 9a2c 7edb 9ea4 a2c2 d7db ced6  .....,~.........
0000020: d1d7 db96 d4d4 c1cc c0d7 db9c d1c2 d7db  ................
0000030: 8bc2 db96 c1ca c0dd d1dd c5dd ddd6 d1d7  ................
0000040: db9e a4db 96d2 caa2 d9db ced6 d6d1 d7db  ................
0000050: 9dd1 c2db 8bd1 d7db 9ea4 db96 d2ca a283  ................
0000060: cdca cad9 81db ced6 d6c5 dddd d62c 246e  .............,$n
0000070: 293b 6563 686f 2224 6320 2462 223b       );echo"$c $b";

And a more readable version:

preg_filter( /* PCRE regex on input */
    '/(\d+)/e', /* match all digits, execute the code for each one */
    '$a[]=($1) /* push the matched value to the array $a */
        .($i++>3 /* if we're at the 5th or higher digit */
            ?($c.=($t=$i>5?".":"").($a[$i-5]&$1)) /* append to $c bitwise AND-ed number */
                .($b.=$t.($a[$i-5]|255&~$1)) /* append to $b the broadcast address */
            :"")',
    $n);
echo"$c $b"; /* output $c and $b */

preg_filter requires a single statement in the replacement pattern when using the e flag, so I 'append' the result of the calculations to the 5th and higher values of $a, because those are never reused.

Aurel Bílý

Posted 2015-12-25T01:24:41.963

Reputation: 1 083

0

Perl, 90 85 bytes

includes +6 for -pF/\D/

for(0..3){push@a,$F[$_]&1*($y=$F[$_+4]);push@b,$F[$_]|~$y&255}$"='.';$_="@a @b"

Usage:

echo "192.168.0.1 255.255.255.0" | perl -pF/\\D/ file.pl

More readable:

for(0..3) {
    push @a, $F[$_] & 1*($y=$F[$_+4]);  # calc/add network address 'byte'
    push @b, $F[$_] | ~$y & 255         # calc/add broadcast address 'byte'
}
$"='.';                                 # set $LIST_SEPARATOR
$_="@a @b"                              # set output to network address and broadcast

The -F/\D/ splits the input on non-digits and stores it in @F.

Kenney

Posted 2015-12-25T01:24:41.963

Reputation: 946

0

Factor, 103 bytes

[ [ ipv4-aton ] bi@ 2dup bitand -rot dup bit-count 32 - abs on-bits pick bitor 2nip [ ipv4-ntoa ] bi@ ]

Nice.

Ungolfed:

: mask-and-broadcast ( ip mask -- netaddr broadcast )
  [ ipv4-aton ] bi@ 2dup bitand -rot dup bit-count 32 - abs on-bits pick bitor 2nip
  [ ipv4-ntoa ] bi@ ;

cat

Posted 2015-12-25T01:24:41.963

Reputation: 4 989