Función de conversión de entero IPv4

17

Escriba la función más corta para convertir una dirección IP en su representación entera y generarla como un entero.

Para cambiar una dirección IPv4 a su representación entera, se requiere el siguiente cálculo:

  • Divide la dirección IP en cuatro octetos.
  • (Octet1 * 16777216) + (Octet2 * 65536) + (Octet3 * 256) + (Octet4)

Entrada de muestra

192.168.1.1           10.10.104.36           8.8.8.8

Salida de muestra

3232235777            168454180              134744072
Kyle Rozendo
fuente
2
Creo que esto sería mejor si hubiera una restricción en el lugar que prohíbe las funciones integradas de un idioma.
Nathan Osman
@George: Sí, lo habría sido, pero la gente ya lo había hecho antes de que pudiera poner eso. Sinceramente, no lo pensé.
Kyle Rozendo

Respuestas:

11

PHP - 21 caracteres

<?=ip2long($argv[1]);
ircmaxell
fuente
8

MySQL - 20 caracteres

SELECT INET_ATON(s);
ircmaxell
fuente
8

Rubí (sin incorporaciones / evaluación) - 47

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

Prueba:

s["192.168.1.1"]
3232235777
Arnaud Le Blanc
fuente
8

C: 79 caracteres

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

EDITAR: eliminado C ++, no se compilaría sin encabezados; con GCC, el printfystrtol llamadas a funciones desencadenan funciones integradas, por lo tanto, las cabeceras se pueden saltar. Gracias a @ugoren por los consejos. Esto se compilará tal cual sin opciones adicionales para gcc.

EDIT2: en returnrealidad es redundante :)

Nim
fuente
uso muy inteligente de main () :) .. mi versión era 116bytes.
akira
Me sale una falla de segmentación.
Nathan Osman
@George, ¿cuál es tu opinión y cómo la estás ejecutando?
Nim
Lo estoy ejecutando con mi UserScript a través de codepad.org
Nathan Osman
Esto no funcionará en C ++, no puede llamar a main de forma recursiva.
Scott Logan
7

Golfscript - 16 caracteres

{[~]2%256base}:f

Como programa independiente, esto es aún más corto a las 11.

~]2%256base

Extremadamente sencillo. Evalúa la cadena de entrada ( ~) y la coloca en una matriz []. Como las .s en la cadena duplican la parte superior de la pila, solo tomamos todos los demás términos en la matriz ( 2%). Ahora tenemos una matriz que básicamente representa un número base 256, por lo que utilizamos una función integrada para realizar la conversión. ( 256base).

Nabb
fuente
muy inteligente. Supongo que base256 se trata de manera diferente para decir base10 o base16, entonces donde 48 => 0?
gnibbler
@gnibbler: No estoy seguro de lo que estás sugiriendo: la función base maneja todas las bases de la misma manera, por ejemplo {:B;{\B*+}*}:base(aunque la función real está sobrecargada para las conversiones de la otra manera). Es interesante notar que la conversión de base para cadenas es la misma que las matrices (ya que las cadenas son solo matrices sin anidamiento, pero con un formato de salida diferente).
Nabb
Sí, estaba pensando en conversiones básicas de cadenas, por lo que no base
busqué
Muy inteligente. Ahora haga eso para una dirección IPv6. :)
Ilmari Karonen
6

Befunge - 2x11 = 22 caracteres

Tan cerca, Befunge ganará algún día.

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

Explicación

La característica más distintiva de Befunge es que, en lugar de ser un conjunto lineal de instrucciones como la mayoría de los idiomas; Es una cuadrícula 2D de instrucciones de un solo carácter, donde el control puede fluir en cualquier dirección.

>      v
^      <

Estos personajes cambian la dirección de control cuando son golpeados, esto hace que el bucle principal.

 &+~1+

Esto ingresa un número y lo empuja a la pila ( &), saca los dos valores superiores de la pila, los agrega y los empuja nuevamente a la pila ( +), ingresa un solo carácter y coloca su valor ascii en la pila ( ~), luego empuja 1 sobre la pila y los agrega ( 1+).

El intérprete que he estado usando devuelve -1 para el final de la entrada, algunos devuelven 0 en su lugar, por lo que la 1+parte podría eliminarse para ellos.

      #v_.@

Esto #hace que se omita el siguiente carácter, luego _saca un valor de la pila y, si es cero, envía el control a la derecha, de lo contrario lo envía a la izquierda. Si el valor era cero, .saca un valor de la pila y lo muestra como un entero y@ detiene el programa. De lo contrario, venvía el control al bucle de retorno.

^*4*8*8<

Esto simplemente multiplica el valor superior de la pila por 256 y devuelve el control al inicio.

Nemo157
fuente
Disculpe mi ignorancia, pero ¿deberían ser 19 caracteres? Entiendo por qué dices 2x11, pero ¿por qué funciona de esa manera?
Kyle Rozendo
Befunge es un lenguaje 2D, si buscas el >v<^que es en realidad el bucle principal de este programa. Supongo que en este caso el control en realidad no pasa por los últimos 3 espacios en la parte inferior, pero me resulta más fácil contar los programas Befunge como el rectángulo delimitador más pequeño; y si intentara contar el flujo de control, se metería en problemas con los programas auto modificables.
Nemo157
5

Rubí (40)

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

->

q["192.168.1.1"]
=> 3232235777
jsvnm
fuente
Buena idea de usar regexp.
Hauleth
¡Muy inteligente! También puede escribir to_i 16como hexpara guardar algunos caracteres.
Paul Prestidge
@chron gracias que hizo que tanto esta como enlace de 4 caracteres más corta
jsvnm
4

Ruby - 46 caracteres

require"ipaddr"
def f s;IPAddr.new(s).to_i;end
gnibbler
fuente
Creo que eso es trampa. ;-)
Chris Jester-Young
3

Golfscript - 21 caracteres

{'.'/{~}%{\256*+}*}:f
gnibbler
fuente
+1 Buena solución sólida. ¿No desea que GolfScript proporcione operadores de desplazamiento de bits? ;-) (Sin embargo, maldita sea si sé a qué símbolos deberían estar vinculados.)
Chris Jester-Young
3

Python 56 45

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

C ++: muchos caracteres

#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
fuente
@George Edison: ¿usar boost ayuda a reducir el número de caracteres? :)
akira
3

PowerShell 66 61

Variación sobre la respuesta de 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
Ty Auvil
fuente
Argh, debo haber sido estúpido por haberme perdido eso ...
Joey
3

AWK en ~ 47 caracteres

Primera vez aquí ... Um, no estoy seguro de cómo contar esto, pero sin el 'eco' son 47 caracteres en AWK. (No es exactamente un campo de golf bogey, pero está en el hoyo).

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

¡¡¡Día completo temprano para #tbt, también, así que en realidad cumplí un horario !!! * 8-)

Día de la bandera

Blair Wyman
fuente
1
¡Bienvenido! Solo contarías el cuerpo de lo que pondrías en un guión awk. Ver esta respuesta . En tu caso solo contarías {print $1*16777216+$2*65536+$3*256+$4}. Por supuesto, tendría que mover el separador de campo al programa, en lugar de especificarlo como una bandera.
Jonás
3

Golpe - 46

Tabla de contenidos

Encontrará 4 versiones de golf diferentes:

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

¡Nueva versión! 15/11/2018 Más golf, 46 char

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

Explicación

  • solía $_ jugar más al golf.
  • La sintaxis ${1//./ }sustituirá todos los puntos .por espacios .
  • así printfque representará algo como192<<(_-=8)|168<<(_-=8)|1<<(_-=8)|1<<(_-=8)|
  • luego agregaremos un 0último O | y
  • preestablecido _a 32 . leerá el constructo de izquierda a derecha, así que $((_-=8))hazlo 24en el primer turno , 16el segundo, y así sucesivamente.

en acción:

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

Por diversión: tratando de obtener $_contenido, después de esto:

echo $_
3232235777

;-si

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

Ok eso es correcto 32 - 4 x 8 = 0

En una función:

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 en un bucle: -> 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

Primer comentario

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

Explicación:

  • La sintaxis ${1//./ }sustituirá todos los puntos .por espacios .
  • set --establecer parámetros posicionales ( $@=($1 $2 $3...))
  • Así set -- ${1//./ }se dividirá $1por puntos y conjunto $1, $2, $3y $4si la cadena containg 3puntos (y sin espacios).

en acción:

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

o en una función:

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

o en un bucle: -> 61

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

en acción:

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

Otra versión de golf diferente: 65

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

Muestra:

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

En un bucle (+14): 82

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

* o un poco más feo: 70 *

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

donde printfdar un poco de cuerda como |192<<24 |168<<16 |1<<8|1<<24 |0<<16 |0<<8tenemos que cortar por fin <<2....

golf con mapfile , más largo: 68

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

o con bucle: 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
fuente
¿podría agregar una breve explicación? He estado tratando de meterme en el golf de bash y no entiendo lo que sucede con la set --pieza. Gracias.
Jonás
@Jonah: set -- foo barse completará $@con foo as $1y bar as $2.
F. Hauri
@Jonah agregó nueva versión
F. Hauri
Gracias por la explicación.
Jonás
¡Nueva versión! más golf, -1 char !!
F. Hauri
2

Windows PowerShell, 70

Enfoque ingenuo:

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

Con el uso de System.Net.IPAddress: 76

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

Prueba:

> '192.168.1.1'|I
3232235777
Joey
fuente
2

Befunge-93 - 36 caracteres

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

Perl: bricolaje (para líneas). (40)

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

# Valor de uso en $ i

Función de bricolaje (65):

sub atoi{my($i,$j)=(0,3);$i+=($_<<($j--*8))for split'.',shift;$i}
Kent Fredric
fuente
Puede dividir por una cadena, por lo que guarda un carácter utilizando en split'.'lugar desplit/\./
cobarde anónimo
Con la versión de función, sí, pero la versión en línea no, porque necesitaría split q{.}evitar la necesidad de escapar de las comillas de shell: /
Kent Fredric
2

Haskell - 14 caracteres

(.) a=(256*a+)

uso en GHCi:

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

El único problema es que tiene que poner espacios a la izquierda o derecha del punto, de lo contrario, los números se interpretarán como coma flotante.

cuasimodo
fuente
¿Le importaría agregar una breve explicación?
Jonás
El operador punto infijo se redefine para hacer el cálculo, ¡muy inteligente!
memorando el
Esto es muy inteligente, pero no usa el formato de entrada correcto (debido a los espacios)
12Me21
2

C # - 77 caracteres

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

JavaScript (45 caracteres)

Requiere soporte para el .reduce()método Array introducido en ES5 y funciones de flecha .

f=(x)=>x.split('.').reduce((p,c)=>p<<8|c)>>>0
PleaseStand
fuente
Huh ... no sabía >>> funcionaba así (convertir a entero de 32 bits sin signo)
12Me21
2

Powershell, 47 43 bytes

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

Script de prueba:

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

Salida:

True: 3232235777
True: 168454180
True: 134744072
mazzy
fuente
1

C # - 120 caracteres

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

Mi primer código de golf: sé amable;)

Kyle Rozendo
fuente
Puede eliminar los espacios alrededor de su primer '='. Sin embargo, su principal problema es el desbordamiento int;). Recuerde, una dirección IP ocupa 4 bytes completos.
Nellius
@Nellius, muy bien. Ni siquiera pensé en comprobar eso, básicamente comprobé la compilación. Gracias, lo arreglaremos ahora.
Kyle Rozendo
1

D: 84 caracteres

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
fuente
No sé D, así que perdóname si es sensible al espacio en blanco como Python, pero esto no parece golfista. ¿Puedes eliminar los saltos de línea dobles o los saltos de línea entre las declaraciones terminadas con punto y coma?
Jonás
1

Python 3.2 (69)

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

PHP (no incorporado / eval) - 54

<foreach(explode(".",$argv[1])as$b)$a=@$a<<8|$b;echo$a;
Arnaud Le Blanc
fuente
¿No debería abrir esto <?php, no solo <?
TRiG
@TRiG, ​​creo que puede cambiar el delimitador de apertura de PHP en el archivo de configuración. Útil en este caso.
Xeoncross
@Xeoncross. Ah Ordenado. Podría intentarlo algún día, solo para meterme en la cabeza de mis compañeros de trabajo.
TRiG
1

Perl, 14 caracteres:

sub _{unpack'L>',pop}

# Example usage
print _(10.10.104.36) # prints 168454180
Grimmy
fuente
55
¿Cómo se hacen esos 14 personajes? Cuento 21.
Peter Taylor
1

C (gcc) -m32 / POSIX, 33 bytes

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

Pruébalo en línea!

En una plataforma big-endian, puede simplemente definir una macro con -Df=inet_atonde 13 bytes .

nwellnhof
fuente