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

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:




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

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


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


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.


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

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


3

Golfscript - 21 caracteres

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

+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

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

@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

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


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
}

¿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


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}

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.


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

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

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

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


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

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

1

PHP (no incorporado / eval) - 54

<foreach(explode(".",$argv[1])as$b)$a=@$a<<8|$b;echo$a;

¿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

55
¿Cómo se hacen esos 14 personajes? Cuento 21.
Peter Taylor




Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.