Funzione di conversione di numeri interi IPv4


17

Scrivi la funzione più breve per convertire un indirizzo IP nella sua rappresentazione di numero intero e inviarlo come numero intero.

Per modificare un indirizzo IPv4 nella sua rappresentazione intera, è necessario il seguente calcolo:

  • Suddividere l'indirizzo IP in quattro ottetti.
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

Input di esempio

192.168.1.1           10.10.104.36           8.8.8.8

Uscita campione

3232235777            168454180              134744072

2
Penso che sarebbe meglio se esistesse una limitazione che vieti le funzioni integrate di una lingua.
Nathan Osman,

@George - Sì, lo sarebbe stato, ma la gente l'aveva già fatto prima che potessi inserirlo - Onestamente non ci ho pensato.
Kyle Rozendo,

Risposte:




8

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

8

C: 79 caratteri

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

EDIT: rimosso C ++, non compilerebbe senza intestazioni; con GCC, ilprintfstrtol chiamate di funzione e attivano funzioni integrate, quindi le intestazioni possono essere saltate. Grazie a @ugoren per i suggerimenti. Questo verrà compilato così com'è senza opzioni aggiuntive per gcc.

EDIT2: in returnrealtà è ridondante :)


uso molto intelligente di main () :) .. la mia versione era 116bytes.
Akira,

Ho un errore di segmentazione.
Nathan Osman,

@Gorge, qual è il tuo contributo e come lo stai eseguendo?
Nim,

Lo sto eseguendo con il mio UserScript tramite codepad.org
Nathan Osman,

Questo non funzionerà in C ++, non puoi chiamare main in modo ricorsivo.
Scott Logan,

7

Golfscript - 16 caratteri

{[~]2%256base}:f

Come programma autonomo, questo è ancora più breve a 11.

~]2%256base

Estremamente semplice. Valuta la stringa di input ( ~) e la inserisce in un array []. Poiché le .s nella stringa duplicano la parte superiore dello stack, prendiamo solo ogni altro termine nell'array ( 2%). Ora abbiamo un array che in pratica rappresenta un numero 256 di base, quindi utilizziamo una funzione integrata per fare la conversione. ( 256base).


molto intelligente. suppongo che base256 sia trattato diversamente per dire base10 o base16 quindi dove 48 => 0?
Gnibbler,

@gnibbler: Non sono sicuro di ciò che stai suggerendo: la funzione base gestisce tutte le basi allo stesso modo, ad esempio {:B;{\B*+}*}:base(sebbene la funzione reale sia sovraccaricata per le conversioni nell'altro modo). È interessante notare che la conversione di base per le stringhe è la stessa delle matrici (poiché le stringhe sono solo matrici senza annidamento, ma con un formato di output diverso).
Nabb,

sì, stavo pensando a conversioni di base di stringhe, quindi non ho guardato abbastanza da vicino baseper la mia risposta
gnibbler

Molto intelligente. Ora fallo per un indirizzo IPv6. :)
Ilmari Karonen,

6

Befunge - 2x11 = 22 caratteri

Così vicino, Befunge vincerà un giorno.

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

Spiegazione

La più grande caratteristica distintiva di Befunge è che invece di essere un insieme lineare di istruzioni come la maggior parte delle lingue; è una griglia 2d di istruzioni a carattere singolo, in cui il controllo può fluire in qualsiasi direzione.

>      v
^      <

Questi personaggi cambiano la direzione del controllo quando vengono colpiti, questo fa il giro principale.

 &+~1+

Questo inserisce un numero e lo inserisce nello stack ( &), estrae i primi due valori dallo stack, li aggiunge e li rimette nello stack ( +), inserisce un singolo carattere e posiziona il suo valore ASCII nello stack ( ~), quindi spinge 1 sulla pila e li aggiunge (1+ ).

L'interprete che ho usato restituisce -1 per la fine dell'input, alcuni restituiscono 0 invece in modo che la 1+parte possa essere rimossa per loro.

      #v_.@

Questo #fa sì che il personaggio successivo venga saltato, quindi _estrae un valore dallo stack e se è zero invia il controllo a destra, altrimenti lo invia a sinistra. Se il valore era zero, .un valore viene estratto dallo stack e viene emesso come numero intero e @arresta il programma. Altrimenti vinvia il controllo al loop di ritorno.

^*4*8*8<

Questo semplicemente moltiplica il valore superiore dello stack per 256 e restituisce il controllo all'inizio.


Perdonate la mia ignoranza, ma dovrebbero essere 19 caratteri? Capisco perché dici 2x11, ma perché funziona in questo modo?
Kyle Rozendo,

Befunge è un linguaggio 2d, se cerchi quello >v<^che in realtà è il ciclo principale in questo programma. Immagino che in questo caso il controllo in realtà non passi attraverso quegli ultimi 3 spazi in basso, ma trovo più semplice contare i programmi Befunge come il più piccolo rettangolo di delimitazione; e se dovessi provare a contare il flusso di controllo potresti avere problemi con i programmi di modifica automatica.
Nemo157,

5

Rubino (40)

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

->

q["192.168.1.1"]
=> 3232235777

Bella idea di usare regexp.
Hauleth,

Molto intelligente! Inoltre puoi scrivere to_i 16come hexper salvare alcuni caratteri.
Paul Prestidge

grazie @chron che ha reso più breve sia il collegamento di 4 caratteri
jsvnm il


3

Golfscript - 21 caratteri

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

+1 Buona soluzione solida. Non desideri che GolfScript offra operatori che cambiano bit? ;-) (Tuttavia, maledetto se so a quali simboli dovrebbero essere legati.)
Chris Jester-Young,

3

Python 56 45

c=lambda x:eval('((('+x.replace('.','<<8)+'))

3

C ++ - molti caratteri

#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: usare boost aiuta a ridurre il numero di caratteri? :)
Akira,

3

PowerShell 66 61

Variazione sulla risposta di Joey:

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, devo essere stato stupido a essermi perso ...
Joey,

3

AWK in ~ 47 caratteri

Primo timer qui ... Ehm, non sono sicuro di come contare questo, ma senza l'eco sono 47 caratteri in AWK. (Non esattamente bogey golf, ma è nella buca.)

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

Intera giornata prima anche per #tbt, quindi ho effettivamente incontrato un programma !!! * 8-)

Giorno della bandiera


1
Benvenuto! Conterresti solo il corpo di ciò che avresti inserito in una sceneggiatura terribile. Vedere questa risposta . Nel tuo caso conteresti solo {print $1*16777216+$2*65536+$3*256+$4}. Ovviamente dovresti spostare il separatore di campo nel programma, anziché specificarlo come flag.
Giona,

3

Bash - 46

Tabella dei contenuti

Troverai 4 versioni diversamente giocate:

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

Nuova versione! 15/11/2018 Più golfizzato, 46 ​​caratteri

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

Spiegazione

  • Ho usato $_per più golf.
  • La sintassi ${1//./ }sostituirà ogni punto .con spazi .
  • così printfrenderà qualcosa di simile192<<(_-=8)|168<<(_-=8)|1<<(_-=8)|1<<(_-=8)|
  • quindi aggiungeremo un 0ultimo OR | e
  • preimpostato _su 32 . leggerà il costrutto da sinistra a destra, quindi $((_-=8))fai 24al 1 ° turno , 16al secondo e così via.

in azione:

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

Per divertimento: provare a ottenere $_contenuti, dopo questo:

echo $_
3232235777

; -b

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

Ok, è corretto 32 - 4 x 8 = 0

In una funzione:

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

o in un ciclo: -> 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

Primo post

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

Spiegazione:

  • La sintassi ${1//./ }sostituirà ogni punto .con spazi .
  • set --imposta parametri posizionali ( $@=($1 $2 $3...))
  • Così set -- ${1//./ }si dividerà $1da punti e set $1, $2, $3e $4se la stringa containg 3punti (e senza spazi).

in azione:

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

o in una funzione:

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

o in un ciclo: -> 61

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

in azione:

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

Un'altra versione giocata diversamente: 65

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

Campione:

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 un ciclo (+14): 82

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

* o un po 'più brutto: 70 *

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

dove printfdare qualche stringa come |192<<24 |168<<16 |1<<8|1<<24 |0<<16 |0<<8dobbiamo tagliare alla fine <<2....

giocato a golf mapfile, più a lungo: 68

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

o con anello: 82

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

potresti aggiungere una breve spiegazione? ho cercato di iniziare a giocare a golf con la bash e non seguo quello che sta succedendo con la set --parte. Grazie.
Giona

@Jonah: set -- foo barpopolerà $@con foo as $1e bar as $2.
F. Hauri,

@Jonah Aggiunta nuova versione
F. Hauri,

Grazie per la spiegazione.
Giona

Nuova versione! più golf, -1 char !!
F. Hauri,

2

Windows PowerShell, 70

Approccio ingenuo:

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

Con l'utilizzo di System.Net.IPAddress: 76

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

Test:

> '192.168.1.1'|I
3232235777

2

Befunge-93 - 36 personaggi

&"~"2+::8****&884**:**&884***&++++.@

2

Perl: DIY (per oneliners.) (40)

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

# Usa valore in $ i

Funzione fai da te (65):

sub atoi{my($i,$j)=(0,3);$i+=($_<<($j--*8))for split'.',shift;$i}

È possibile dividere da una stringa, in modo da risparmiare un personaggio utilizzando split'.'piuttosto chesplit/\./
codardo anonimo

Con la versione della funzione, sì, ma la versione in linea no, perché dovresti split q{.}aggirare la necessità di sfuggire alle citazioni della shell: /
Kent Fredric

2

Haskell - 14 caratteri

(.) a=(256*a+)

utilizzo in GHCi:

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

L'unico problema è che devi posizionare gli spazi a sinistra o a destra del punto, altrimenti i numeri verranno interpretati come virgola mobile.


ti va di aggiungere una breve spiegazione?
Giona

l'operatore dot infix è stato ridefinito per eseguire il calcolo, davvero molto intelligente!
nota del

Questo è molto intelligente, ma non utilizza il formato di input corretto (a causa degli spazi)
Me21

2

C # - 77 caratteri

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

2

JavaScript (45 caratteri)

Richiede supporto per il .reduce()metodo Array introdotto in ES5 e funzioni freccia .

f=(x)=>x.split('.').reduce((p,c)=>p<<8|c)>>>0

Eh ... non lo sapevo >>> ha funzionato in questo modo (convertendo in numero intero a 32 bit senza segno)
Me21

2

Powershell, 47 43 byte

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

Script di prova:

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

Produzione:

True: 3232235777
True: 168454180
True: 134744072

1

C # - 120 personaggi

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

Il mio primo codice golf - sii gentile;)


Puoi rimuovere gli spazi attorno al tuo primo '='. Tuttavia, il problema principale è int overflow;). Ricorda, un indirizzo IP occupa 4 byte completi.
Nellius,

@Nellius - assolutamente giusto. Non ho nemmeno pensato di verificarlo, in pratica ho controllato la compilazione. Grazie, risolverò ora.
Kyle Rozendo,

1

D: 84 personaggi

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

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

    return n;
}

non conosco D così perdonami se è sensibile agli spazi bianchi come il pitone, ma questo non sembra golfato. è possibile rimuovere le interruzioni di doppia riga o le interruzioni di riga tra istruzioni terminate punto e virgola?
Giona

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;

Non dovrebbe aprire questo <?php, non solo <?
TRiG

@TRiG, ​​credo che tu possa cambiare il delimitatore di apertura PHP nel file di configurazione. Utile in questo caso.
Xeoncross,

@Xeoncross. Ah. Neat. Potrei provarlo un giorno, solo per scherzare con la testa dei miei compagni di lavoro.
TRiG

1

Perl, 14 caratteri:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180

5
Come si creano quei 14 personaggi? Conto 21.
Peter Taylor,




1

C (gcc) -m32 / POSIX, 33 byte

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

Provalo online!

Su una piattaforma big-endian, potresti semplicemente definire una macro con -Df=inet_atonper 13 byte .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.