### Daily Challenge #31 - Count IPv4 Addresses

#### dev.to staff on August 03, 2019

Your challenge is to write a function that accepts starting and ending IPv4 addresses and returns the number of IP addresses from start to end, exc... [Read Full]

Ruby, and totally cheating by using it's IPAddr class :)

``````def ips_between(from, to)
end
``````

This actually made me chuckle... lol cheating indeed 😁

And it was my first idea as well... IPv4 Addresses are 4byte integers... so the easiest way is to subtract them. 😎

``````def ip2int ip
ip.split(".").map(&:to_i).pack('CCCC').unpack('N')[0]
end

def ipsBetween start, end_
ip2int(end_) - ip2int(start)
end

p ipsBetween("10.0.0.0", "10.0.0.50") # => 50
p ipsBetween("10.0.0.0", "10.0.1.0")  # => 256
p ipsBetween("20.0.0.10", "20.0.1.0") # => 246
``````

`ip2int()` is from Stack Overflow.

Here's mine! I extended it a little to work if the start and end were reversed.

``````const convertIPStringToNumber = ipString => ipString.split(".")
.reduce((acc, part) => (acc << 8) | Number(part), 0);

const ipsBetween = (start, finish) =>
Math.abs(convertIPStringToNumber(finish) - convertIPStringToNumber(start));
``````

Perl, using recursion. Tests included. It throws an exception if the end address precedes the start one.

``````#!/usr/bin/perl
use warnings;
use strict;

sub _ips_between {
my (\$list1, \$list2, \$sum) = @_;
return \$sum unless @\$list1;

my (\$e1, \$e2) = (shift @\$list1, shift @\$list2);
die "End before start.\n" if \$e2 < \$e1 && \$sum == 0;

return _ips_between(\$list1, \$list2, \$sum + (\$e2 - \$e1) * 256 ** @\$list1)
}

sub ips_between {
_ips_between([split /\./, shift],
[split /\./, shift],
0)
}

use Test::More tests => 6;
use Test::Exception;

is ips_between('10.0.0.0', '10.0.0.50'), 50;
is ips_between('10.0.0.0', '10.0.1.0'), 256;
is ips_between('20.0.0.10', '20.0.1.0'), 246;
is ips_between('0.255.127.12', '1.2.3.4'), 164_856;
is ips_between('1.1.1.1', '1.1.1.1'), 0;
throws_ok { ips_between('1.1.1.1', '1.1.0.1') } qr/End before start/;
``````

Elixir:

``````defmodule IP do
import Bitwise

def between(from, to),
do: abs(to_integer(to) - to_integer(from))

defp to_integer(ip) do
ip
|> String.split(".")
|> Enum.reduce(0, fn part, acc -> acc <<< 8 ||| String.to_integer(part) end)
end
end
``````

``````// sectionSum :: (Number -> Number) -> Number
const sectionSum = value => section => value * 256 ** section;
// ipSum :: [Number] -> Number
const ipSum = ipArray => ipArray.reduceRight((sum, value, section) => sum += sectionSum(value)(3-section));
// ipDifference :: Number -> Number -> Number
const ipDifference = ipSum1 => ipSum2 => Math.abs(ipSum1 - ipSum2);
// ipSections :: String -> [Number]
// ipVal :: String -> Number
const ipVal = ip => ipSum(ipSections(ip))

// ipsBetween :: (String -> String) -> Number
const ipsBetweenCount = startIp => endIp => ipDifference(ipVal(startIp))(ipVal(endIp))
``````

JavaScript

``````const ipsBetween = (ip1, ip2) => {
let diff = 0;
const aIp1 = ip1.split(".");
const aIp2 = ip2.split(".");

// check that the IPs are well formed
if (aIp1.length !== 4 || aIp2.length !== 4) {
return "Invalid IPs: incorrect format";
}

for (x = 0; x < 4; x++) {
// check that all the parts are valid (numeric and 0-255)
if (
isNaN(aIp1[x]) || isNaN(aIp2[x])
|| aIp1[x] < 0 || aIp1[x] > 255
|| aIp2[x] < 0 || aIp2[x] > 255
) {
return "Invalid IPs: incorrect values"
}
diff += (aIp1[x] - aIp2[x]) * (256 ** (3-x));
}
return Math.abs(diff);
}
``````

A bit verbose, but it seems to work fine. Live demo on CodePen.

PHP :D

``````function ipsBetween(\$from, \$to)
{
return ip2long(\$to) - ip2long(\$from);
}
``````

demo: 3v4l.org/8NiWc

in C#

``````public long IPAddressesBetween(string start, string end) =>