Funkcja konwersji liczb całkowitych IPv4

17

Napisz najkrótszą funkcję, aby przekonwertować adres IP na jego liczbę całkowitą i wyślij go jako liczbę całkowitą.

Aby zmienić adres IPv4 na jego reprezentację całkowitą, wymagane są następujące obliczenia:

  • Podziel adres IP na cztery oktety.
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

Przykładowe dane wejściowe

192.168.1.1           10.10.104.36           8.8.8.8

Przykładowe dane wyjściowe

3232235777            168454180              134744072
Kyle Rozendo
źródło
2
Myślę, że byłoby lepiej, gdyby istniało ograniczenie zabraniające wbudowanych funkcji języka.
Nathan Osman,
@George - Tak, byłoby, ale ludzie już to zrobili, zanim zdążyłem to włożyć - szczerze o tym nie myślałem.
Kyle Rozendo

Odpowiedzi:

11

PHP - 21 znaków

<?=ip2long($argv[1]);
ircmaxell
źródło
8

MySQL - 20 znaków

SELECT INET_ATON(s);
ircmaxell
źródło
8

Ruby (bez wbudowanych / eval) - 47

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

Test:

s["192.168.1.1"]
3232235777
Arnaud Le Blanc
źródło
8

C: 79 znaków

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

EDYCJA: usunięty C ++, nie skompilowałby się bez nagłówków; dzięki GCC wywołania funkcji printfi strtolwyzwalają wbudowane funkcje, dlatego nagłówki można pominąć. Dziękujemy za @ugoren za wskazówki. Spowoduje to kompilację bez dodatkowych opcji gcc.

EDIT2: returnjest właściwie zbędny :)

Nim
źródło
bardzo sprytne użycie main () :) .. moja wersja miała 116 bajtów.
akira
Dostaję błąd segmentacji.
Nathan Osman,
@George, jaki jest twój wkład i jak go uruchamiasz?
Nim,
Używam go z moim skryptem użytkownika za pośrednictwem codepad.org
Nathan Osman
To nie zadziała w C ++, nie można wywoływać main rekurencyjnie.
Scott Logan,
7

Golfscript - 16 znaków

{[~]2%256base}:f

Jako samodzielny program jest jeszcze krótszy o 11.

~]2%256base

Niezwykle proste. Ocenia wejściowy ciąg znaków ( ~) i umieszcza go w tablicy []. Ponieważ .s w ciągu powielają górę stosu, bierzemy tylko co drugi termin w tablicy ( 2%). Mamy teraz tablicę, która zasadniczo reprezentuje podstawową liczbę 256, więc do konwersji używamy wbudowanej funkcji. ( 256base).

Nabb
źródło
bardzo mądry. Myślę, że base256 jest traktowane inaczej niż powiedzmy base10 lub base16, a gdzie 48 => 0?
gnibbler
@gnibbler: Nie jestem pewien, co sugerujesz - funkcja podstawowa obsługuje wszystkie bazy w ten sam sposób, np. {:B;{\B*+}*}:base(chociaż prawdziwa funkcja jest przeciążona do konwersji w drugą stronę). Warto zauważyć, że podstawowa konwersja ciągów znaków jest taka sama, jak tablic (ponieważ ciągi są tylko tablicami bez zagnieżdżenia, ale z innym formatem wyjściowym).
Nabb
tak, myślałem o podstawowych konwersjach ciągów, więc nie base
patrzyłem
Bardzo mądry. Teraz zrób to dla adresu IPv6. :)
Ilmari Karonen
6

Befunge - 2x11 = 22 znaków

Tak blisko, Befunge pewnego dnia wygra.

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

Wyjaśnienie

Największą cechą wyróżniającą Befunge jest to, że zamiast być liniowym zestawem instrukcji, jak większość języków; jest siatką 2d instrukcji jednoznakowych, w których kontrola może płynąć w dowolnym kierunku.

>      v
^      <

Po trafieniu postacie te zmieniają kierunek kontroli, co tworzy główną pętlę.

 &+~1+

Wprowadza liczbę i wypycha ją na stos ( &), usuwa dwie górne wartości ze stosu, dodaje je i wypycha z powrotem na stos ( +), wprowadza pojedynczy znak i umieszcza swoją wartość ascii na stosie ( ~), a następnie wypycha 1 na stos i dodaje je ( 1+).

Interpretator, którego używałem, zwraca -1 na końcu wejścia, niektóre zwracają 0, więc 1+część można dla nich usunąć.

      #v_.@

#Powoduje, że następny znak zostać pominięty, wtedy _Zdejmuje wartość ze stosu i jeśli jest zerowa wysyła prawo kontroli, inaczej wysyła go w lewo. Jeśli wartość wynosiła zero, .wyskakuje wartość ze stosu i wyprowadza ją jako liczbę całkowitą i @zatrzymuje program. W przeciwnym razie vprzesyła kontrolę do pętli powrotnej.

^*4*8*8<

To po prostu zwielokrotnia najwyższą wartość stosu przez 256 i przywraca kontrolę do początku.

Nemo157
źródło
Przepraszam za moją ignorancję, ale czy powinno to być 19 znaków? Rozumiem, dlaczego mówisz 2x11, ale dlaczego tak to działa?
Kyle Rozendo
Befunge jest językiem 2d, jeśli szukasz tej, >v<^która jest główną pętlą w tym programie. Wydaje mi się, że w tym przypadku kontrola nie przechodzi przez ostatnie 3 spacje na dole, ale najłatwiej jest po prostu policzyć programy Befunge jako najmniejszy prostokąt ograniczający; a jeśli spróbujesz policzyć przepływ sterowania, wpadniesz w kłopoty z samodopasowującymi się programami.
Nemo157
5

Rubinowy (40)

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

->

q["192.168.1.1"]
=> 3232235777
jsvnm
źródło
Fajny pomysł na użycie wyrażenia regularnego.
Hauleth
Bardzo mądry! Ponadto można napisać to_i 16jak hexzaoszczędzić kilka znaków.
Paul Prestidge
dzięki @chron, dzięki czemu zarówno to, jak i link 4 są krótsze
jsvnm
4

Ruby - 46 znaków

require"ipaddr"
def f s;IPAddr.new(s).to_i;end
gnibbler
źródło
Myślę, że to oznacza oszukiwanie. ;-)
Chris Jester-Young,
3

Golfscript - 21 znaków

{'.'/{~}%{\256*+}*}:f
gnibbler
źródło
+1 Dobre stałe rozwiązanie. Czy nie chcesz, aby GolfScript zapewniał operatory z przesunięciem bitów? ;-) (Cholera, jeśli wiem, z którymi symbolami powinny się związać.)
Chris Jester-Young
3

Python 56 45

c=lambda x:eval('((('+x.replace('.','<<8)+'))
Alexandru
źródło
3

C ++ - wiele znaków

#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;
}
grokus
źródło
@George Edison: korzystanie ze wzmocnienia pomaga obniżyć liczbę znaków? :)
akira,
3

PowerShell 66 61

Wariacja na odpowiedź Joeya:

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
Ty Auvil
źródło
Argh, musiałem być głupi, że przegapiłem to ...
Joey
3

AWK za ~ 47 znaków

Po raz pierwszy tutaj ... Nie wiem, jak to policzyć, ale bez echa mamy 47 znaków w AWK. (Niezupełnie bogey golf, ale jest w dołku.)

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

Cały dzień wcześnie też na #tbt, więc właściwie spełniłem harmonogram !!! * 8-)

Dzień baneru.

Blair Wyman
źródło
1
Witamy! Policzyłbyś tylko to, co włożyłeś do skryptu awk. Zobacz tę odpowiedź . W twoim przypadku liczysz tylko {print $1*16777216+$2*65536+$3*256+$4}. Oczywiście musisz przenieść separator pól do programu, zamiast określać go jako flagę.
Jonasz
3

Bash - 46

Spis treści

Znajdziesz 4 różne wersje gry w golfa:

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

Nowa wersja! 15.11.2018 Więcej golfa, 46 char

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

Wyjaśnienie

  • Użyłem $_więcej golfa.
  • Składnia ${1//./ }zastąpi każdą kropkę .spacjami .
  • więc printfwyrenderuje coś takiego192<<(_-=8)|168<<(_-=8)|1<<(_-=8)|1<<(_-=8)|
  • wtedy dodamy 0po ostatnim OR | i
  • wstępnie ustawiony _na 32 . odczyta konstrukt od lewej do prawej, więc $((_-=8))wykonaj 24na 1. zmianie , 16na drugiej itd.

w akcji:

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

Dla zabawy: próba uzyskania $_treści, po tym:

echo $_
3232235777

;-b

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

Ok, to prawda 32 - 4 x 8 = 0

W funkcji:

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

lub w pętli: -> 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

Pierwszy post

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

Wyjaśnienie:

  • Składnia ${1//./ }zastąpi każdą kropkę .spacjami .
  • set --ustaw parametry pozycyjne ( $@=($1 $2 $3...))
  • Więc set -- ${1//./ }będzie podzielona $1przez kropek i zestawu $1, $2, $3a $4jeżeli ciąg zawierajacego 3kropek (bez spacji).

w akcji:

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

lub w funkcji:

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

lub w pętli: -> 61

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

w akcji:

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

Inna wersja inaczej golfowana: 65

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

Próba:

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

W pętli (+14): 82

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

* lub trochę bardziej brzydka: 70 *

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

gdzie printfdajcie sznurek, |192<<24 |168<<16 |1<<8|1<<24 |0<<16 |0<<8jakbyśmy musieli w końcu przeciąć <<2....

grał w golfa mapfile, dłużej: 68

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

lub z pętlą: 82

ip2int() {
    for a;do
      mapfile -td. i<<<$a;for((a=o=0;a<4;o+=i[a]<<(3-a++)*8)){ :;};echo $o
    done
}
F. Hauri
źródło
czy możesz dodać krótkie wyjaśnienie? starałem się grać w golfa bash i nie śledzę tego, co się dzieje z tą set --częścią. dzięki.
Jonasz
@Jonah: set -- foo barpropaguje $@z foo jak $1i bar jak $2.
F. Hauri,
@Jonah Dodano nową wersję
F. Hauri
Dziękuję za wyjaśnienie.
Jonasz
Nowa wersja! bardziej golfa, -1 char !!
F. Hauri,
2

Windows PowerShell, 70

Podejście naiwne:

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

Korzystając z System.Net.IPAddress: 76

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

Test:

> '192.168.1.1'|I
3232235777
Joey
źródło
2

Befunge-93 - 36 znaków

&"~"2+::8****&884**:**&884***&++++.@
MiffTheFox
źródło
2

Perl: DIY (dla onelinerów.) (40)

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

# Użyj wartości w $ i

Funkcja majsterkowania (65):

sub atoi{my($i,$j)=(0,3);$i+=($_<<($j--*8))for split'.',shift;$i}
Kent Fredric
źródło
Możesz podzielić przez sznurek, więc ocalasz postać, używając split'.'zamiastsplit/\./
anonimowego tchórza
Z wersją funkcji tak, ale z wbudowaną wersją nie, ponieważ trzeba split q{.}obejść potrzebę unikania cudzysłowów: /
Kent Fredric
2

Haskell - 14 znaków

(.) a=(256*a+)

użycie w GHCi:

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

Jedynym problemem jest to, że musisz umieścić spacje po lewej lub prawej stronie kropki, w przeciwnym razie liczby będą interpretowane jako zmiennoprzecinkowe.

quasimodo
źródło
nie możesz dodać krótkiego wyjaśnienia?
Jonasz
operator infix kropki został ponownie zdefiniowany, aby wykonać obliczenia, naprawdę bardzo inteligentny!
notatka
Jest to bardzo sprytne, ale nie używa poprawnego formatu wejściowego (ze względu na spacje)
12Me21
2

C # - 77 znaków

Func<string,uint>F=s=>s.Split('.').Aggregate(0u,(c,b)=>(c<<8)+uint.Parse(b));
Mormegil
źródło
2

JavaScript (45 znaków)

Wymaga obsługi .reduce()metody Array wprowadzonej w ES5 i funkcji strzałek .

f=(x)=>x.split('.').reduce((p,c)=>p<<8|c)>>>0
Proszę wstać
źródło
Huh ... nie wiedziałem >>> działało w ten sposób (konwersja na 32-bitową liczbę całkowitą bez znaku)
12Me21
2

PowerShell, 47 43 bajtów

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

Skrypt testowy:

$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"
}

Wynik:

True: 3232235777
True: 168454180
True: 134744072
mazzy
źródło
1

C # - 120 znaków

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

Mój pierwszy golf golfowy - bądź delikatny;)

Kyle Rozendo
źródło
Możesz usunąć spacje wokół pierwszego „=”. Jednak twoim głównym problemem jest przepełnienie int;). Pamiętaj, że adres IP zajmuje 4 pełne bajty.
Nellius
@Nellius - całkiem słusznie. Nawet nie pomyślałem o sprawdzeniu tego, po prostu sprawdziłem przy kompilacji. Dzięki, naprawię teraz.
Kyle Rozendo
1

D: 84 znaków

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

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

    return n;
}
Jonathan M. Davis
źródło
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]))
l0nwlf
źródło
1

PHP (no builtins/eval) - 54

<foreach(explode(".",$argv[1])as$b)$a=@$a<<8|$b;echo$a;
Arnaud Le Blanc
źródło
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
Grimmy
źródło
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.

nwellnhof
źródło