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.