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

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:




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

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


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


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.


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

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


3

Golfscript - 21 znaków

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

+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

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

@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

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.


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
}

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


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}

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.


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

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

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


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


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

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



Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.