17
\$\begingroup\$

Write the shortest function to convert an IP address into it's integer representation and output it as an integer.

To change an IPv4 address to it's integer representation, the following calculation is required:

  • Break the IP address into it's four octets.
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

Sample Input

192.168.1.1           10.10.104.36           8.8.8.8

Sample Output

3232235777            168454180              134744072
\$\endgroup\$
  • 2
    \$\begingroup\$ I think this would be better if there was a restriction in place prohibiting a language's built-in functions. \$\endgroup\$ – Nathan Osman Feb 6 '11 at 20:04
  • \$\begingroup\$ @George - Yea, it would have been, but people had already done it before the I could put that in - I honestly didn't think about it. \$\endgroup\$ – Kyle Rozendo Feb 7 '11 at 5:51

46 Answers 46

11
\$\begingroup\$

PHP - 21 Characters

<?=ip2long($argv[1]);
\$\endgroup\$
8
\$\begingroup\$

MySQL - 20 Characters

SELECT INET_ATON(s);
\$\endgroup\$
8
\$\begingroup\$

Ruby (no builtins/eval) - 47

s=->s{s.split(".").inject(0){|a,b|a<<8|b.to_i}}

Test:

s["192.168.1.1"]
3232235777
\$\endgroup\$
8
\$\begingroup\$

C: 79 characters

main(i,a)char**a;{i=i<<8|strtol(a[1],a+1,0);*a[1]++?main(i,a):printf("%u",i);}

EDIT: removed C++, would not compile without headers; with GCC, the printf and strtol function calls trigger built-in functions, hence headers can be skipped. Thx to @ugoren for the tips. This will compile as is without additional options to gcc.

EDIT2: return is actually redundant :)

\$\endgroup\$
  • \$\begingroup\$ very clever use of main() :) .. my version was 116bytes. \$\endgroup\$ – akira Feb 15 '11 at 14:21
  • \$\begingroup\$ I get a segmentation fault. \$\endgroup\$ – Nathan Osman Feb 19 '11 at 3:11
  • \$\begingroup\$ @George, what is your input and how are you running it? \$\endgroup\$ – Nim Feb 21 '11 at 10:43
  • \$\begingroup\$ I'm running it with my UserScript through codepad.org \$\endgroup\$ – Nathan Osman Feb 21 '11 at 19:33
  • \$\begingroup\$ This won't work in C++, you can't call main recursively. \$\endgroup\$ – Scott Logan Feb 26 '12 at 17:40
7
\$\begingroup\$

Golfscript -- 16 chars

{[~]2%256base}:f

As a standalone program, this is even shorter at 11.

~]2%256base

Extremely straightforward. Evaluates the input string (~) and puts it into an array []. Since the .s in the string duplicate the top of the stack, we only take every other term in the array (2%). We now have an array which basically represents a base 256 number, so we use a built-in function to do the conversion. (256base).

\$\endgroup\$
  • \$\begingroup\$ very clever. i guess base256 is treated differently to say base10 or base16 then where 48=>0? \$\endgroup\$ – gnibbler Feb 6 '11 at 20:05
  • \$\begingroup\$ @gnibbler: I'm not sure what you're suggesting -- the base function handles all bases the same way, e.g. {:B;{\B*+}*}:base (although the real function is overloaded for conversions the other way). Interesting to note is that base conversion for strings is the same as arrays (as strings are just arrays without nesting, but with a different output format). \$\endgroup\$ – Nabb Feb 6 '11 at 20:27
  • \$\begingroup\$ yeah i was thinking of base conversions of strings, so i didn't look closely enough at base for my answer \$\endgroup\$ – gnibbler Feb 7 '11 at 0:20
  • \$\begingroup\$ Very clever. Now do that for an IPv6 address. :) \$\endgroup\$ – Ilmari Karonen Feb 29 '12 at 17:28
6
\$\begingroup\$

Befunge - 2x11 = 22 characters

So close, Befunge will win one day.

>&+~1+#v_.@
^*4*8*8<

Explanation

The biggest distinguishing feature of Befunge is that instead of being a linear set of instructions like most languages; it is a 2d grid of single character instructions, where control can flow in any direction.

>      v
^      <

These characters change the direction of control when they are hit, this makes the main loop.

 &+~1+

This inputs a number and pushes it onto the stack (&), pops the top two values off the stack, adds them and pushes them back onto the stack (+), inputs a single character and places its ascii value on the stack (~), then pushes 1 onto the stack and adds them (1+).

The interpreter I've been using returns -1 for end of input, some return 0 instead so the 1+ part could be removed for them.

      #v_.@

The # causes the next character to be skipped, then the _ pops a value off the stack and if it is zero sends control right, otherwise sends it left. If the value was zero . pops a value off the stack and outputs it as an integer and @ stops the program. Otherwise v sends control down to the return loop.

^*4*8*8<

This simply multiplies the top value of the stack by 256 and returns control to the start.

\$\endgroup\$
  • \$\begingroup\$ Pardon my ignorance, but should that be 19 chars? I understand why you say 2x11, but why does it work that way? \$\endgroup\$ – Kyle Rozendo Feb 4 '11 at 19:08
  • \$\begingroup\$ Befunge is a 2d language, if you look for the >v<^ that is actually the main loop in this program. I guess in this case control doesn't actually pass through those last 3 spaces on the bottom, but I find it easiest to just count Befunge programs as the smallest bounding rectangle; and if you were to try and count control flow you get into trouble with self-modifying programs. \$\endgroup\$ – Nemo157 Feb 4 '11 at 22:37
5
\$\begingroup\$

Ruby (40)

q=->x{x.gsub(/(\d+)\.?/){'%02x'%$1}.hex}

->

q["192.168.1.1"]
=> 3232235777
\$\endgroup\$
  • \$\begingroup\$ Nice idea of using regexp. \$\endgroup\$ – Hauleth Feb 28 '12 at 14:56
  • \$\begingroup\$ Very clever! Also you can write to_i 16 as hex to save some characters. \$\endgroup\$ – Paul Prestidge Mar 1 '12 at 21:54
  • \$\begingroup\$ thanks @chron that made both this and link 4 characters shorter \$\endgroup\$ – jsvnm Mar 2 '12 at 8:35
4
\$\begingroup\$

Ruby - 46 chars

require"ipaddr"
def f s;IPAddr.new(s).to_i;end
\$\endgroup\$
  • \$\begingroup\$ I think that constitutes cheating. ;-) \$\endgroup\$ – Chris Jester-Young Feb 2 '11 at 12:10
3
\$\begingroup\$

Golfscript - 21 chars

{'.'/{~}%{\256*+}*}:f
\$\endgroup\$
  • \$\begingroup\$ +1 Good solid solution. Don't you wish GolfScript provides bit-shifting operators? ;-) (Though, darned if I know which symbols they should be bound to.) \$\endgroup\$ – Chris Jester-Young Feb 2 '11 at 12:12
3
\$\begingroup\$

Python 56 45

c=lambda x:eval('((('+x.replace('.','<<8)+'))
\$\endgroup\$
3
\$\begingroup\$

C++ - lots of chars

#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
uint f(std::string p)
{
        std::vector<std::string> x;
        boost::split(x,p,boost::is_any_of("."));
        uint r=0;
        for (uint i = 0; i < x.size(); i++)
                r=r*256+atoi(x[i].c_str());
        return r;
}
\$\endgroup\$
  • \$\begingroup\$ @George Edison: using boost helps to get down with the numbers of chars? :) \$\endgroup\$ – akira Feb 15 '11 at 14:24
3
\$\begingroup\$

PowerShell 66 61

Variation on Joey's answer:

filter I{([ipaddress](($_-split'\.')[3..0]-join'.')).address}

PS C:\> '192.168.1.1' | I
3232235777
PS C:\> '10.10.104.36' | I
168454180
PS C:\> '8.8.8.8' | I
134744072
\$\endgroup\$
  • \$\begingroup\$ Argh, I must have been stupid to have missed that ... \$\endgroup\$ – Joey Feb 15 '11 at 1:59
3
\$\begingroup\$

AWK in ~47 chars

First-timer here... Um, not sure how to count this, but without the 'echo' it's 47 chars in AWK. (Not exactly bogey golf, but it's in the hole.)

echo $addr | /bin/awk -F\. '{print $1*16777216+$2*65536+$3*256+$4}'

Full day early for #tbt, too, so I actually met a schedule!!! *8-)

Banner day.

\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome! You'd only count the body of what you'd put into an awk script. See this answer. In your case you'd count only {print $1*16777216+$2*65536+$3*256+$4}. Of course you'd have to move the field separator into the program, rather than specifying it as a flag. \$\endgroup\$ – Jonah Nov 13 '18 at 2:00
3
\$\begingroup\$

Bash - 46

Table of content

You will find 4 differently golfed version:

echo $[_=32,`printf "%d<<(_-=8)|" ${1//./ }`0]                        # 46chr
set -- ${1//./ };echo $[$1<<24|$2<<16|$3<<8|$4]                       # 47chr
v=('|%d<<'{24,16,8,0});printf -vv "${v[*]}" ${1//./ };echo $[0$v]     # 65chr
mapfile -td. i<<<$1;for((a=o=0;a<4;o+=i[a]<<(3-a++)*8)){ :;};echo $o  # 68chr

New version! 2018-11-15 More golfed, 46 char

echo $[_=32,`printf "%d<<(_-=8)|" ${1//./ }`0]

Explanation

  • I used $_ for more golfing.
  • Syntax ${1//./ }will substitute every dots . by spaces .
  • so printfwill render something like 192<<(_-=8)|168<<(_-=8)|1<<(_-=8)|1<<(_-=8)|
  • then we will add a 0 after last OR | and
  • preset _ to 32. will read construct from left to right, so $((_-=8)) make 24 at 1st shift, 16 on second, and so on.

in action:

set -- 192.168.1.1
echo $[_=32,`printf "%d<<(_-=8)|" ${1//./ }`0]
3232235777

For fun: trying to get $_ content, after this:

echo $_
3232235777

;-b

set -- 192.168.1.1
echo $_ $[_=32,`printf "%d<<(_-=8)|" ${1//./ }`0] $_
192.168.1.1 3232235777 0

Ok, that's correct 32 - 4 x 8 = 0

In a function:

ip2int() {
    echo $[_=32,`printf "%d<<(_-=8)|" ${1//./ }`0]
}
ip2int 192.168.1.1
3232235777
ip2int 255.255.255.255
4294967295
ip2int 0.0.0.0
0

or into a loop: -> 60

ip2int() {
    for i;do
        echo $[_=32,`printf "%d<<(_-=8)|" ${i//./ }`0]
    done
}

ip2int 192.168.1.1 10.10.104.36 8.8.8.8 1.1.1.1 255.255.255.255 0.0.0.0
3232235777
168454180
134744072
16843009
4294967295
0

bash (v4.1+): 47

First post

set -- ${1//./ };echo $[$1<<24|$2<<16|$3<<8|$4]

Explanation:

  • Syntax ${1//./ }will substitute every dots . by spaces .
  • set -- set positional parameters ($@=($1 $2 $3...))
  • So set -- ${1//./ } will split $1 by dots and set $1, $2, $3 and $4 if string containg 3 dots (and no spaces).

in action:

set -- 192.168.1.1
set -- ${1//./ };echo $[$1<<24|$2<<16|$3<<8|$4]
3232235777

or in a function:

ip2int() {
    set -- ${1//./ }
    echo $[$1<<24|$2<<16|$3<<8|$4]
}
ip2int 192.168.1.1
3232235777
ip2int 0.0.0.0
0

or into a loop: -> 61

for i;do set -- ${i//./ };echo $[$1<<24|$2<<16|$3<<8|$4];done

in action:

ip2int() {
    for i;do
        set -- ${i//./ }
        echo $[$1<<24|$2<<16|$3<<8|$4]
    done
}

ip2int 192.168.1.1 10.10.104.36 8.8.8.8 1.1.1.1 0.0.0.0
3232235777
168454180
134744072
16843009
0

Another version differently golfed: 65

v=('|%d<<'{24,16,8,0});printf -vv "${v[*]}" ${1//./ };echo $[0$v]

Sample:

ip2int() {
    v=('|%d<<'{24,16,8,0});printf -vv "${v[*]}" ${1//./ };echo $[0$v]
}

ip2int 255.255.255.255
4294967295
ip2int 10.10.104.36
168454180

In a loop (+14): 82

ip2int() {
    for i;do
        v=('|%d<<'{24,16,8,0})
        printf -vv "${v[*]}" ${1//./ }
        echo $[0$v]
    done
}

* or a little more ugly: 70*

v=('|%d<<'{24,16,8});printf -vv "${v[*]}" ${1//./ };echo $[0${v%<<2*}]

where printf give some string like |192<<24 |168<<16 |1<<8|1<<24 |0<<16 |0<<8 we have to cut at last <<2....

golfed with mapfile, longer: 68

ip2int() {
    mapfile -td. i<<<$1;for((a=o=0;a<4;o+=i[a]<<(3-a++)*8)){ :;};echo $o
}

or with loop: 82

ip2int() {
    for a;do
      mapfile -td. i<<<$a;for((a=o=0;a<4;o+=i[a]<<(3-a++)*8)){ :;};echo $o
    done
}
\$\endgroup\$
  • \$\begingroup\$ could you add a brief explanation? i've been trying to get into bash golfing and i don't follow what's happening with the set -- part. thanks. \$\endgroup\$ – Jonah Nov 12 '18 at 20:27
  • \$\begingroup\$ @Jonah : set -- foo bar will populate $@ with foo as $1 and bar as $2. \$\endgroup\$ – F. Hauri Nov 13 '18 at 17:01
  • \$\begingroup\$ @Jonah Added new version \$\endgroup\$ – F. Hauri Nov 13 '18 at 17:18
  • \$\begingroup\$ Thanks for the explanation. \$\endgroup\$ – Jonah Nov 13 '18 at 17:23
  • \$\begingroup\$ New version! more golfed, -1 char!! \$\endgroup\$ – F. Hauri Nov 15 '18 at 10:12
2
\$\begingroup\$

Windows PowerShell, 70

Naïve approach:

filter I{[int[]]$x=$_-split'\.'
$x[0]*16MB+$x[1]*64KB+$x[2]*256+$x[3]}

With using System.Net.IPAddress: 76

filter I{([ipaddress]($_-replace('(.+)\.'*3+'(.+)'),'$4.$3.$2.$1')).address}

Test:

> '192.168.1.1'|I
3232235777
\$\endgroup\$
2
\$\begingroup\$

Befunge-93 - 36 characters

&"~"2+::8****&884**:**&884***&++++.@
\$\endgroup\$
2
\$\begingroup\$

Perl : DIY ( for oneliners. )(40)

$j=3;$i+=($_<<($j--*8))for split/\./,$x;

# Use value in $i

DIY Function(65):

sub atoi{my($i,$j)=(0,3);$i+=($_<<($j--*8))for split'.',shift;$i}
\$\endgroup\$
  • \$\begingroup\$ You can split by a string, so you save a character by using split'.' rather than split/\./ \$\endgroup\$ – anonymous coward Feb 5 '11 at 10:14
  • \$\begingroup\$ With the function version, yes, but the inline version no, because you'd need split q{.} to get around the need to escape shell quotes :/ \$\endgroup\$ – Kent Fredric Feb 6 '11 at 4:59
2
\$\begingroup\$

Haskell - 14 chars

(.) a=(256*a+)

usage in GHCi:

Prelude> let (.) a=(256*a+)
Prelude> 192. 168. 0. 1
3232235521

The only problem is that you have to put spaces left or right of the dot, otherwise the numbers will be interpreted as floating point.

\$\endgroup\$
  • \$\begingroup\$ mind adding a brief explanation? \$\endgroup\$ – Jonah Nov 12 '18 at 20:28
  • \$\begingroup\$ the dot infix operator is redefined to do the computation, very smart indeed! \$\endgroup\$ – memo Nov 22 '18 at 12:36
  • \$\begingroup\$ This is very clever, but it doesn't use the correct input format (because of the spaces) \$\endgroup\$ – 12Me21 Nov 24 '18 at 19:39
2
\$\begingroup\$

C# – 77 chars

Func<string,uint>F=s=>s.Split('.').Aggregate(0u,(c,b)=>(c<<8)+uint.Parse(b));
\$\endgroup\$
2
\$\begingroup\$

JavaScript (45 characters)

Requires support for the .reduce() Array method introduced in ES5 and arrow functions.

f=(x)=>x.split('.').reduce((p,c)=>p<<8|c)>>>0
\$\endgroup\$
  • \$\begingroup\$ Huh... I didn't know >>> worked like that (converting to unsigned 32 bit integer) \$\endgroup\$ – 12Me21 Nov 24 '18 at 15:30
2
\$\begingroup\$

Powershell, 47 43 bytes

$args-split'\.'|%{$r=([long]$r-shl8)+$_};$r

Test script:

$f = {

$args-split'\.'|%{$r=([long]$r-shl8)+$_};$r

}

@(
    ,("192.168.1.1",3232235777)
    ,("10.10.104.36",168454180)
    ,("8.8.8.8",134744072)
) | % {
    $s,$expected = $_
    $result = &$f $s
    "$($result-eq$expected): $result"
}

Output:

True: 3232235777
True: 168454180
True: 134744072
\$\endgroup\$
1
\$\begingroup\$

C# - 120 Characters

float s(string i){var o=i.Split('.').Select(n=>float.Parse(n)).ToList();return 16777216*o[0]+65536*o[1]+256*o[2]+o[3];}

My first code golf - be gentle ;)

\$\endgroup\$
  • \$\begingroup\$ You can remove the spaces around your first '='. However, your main problem is int overflow ;). Remember, an IP address takes up 4 full bytes. \$\endgroup\$ – Nellius Feb 2 '11 at 10:49
  • \$\begingroup\$ @Nellius - quite right. I didn't even think of checking that, basically checked on compile. Thanks, will fix now. \$\endgroup\$ – Kyle Rozendo Feb 2 '11 at 12:35
1
\$\begingroup\$

D: 84 Characters

uint f(S)(S s)
{
    uint n;
    int i = 4;

    foreach(o; s.split("."))
        n += to!uint(o) << 8 * --i;

    return n;
}
\$\endgroup\$
  • \$\begingroup\$ i don't know D so forgive me if it's whitespace sensitive like python, but this doesn't look golfed. can you remove the double line breaks or the line breaks between semi-colon terminated statements? \$\endgroup\$ – Jonah Nov 12 '18 at 20:25
1
\$\begingroup\$

Python 3.2 (69)

sum((int(j)*4**(4*i)) for i,j in enumerate(input().split('.')[::-1]))
\$\endgroup\$
1
\$\begingroup\$

PHP (no builtins/eval) - 54

<foreach(explode(".",$argv[1])as$b)$a=@$a<<8|$b;echo$a;
\$\endgroup\$
  • \$\begingroup\$ Shouldn't this open with <?php, not just <? \$\endgroup\$ – TRiG Sep 25 '12 at 16:44
  • \$\begingroup\$ @TRiG, I believe you can change the PHP opening delimiter in the config file. Useful in this case. \$\endgroup\$ – Xeoncross Sep 25 '12 at 16:56
  • \$\begingroup\$ @Xeoncross. Ah. Neat. I might try that one day, just to mess with my workmates' heads. \$\endgroup\$ – TRiG Sep 25 '12 at 16:57
1
\$\begingroup\$

Perl, 14 characters:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180
\$\endgroup\$
  • 5
    \$\begingroup\$ How do you make that 14 characters? I count 21. \$\endgroup\$ – Peter Taylor Oct 3 '12 at 10:49
1
\$\begingroup\$

Stax, 9 bytes

üL▼ü╛tΓi╨

Run and debug it

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

05AB1E, 5 bytes

'.¡₁β

Try it online!

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

Perl 6, 16 bytes

{:256[m:g/\d+/]}

Try it online!

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

C (gcc) -m32 / POSIX, 33 bytes

f(a){inet_aton(a,&a);a=ntohl(a);}

Try it online!

On a big-endian platform, you could simply define a macro with -Df=inet_aton for 13 bytes.

\$\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.