IPv4 Tam Sayı Dönüştürme İşlevi


17

Bir IP adresini tamsayı gösterimine dönüştürmek için en kısa işlevi yazın ve tamsayı olarak çıkın.

Bir IPv4 adresini tamsayı gösterimiyle değiştirmek için aşağıdaki hesaplama gereklidir:

  • IP adresini dört oktete bölün.
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

Örnek Giriş

192.168.1.1           10.10.104.36           8.8.8.8

Örnek Çıktı

3232235777            168454180              134744072

2
Bir dilin yerleşik işlevlerini yasaklayan bir kısıtlama olsaydı bunun daha iyi olacağını düşünüyorum.
Nathan Osman

@George - Evet, olurdu, ama insanlar bunu koyamadan önce yapmışlardı - dürüstçe düşünmedim.
Kyle Rozendo

Yanıtlar:




8

Ruby (yerleşik yapı yok / eval) - 47

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

Ölçek:

s["192.168.1.1"]
3232235777

8

C: 79 karakter

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

EDIT: kaldırıldı C ++, üstbilgi olmadan derlemek olmaz; GCC ile printfve strtolişlev çağrıları yerleşik işlevleri tetikler, böylece üstbilgiler atlanabilir. İpuçları için @ugoren'e teşekkürler. Bu, ek seçenekler olmadan olduğu gibi derlenecektirgcc .

EDIT2: returnaslında gereksiz :)


main () :) çok zekice kullanımı benim sürümüm 116bayt oldu.
akira

Bir segmentasyon hatası alıyorum.
Nathan Osman

@ George, girdiniz nedir ve nasıl çalıştırıyorsunuz?
Nim

CodeScript.org aracılığıyla UserScript
Nathan Osman

Bu C ++ ile çalışmaz, ana özyinelemeli çağıramazsınız.
Scott Logan

7

Golfscript - 16 karakter

{[~]2%256base}:f

Bağımsız bir program olarak, bu 11'de daha da kısadır.

~]2%256base

Son derece basit. Giriş dizesini ( ~) değerlendirir ve bir diziye koyar []. Yana .dizede ler yığının tepesine çoğaltmak, sadece dizideki her dönem sürer ( 2%). Şimdi temel olarak bir temel 256 sayısını temsil eden bir dizimiz var, bu yüzden dönüştürmeyi yapmak için yerleşik bir işlev kullanıyoruz. ( 256base).


çok zeki. sanırım base256, base10 veya base16 demek için farklı muamele görür, o zaman burada 48 => 0?
gnibbler

@gnibbler: Ne önerdiğinizden emin değilim - temel işlev tüm temelleri aynı şekilde işler, örneğin {:B;{\B*+}*}:base(gerçek işlev dönüşümler için aşırı yüklenmiş olmasına rağmen). İlginçtir ki, dizeler için taban dönüşüm dizilerle aynıdır (dizeler sadece iç içe yerleştirilmemiş dizilerdir, ancak farklı bir çıktı biçimindedir).
Nabb

Evet ben dizeleri temel dönüşümleri düşünüyordum, bu yüzden basebenim cevap için yeterince yakından bakmadı
gnibbler

Çok zeki. Şimdi bunu bir IPv6 adresi için yapın. :)
Ilmari Karonen

6

Befunge - 2x11 = 22 karakter

Çok yakın, Befunge bir gün kazanacak.

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

açıklama

Befunge'nin en büyük ayırt edici özelliği, çoğu dil gibi doğrusal bir talimat kümesi olmak yerine; kontrolün herhangi bir yönde akabildiği tek karakterli talimatların 2d ızgarasıdır.

>      v
^      <

Bu karakterler vurulduklarında kontrolün yönünü değiştirir, bu da ana döngüyü yapar.

 &+~1+

Bu bir sayı girer ve yığına ( &) iter , ilk iki değeri yığından çıkarır, ekler ve yığına ( +) geri iter , tek bir karakter girer ve ascii değerini yığına ( ~) yerleştirir, 1'i yığının üzerine iter ve ekler ( 1+).

Kullandığım yorumlayıcı, girişin sonu için -1 döndürür, bunun yerine bir 1+kısmı 0 döndürür, böylece parça onlar için kaldırılabilir.

      #v_.@

Bir #sonraki karakterin atlanmasına neden olur, ardından _yığının dışına bir değer çıkar ve sıfırsa kontrolü sağa gönderir, aksi takdirde sola gönderir. Değer sıfırsa ., yığından bir değer çıkar ve bunu bir tamsayı olarak verir ve @programı durdurur. Aksi takdirde vdönüş döngüsüne kontrolü gönderir.

^*4*8*8<

Bu, yığının en üst değerini 256 ile çarpar ve kontrolü başlangıca döndürür.


Cehaletimi affedin, ama bu 19 karakter olmalı mı? Neden 2x11 dediğini anlıyorum, ama neden bu şekilde çalışıyor?
Kyle Rozendo

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.
Nemo157

5

Ruby (40)

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

->

q["192.168.1.1"]
=> 3232235777

Nice idea of using regexp.
Hauleth

Very clever! Also you can write to_i 16 as hex to save some characters.
Paul Prestidge

thanks @chron that made both this and link 4 characters shorter
jsvnm


3

Golfscript - 21 chars

{'.'/{~}%{\256*+}*}:f

+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.)
Chris Jester-Young


3

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;
}

@George Edison: using boost helps to get down with the numbers of chars? :)
akira

3

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

Argh, I must have been stupid to have missed that ...
Joey

3

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.


1
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.
Jonah

3

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
}

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.
Jonah

@Jonah : set -- foo bar will populate $@ with foo as $1 and bar as $2.
F. Hauri

@Jonah Added new version
F. Hauri

Thanks for the explanation.
Jonah

New version! more golfed, -1 char!!
F. Hauri

2

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


2

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}

You can split by a string, so you save a character by using split'.' rather than split/\./
anonymous coward

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 :/
Kent Fredric

2

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.


mind adding a brief explanation?
Jonah

the dot infix operator is redefined to do the computation, very smart indeed!
memo

This is very clever, but it doesn't use the correct input format (because of the spaces)
12Me21

2

C# – 77 chars

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

2

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

Huh... I didn't know >>> worked like that (converting to unsigned 32 bit integer)
12Me21

2

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


1

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 ;)


You can remove the spaces around your first '='. However, your main problem is int overflow ;). Remember, an IP address takes up 4 full bytes.
Nellius

@Nellius - quite right. I didn't even think of checking that, basically checked on compile. Thanks, will fix now.
Kyle Rozendo

1

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;
}

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?
Jonah

1

Python 3.2 (69)

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

1

PHP (no builtins/eval) - 54

<foreach(explode(".",$argv[1])as$b)$a=@$a<<8|$b;echo$a;

Shouldn't this open with <?php, not just <?
TRiG

@TRiG, I believe you can change the PHP opening delimiter in the config file. Useful in this case.
Xeoncross

@Xeoncross. Ah. Neat. I might try that one day, just to mess with my workmates' heads.
TRiG

1

Perl, 14 characters:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180

5
How do you make that 14 characters? I count 21.
Peter Taylor



1

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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.