Estoy en tus subredes, jugando tu código


17

Desafío

Dado un IPv4 addressen notación de cuatro puntos y un IPv4 subneten notación CIDR , determine si addressestá en el subnet. Genere un valor distinto y coherente si está en el subnet, y un valor distinto distinto y coherente si no está en el subnet. Los valores de salida no necesariamente tienen que ser veraz / falsey en su idioma.

Breve introducción a la notación de subred CIDR

Las direcciones de red IPv4 tienen 32 bits de longitud, divididas en cuatro grupos de 8 bits para facilitar la lectura. La notación de subred CIDR es una máscara del número especificado de bits, que comienza en el extremo izquierdo. Por ejemplo, para una /24subred, esto significa que los 8 bits más a la derecha de la dirección están disponibles en esa subred. Por lo tanto, dos direcciones que están separadas como máximo 255y tienen la misma máscara de subred, están en la misma subred. Tenga en cuenta que los CIDR válidos tienen todos los bits de host (el lado derecho) sin establecer (ceros).

xxxxxxxx xxxxxxxx xxxxxxxx 00000000
^---    subnet mask   ---^ ^-hosts-^

Para otro ejemplo, una /32subred especifica que todos los bits son la máscara de subred, lo que significa que solo se permite un host por /32.

xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
^---        subnet mask        ---^

Ejemplos:

Usando Truepara "en la subred" y Falsepara "no en la subred" como salida:

127.0.0.1
127.0.0.0/24
True

127.0.0.55
127.0.0.0/23
True

127.0.1.55
127.0.0.0/23
True

10.4.1.33
10.4.0.0/16
True

255.255.255.255
0.0.0.0/0
True

127.1.2.3
127.0.0.0/24
False

127.1.2.3
127.1.2.1/32
False

10.10.83.255
10.10.84.0/22
False

Reglas y aclaraciones

  • Dado que el análisis de entrada no es el punto interesante de este desafío, se garantiza que obtendrá direcciones IPv4 y máscaras de subred válidas.
  • La entrada y salida se pueden dar por cualquier método conveniente .
  • Puede imprimir el resultado en STDOUT o devolverlo como resultado de una función. Indique en su envío qué valores puede tomar la salida.
  • Un programa completo o una función son aceptables.
  • Las lagunas estándar están prohibidas.
  • Este es el por lo que se aplican todas las reglas habituales de golf, y gana el código más corto (en bytes).

¿Tenemos que tomar la entrada en el mismo formato que sus casos de prueba?
Encarnación de la ignorancia

1
@EmbodimentofIgnorance No tiene que tomarlos como uno por línea como en los ejemplos, pero sí debe tomarlos como un quad de puntos y una subred de puntos como en los ejemplos. (por ejemplo, vea la respuesta de JavaScript de Arnauld)
AdmBorkBork

¿Está bien tenerlos separados por una barra, por ejemplo 10.0.0.1/10.0.0.0”/16?
Nick Kennedy

1
@Poke Estoy de acuerdo en que tiene razón en que la notación CIDR describe una dirección IP y un tamaño de subred. Como en, 1.255.1.1/8es una expresión CIDR válida , que representa el host 1.255.1.1dentro de la red 1.0.0.0con una máscara de subred de 255.0.0.0. Sin embargo, el desafío solicita el número de red y la subred específicamente en notación CIDR, que 1.255.1.1/8no es una combinación válida de número de red y subred.
640 KB

1
Ahora también necesitamos una versión IPv6 de este desafío
Ferrybig

Respuestas:


13

Python 3 (62 bytes)

Muy sencillo:

from ipaddress import*
lambda i,m:ip_address(i)in ip_network(m)

9
Bien, pero ¿Python tiene incorporado un reconocimiento de cabras también?
Benjamin Urquhart

3
Por supuesto, Mathematica tiene una función incorporada para todo, ¡ incluso para exoplanetas ! Nada puede superar eso ... Pero como habrás visto, Python coincide con la forma de cabra de Mathematica
hasta

Me pregunto si constituyen un ip_adressobjeto y un ip_networkobjeto any convenient method, posiblemente permitiendo que Python gane, a menos que un lenguaje de golf basado en Python tenga estos como sus tipos.
mi pronombre es monicareinstate

No lo obtendrá en el rango de 20 bytes en Python normal. Solo la importación y lambda ya son más largas que la respuesta Stax. No sorprende que los idiomas de golf ganen con los idiomas "normales" ... :-(
hasta

@someone: vencí a Python con 53 bytes de código de máquina x86-64 . :) No es un lenguaje de golf tradicional, y la mayor parte del tamaño del código está analizando string-> int manualmente. (host^net)>>(32-mask)solo tiene 10 bytes. Pero está a medio camino entre las tareas que no incluyen listas de listas o el mapeo de una función en una lista, porque muchas operaciones escalares se pueden hacer con una instrucción de 2 o 3 bytes, y se pueden construir bucles alrededor de cosas en unos pocos bytes.
Peter Cordes

4

C # (compilador de Visual C #) , 250 + 31 = 281 bytes

(a,b)=>{Func<string,string>h=g=>string.Join("",g.Split('.').Select(x=>{var e=Convert.ToString(int.Parse(x),2);while(e.Length<8)e='0'+e;return e;}));a=h(a);var c=b.Split('/');b=h(c[0]);var d=int.Parse(c[1]);return a.Substring(0,d)==b.Substring(0,d);};

Bytecount incluye using System;using System.Linq;

Pruébalo en línea!

Escribí esto en JS tan pronto como se publicó el desafío, pero Arnauld me ganó con una respuesta mucho mejor, por lo que aquí está en C #.

Definitivamente mucho espacio para jugar al golf.

Explicación:

La función consiste en una subfunción llamada h:

h=g=>string.Join("",
    g.Split('.').Select(x => {
        var e = Convert.ToString(int.Parse(x), 2);
        while (e.Length < 8) e = '0' + e;
        return e;
    }
);

Esta subfunción divide la dirección IP ., convierte cada número en una cadena binaria, deja cada cadena con 0una longitud de 8 bits y luego concatena las cadenas en una cadena binaria de 32 bits.

Esto se hace inmediatamente en el lugar con a=h(a);la dirección IP dada.
Luego dividimos la máscara de subred en una dirección IP y un número de máscara conc=b.Split('/');

El componente de dirección IP también se pasa a través de nuestra subfunción: b=h(c[0]);y el número de máscara se analiza a un entero:var d=int.Parse(c[1]);

Finalmente tomamos los primeros dbits de ambas cadenas binarias (donde destá el número de máscara) y las comparamos:return a.Substring(0,d)==b.Substring(0,d);


1
Demasiado cansado para resolver esto, así que acabo de jugar el tuyo para ti
datos caducados

1
En realidad se olvidó de PadLeft en eso también. ¡ Pruébelo en línea!
Datos vencidos

Muchas optimizaciones. Me complace informarle que rPadestá integrado en cadenas. enlace de pastebin a enlace TIO que es demasiado largo solo
mi pronombre es monicareinstate

2
@someone Small FYI: los acortadores de URL como tinyurl.com están permitidos en los comentarios sobre este SE, a diferencia de la mayoría. :)
Kevin Cruijssen

1
188 - tinyurl.com/y6xfkbxt - buenos consejos para acortar url @KevinCruijssen
dana

4

Shell POSIX de Linux (con net-tools / iputils) (34 bytes sin terminación, 47 bytes con terminación)

¿Qué es más adecuado para analizar máscaras y direcciones de red que las propias utilidades de red? :)

route add -net $2 reject;! ping $1

Advertencia: el script es potencialmente perjudicial para su conectividad a Internet, ejecute con cuidado.

Entrada: el script toma la dirección IP probada como primer argumento y la subred probada. como segundo argumento

Salida: el script devuelve un valor verdadero (0) si el primer argumento del script pertenece a la subred indicada en el segundo argumento. De lo contrario, nunca terminará.

Suposiciones: el script debe ejecutarse como usuario root, en un entorno limpio ( es decir , el administrador no ha establecido ninguna otra ruta de agujero negro, y si se ha ejecutado una instancia anterior del script, la ruta de agujero negro que creó se ha eliminado ) El script también asume una "conexión a Internet que funciona" ( es decir , una ruta predeterminada válida está presente).


Explicación:

Creamos una ruta de agujero negro a la subred especificada. Luego probamos la conectividad a la dirección IP proporcionada mediante ping . Si la dirección no pertenece a la subred (y dado que suponemos una conexión a Internet configurada correctamente), ping intentará enviar paquetes a esa dirección. Tenga en cuenta que si esta dirección realmente responde no importa, ya que ping seguirá intentándolo para siempre. Por el contrario, si la dirección pertenece a la subred, el ping fallará con ENETUNREACH y devolverá 2, y dado que negamos el comando, el script tendrá éxito.


Ejemplo

Pruebe si 5.5.5.5 pertenece a 8.8.8.0/24

$ sudo ./a.sh 5.5.5.5 8.8.8.0/24
PING 5.5.5.5 (5.5.5.5) 56(84) bytes of data.
[...runs forever...]

(Limpiar con sudo ip route del 8.8.8.0/24después de ejecutar el comando).

Pruebe si 5.5.5.5 pertenece a 5.5.5.0/24:

$ sudo ./a.sh 5.5.5.5 5.5.5.0/24
connect: Network is unreachable
$ echo $?
0

(Limpiar con sudo ip route del 5.5.5.0/24después de ejecutar el comando).

Pruebe si 8.8.8.8 pertenece a 5.5.5.0/24:

$ sudo ./a.sh 8.8.8.8 5.5.5.0/24
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=122 time=2.27 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=122 time=1.95 ms
[...runs forever...]

(Limpiar con sudo ip route del 5.5.5.0/24después de ejecutar el comando).


Versión de 47 bytes si no permitimos scripts que no terminen

route add -net $2 reject;ping -c1 $1;[ $? = 2 ]

Según el comentario de @ Grimy, aquí está la versión que siempre termina y devuelve 0 (verdadero) si la dirección está en la subred y 1 (falso) en caso contrario. Hacemos que el ping termine con el -c1indicador que limita el número de paquetes enviados a 1. Si la dirección respondió, el ping devolverá 0, y si no, el ping devolverá 1. Solo si la dirección pertenece a la subred de blackholed, el ping devolverá 2, que es lo que probamos en el último comando.


3
Si bien es inteligente, esto no cumple con el requisito de generar un valor distinto y consistente si la dirección no está en la subred (la ejecución para siempre no cuenta como salida , consulte también esto ).
Grimmy

1
@Grimy: Pero no se ejecuta silenciosamente para siempre, por lo que solo se aplica su segundo enlace, no el primero. También creo pingque moriría de SIGPIPE si se ejecutara con stdout + stderr conectado a otro programa, y ​​el lector cerró la tubería. Y ese es el caso de uso más probable porque el estado de salida puede ser exitoso de cualquier manera (si agregamos una -c1opción para hacer ping para establecer el conteo). Pero claro, la lectura de su salida var=$(/a.sh)fallará; necesitaría un lector que se detuviera después de decidir, en lugar de leer todo el resultado y luego mirarlo.
Peter Cordes

@Grimy Fair point (aunque por el argumento podría decir que tenemos dos valores consistentes aquí, ya pingque terminará en menos de, digamos, un segundo en caso de una dirección de blackholed). ¡Agregué una versión final por 13 bytes adicionales! :)
yoann

3

JavaScript (ES6), 82 bytes

Toma entrada como (address)(subnet). Devuelve un valor booleano.

a=>s=>!([s,v]=s.split`/`,+v&&(g=s=>s.split`.`.map(k=v=>k=k<<8|v)|k>>32-v)(a)^g(s))

Pruébalo en línea!


3

PHP , 101 92 88 bytes

-13 bytes de @gwaugh

function($i,$r){[$r,$n]=explode('/',$r);return(ip2long($i)&~(1<<32-$n)+1)==ip2long($r);}

Pruébalo en línea!


2
Me divertí jugando al golf (Ty!):function($i,$r){return!((ip2long($i)^ip2long(strtok($r,'/')))>>32-strtok(_));}
Christoph

@ Christoph muy agradable! Nunca se me ocurrió que podría usar cualquier token para la segunda llamada strtok(). La suya es 4 bytes más corta que mi respuesta muy similar a continuación. ¡Accesorios!
640 KB

@ Christoph Debe publicar su solución como una respuesta separada, ya que es mejor que la mía.
Luis felipe De jesus Munoz

3

PowerPC / PPC64 C, 116 114 bytes

#include<stdio.h>
main(){unsigned u[4];char*p=u;for(;p<u+3;)scanf("%hhu%c",p++,u+3);return!((*u^u[1])>>32-p[-4]);}

(Probado en x86_64 Ubuntu 18.04 usando powerpc64-linux-gnu-gcc -static y qemu-user).

El programa toma las dos líneas en la entrada estándar y, como código de salida, devuelve 1 si la dirección coincide y 0 si no. (Por lo tanto, esto depende de que la especificación no requiera un valor verdadero para una coincidencia y un valor falsey para una falta de coincidencia). Tenga en cuenta que si está ejecutando de forma interactiva, deberá indicar EOF ( ^D) tres veces después de ingresar a la segunda línea.

Esto depende de que PowerPC sea big-endian, y también de que la plataforma devuelva 0 para desplazar a la derecha un valor sin signo de 32 bits por 32. Lee los octetos en valores sin signo uno por uno, junto con la longitud de la máscara de red en otro byte ; luego toma el xor de las dos direcciones de 32 bits sin signo y desplaza los bits irrelevantes. Finalmente se aplica! para satisfacer el requisito de devolver solo dos valores distintos.

Nota: Se podría ser posible afeitar de dos bytes, reemplazando u+3con py que requieren compilación con -O0. Sin embargo, eso es vivir más peligrosamente de lo que me importa.

Gracias a Peter Cordes por la inspiración para esta solución.


Más portátil C, 186 171 167 bytes

Aquí preservaré una versión más portátil que ejecuta 167 bytes.

#include<stdio.h>
main(){unsigned a,b,c,d,e,f,g,h,n;scanf("%u.%u.%u.%u %u.%u.%u.%u/%u",&a,&b,&c,&d,&e,&f,&g,&h,&n);return!(n&&((((a^e)<<8|b^f)<<8|c^g)<<8|d^h)>>32-n);}

Este programa toma las dos líneas en la entrada estándar y devuelve el código de salida 1 si la dirección está en la subred y 0 si no lo está. (Por lo tanto, esto depende de que la especificación no requiera un valor verdadero para las coincidencias y un valor falso para las no coincidencias).

Un desglose de la expresión central:

  • a^e, b^f, c^g, d^hCalcula el XOR de la dirección y la máscara de byte a byte.
  • (((a^e)<<8|b^f)<<8|c^g)<<8|d^h luego los combina en un solo valor de 32 bits sin signo mediante un método similar a Horner.
  • ...>>32-nluego cambia los bits de la diferencia xor que no son relevantes para la máscara de subred (teniendo en cuenta que -tiene mayor prioridad en C que <<)
  • Sin embargo, hay un problema: si n = 0 ~0U<<32, dará un comportamiento indefinido asumiendo que unsignedes de 32 bits (que está en prácticamente todas las plataformas actuales). Por otro lado, si n = 0, cualquier dirección coincidirá, por n&&...lo que dará el resultado correcto (aprovechando el comportamiento de cortocircuito de &&).
  • Finalmente, para cumplir con el requisito de que la salida solo puede ser uno de dos valores, aplicamos !a la salida 0 o 1.

-15 bytes debido a los comentarios de ceilingcat y AdmBorkBork

-4 bytes debido al comentario de Peter Cordes


1
El uso de códigos de salida para devolver valores es uno de los métodos de E / S predeterminados y, por lo tanto, está permitido.
AdmBorkBork

@ceilingcat Por supuesto, qué tonto de mi parte perder eso.
Daniel Schepler

@AdmBorkBork OK, gracias, lo he cambiado para usar el código de salida.
Daniel Schepler

idea: apunte a una implementación C little-endian o big-endian (code-golf no requiere código portátil) y punteros de salida de tipo-pun en los bytes de un unsigned . por ejemplo, con char*p=&athen p++,p++,p++,...o p--,...como scanf args. Sin "%hhu.%hhu..."embargo, la cadena de formato debería ser , por lo que es una compensación significativa entre ese tamaño adicional frente a declarar menos variables y poder hacerlo(a^b)>>(32-count)
Peter Cordes,

1
@PeterCordes Sí, el cambio a la derecha funciona, gracias.
Daniel Schepler

2

Stax , 22 bytes

é.○▄╗jF⌐§╥§I╓☻lw«ç┴║╫┼

Ejecutar y depurarlo

Toma los parámetros de entrada separados por espacios en la entrada estándar.

Desempaquetado, sin golf y comentado, se ve así.

'/:/~       split on slash and push the last group back to the input stack
j{          split on space; for each group, run this code block
  './       split on period
  {emVB|E   evaluate integers and decode integer as base-256
  ;e|<      peek from input stack and shift left
  Vu/       integer divide by 2^32
F           end of for-each
=           two values left on stack are equal?

Ejecute este


2

Función de código de máquina x86-64, 53 48 bytes

registro de cambios:

  • -2 jz sobre el turno en lugar de usar un turno de 64 bits para manejar el >>(32-0)caso especial.
  • -3 devuelve en ZF en lugar de AL, ahorrando 3 bytes para un setnz al .

(Véase también la respuesta del código de máquina de 32 bits de Daniel Schepler basada en esto, que luego evolucionó para usar algunas otras ideas que teníamos. Incluyo mi última versión de eso al final de esta respuesta).


Devuelve ZF = 0 para el host no en la subred, ZF = 1 para la subred, por lo que puede ramificar el resultado conje host_matches_subnet

Se puede llamar con la convención de llamadas del sistema V x86-64 como
bool not_in_subnet(int dummy_rdi, const char *input_rsi); si agregara setnz al.

La cadena de entrada contiene el host y la red, separados por exactamente 1 carácter sin dígitos. La memoria que sigue al final del ancho del CIDR debe contener al menos 3 bytes sin dígitos antes del final de una página. (No debería ser un problema en la mayoría de los casos, como para un cmdline arg.) La versión de 32 bits de Daniel no tiene esta limitación.

Ejecutamos el mismo bucle de análisis de cuatro puntos con puntos 3 veces, obteniendo las dos direcciones IPv4 y obteniendo el /mask como un entero en el byte alto de una palabra d. (Esta es la razón por la que debe haber memoria legible después del /mask, pero no importa si hay dígitos ASCII).

Lo hacemos (host ^ subnet) >> (32-mask)para cambiar los bits del host (los que no pueden coincidir), dejando solo la diferencia entre la subred y el host. Para resolver el /0caso especial en el que necesitamos cambiar por 32, saltamos sobre el cambio en cuenta = 0. ( neg clestablece ZF, que podemos ramificar y dejar como valor de retorno si no cambiamos). Tenga en cuenta que 32-mask mod 32 = -mask, y los cambios escalares x86 enmascaran su recuento en & 31o & 63.

    line  addr   machine                NASM source.  (from nasm -felf64 -l/dev/stdout)
    num          code bytes

     1                             %use smartalign
     2                             
     3                                 ;10.4.1.33 10.4.0.0/23         true
     4                                 ;10.4.1.33 10.4.0.0/24         false
     5                             
     6                             ;; /codegolf/185005/im-in-your-subnets-golfing-your-code
     7                             %ifidn __OUTPUT_FORMAT__, elf64
     8                             in_subnet:
     9                             
    10 00000000 6A03                   push 3
    11 00000002 5F                     pop  rdi                    ; edi = 3 dotted-quads to parse, sort of.
    12                             .parseloop:
    13                             
    14                                 ;xor  ebx,ebx             ; doesn't need to be zeroed first; we end up shifting out the original contents
    15                                 ;lea  ecx, [rbx+4]
    16 00000003 6A04                   push   4
    17 00000005 59                     pop    rcx                  ; rcx = 4 integers in a dotted-quad
    18                             .quadloop:
    19                             
    20 00000006 31D2                   xor   edx,edx               ; standard edx=atoi(rdi) loop terminated by a non-digit char
    21 00000008 EB05                   jmp  .digit_entry
    22                              .digitloop:
    23 0000000A 6BD20A                 imul   edx, 10
    24 0000000D 00C2                   add    dl, al
    25                              .digit_entry:
    26 0000000F AC                     lodsb
    27 00000010 2C30                   sub    al, '0'
    28 00000012 3C09                   cmp    al, 9
    29 00000014 76F4                   jbe   .digitloop
    30                                 ; al=non-digit character - '0'
    31                                 ; RDI pointing to the next character.
    32                                 ; EDX = integer
    33                             
    34 00000016 C1E308                 shl    ebx, 8
    35 00000019 88D3                   mov    bl, dl               ; build a quad 1 byte at a time, ending with the lowest byte
    36 0000001B E2E9                   loop .quadloop
    37                             
    38 0000001D 53                     push   rbx          ; push result to be collected after parsing 3 times
    39 0000001E FFCF                   dec    edi
    40 00000020 75E1                   jnz   .parseloop
    41                             
    42 00000022 59                     pop    rcx   ; /mask  (at the top of a dword)
    43 00000023 5A                     pop    rdx   ; subnet
    44 00000024 58                     pop    rax   ; host
    45 00000025 0FC9                   bswap  ecx   ; cl=network bits  (reusing the quad parse loop left it in the high byte)

    49 00000027 F6D9                   neg    cl
    50 00000029 7404                   jz   .all_net     ; skip the count=32 special case
    51                             
    52 0000002B 31D0                   xor    eax, edx   ; host ^ subnet
    53 0000002D D3E8                   shr    eax, cl    ; shift out the host bits, keeping only the diff of subnet bits
    54                             
    55                             .all_net:
    56                                ; setnz  al         ; return ZF=1 match,  ZF=0 not in subnet
    57 0000002F C3                     ret
    58 00000030 30                 .size:      db $ - in_subnet

              0x30 = 48 bytes

(no actualizado con la última versión) Pruébelo en línea!

incluido un _startque lo activa argv[1]y devuelve un estado de salida.

## on my desktop
$ ./ipv4-subnet "10.4.1.33 10.4.0.0/24"    && echo "$? : in subnet" || echo "$? : not in subnet"
not in subnet

$ ./ipv4-subnet "10.4.1.33 10.4.0.0/23"    && echo "$? : in subnet" || echo "$? : not in subnet"
in subnet

Funciona bien si pasa una línea de comando arg que contiene una nueva línea en lugar de un espacio. Pero tiene que ser en su lugar , no tan bien.


Función de código de máquina x86 de 32 bits, 38 bytes

Hacer 9 enteros -> uint8_t analiza y "empujarlos" en la pila, donde los sacamos como dwords o usamos el último todavía en CL. Evita leer más allá del final de la cadena en absoluto.

Además, decsolo tiene 1 byte en modo de 32 bits.

    72                             in_subnet:
    73 00000000 89E7                   mov   edi, esp
    74 00000002 51                     push  ecx
    75 00000003 51                     push  ecx                   ; sub esp,8
    76                             .byteloop:
    77                             
    78 00000004 31C9                   xor   ecx,ecx               ; standard ecx=atoi(rdi) loop terminated by a non-digit char
    79                                                             ; runs 9 times: 8 in two dotted-quads, 1 mask length
    80 00000006 EB05                   jmp  .digit_entry
    81                              .digitloop:
    82 00000008 6BC90A                 imul   ecx, 10
    83 0000000B 00C1                   add    cl, al
    84                              .digit_entry:
    85 0000000D AC                     lodsb
    86 0000000E 2C30                   sub    al, '0'
    87 00000010 3C09                   cmp    al, 9
    88 00000012 76F4                   jbe   .digitloop
    89                                 ; RDI pointing to the next character.
    90                                 ; EDX = integer
    91                             
    92 00000014 4F                     dec    edi
    93 00000015 880F                   mov    [edi], cl           ; /mask store goes below ESP but we don't reload it
    94 00000017 39E7                   cmp    edi, esp
    95 00000019 73E9                   jae   .byteloop
    96                             
    97                                 ;; CL = /mask still there from the last conversion
    98                                 ;; ESP pointing at subnet and host on the stack, EDI = ESP-1
    99                             
   100 0000001B 5A                     pop    edx   ; subnet
   101 0000001C 58                     pop    eax   ; host
   102                             
   103 0000001D 31D0                   xor    eax, edx             ; host ^ subnet
   104 0000001F F6D9                   neg    cl                   ; -mask = (32-mask) mod 32;  x86 shifts mask their count
   105 00000021 7402                   jz     .end                 ; 32-n = 32 special case
   106 00000023 D3E8                   shr    eax, cl
   107                             .end:
   108                                 ; setz  al                  ; just return in ZF
   109 00000025 C3                     ret

   110 00000026 26                 .size:      db $ - in_subnet
      0x26 = 38 bytes

Llamada de prueba

   113                             global _start
   114                             _start:
   115 00000027 8B742408               mov    esi, [esp+8]   ; argv[1]
   116 0000002B E8D0FFFFFF             call   in_subnet
   117 00000030 0F95C3                 setnz  bl
   118 00000033 B801000000             mov    eax, 1         ; _exit syscall
   119 00000038 CD80                   int    0x80

Tengo curiosidad por saber cómo sería el recuento de bytes de asm de 32 bits si, en lugar de lo cmp/jccque mencionaste, hicieras algo así xor edx,edx;neg cl;cmovz eax,edx;shr eax,cl, o tal vez ya tengas un valor 0 en alguna parte. (Y entonces no necesitarías las sub cl,32instrucciones.)
Daniel Schepler

1
Sí, parece que edidebería ser 0 cuando sale el bucle, por lo que xor eax,edx;neg cl;cmovz eax,edi;shr eax,cldebería funcionar.
Daniel Schepler

1
Si conté bien las cosas, cmove eax,editiene 3 bytes, que es un lavado sobre el eliminado, sub cl,32luego shr cl,eaxguarda un byte shr cl,raxy 32 bits dec ediguarda un byte sobre 64 bits dec edi. Mi ensamblaje luego da .byte 0x33(en la sintaxis binutils de GNU) = 51 para in_subnet.size.
Daniel Schepler

Buena idea, gracias. (En la sintaxis de Intel es shr eax,cl, shr %cl, %eaxen comparación con la sintaxis de AT&T, su último comentario revirtió eso). Es un poco complicado actualizar las respuestas del código de máquina (y portar a la _startpersona que llama y volver a describir la convención de llamada para el modo de 32 bits ... .), así que podría no llegar a eso. Sentirse flojo hoy. >. <
Peter Cordes

1
Acabo de intentar implementar el comentario que pones en mi respuesta sobre deshacerse del doble bucle y almacenarlo en variables de pila, e incluso con el código adicional para inicializar el puntero de ediescritura, escribir la salida, etc., terminó ahorrando 2 bytes en la red. (Al menos una vez me di cuenta de que push ecx;push ecx;push ecxera más corto que sub esp,12; y parecía ser un lavado si predecrementaba ediy usaba std;stosb;cldo si simplemente almacenaba usando dec edi;mov [edi],al.
Daniel Schepler

1

Jalea , 23 bytes

ṣ”/ṣ€”.Vḅ⁹s2+Ø%BḊ€ḣ€ʋ/E

Pruébalo en línea!

Enlace monádico que toma una dirección y una subred separadas por una barra diagonal y devuelve 1 para verdadero y 0 para falso.

Gracias a @gwaugh por señalar una falla en el original: no se pudo garantizar que la lista binaria fuera de 32 años.



1

05AB1E , 21 bytes

'/¡`U‚ε'.¡b8jð0:JX£}Ë

Toma la subred antes de la dirección.

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

'/¡              '# Split the first subnet-input by "/"
   `              # Push both values separated to the stack
    U             # Pop and store the trailing number in variable `X`
                 # Pair the subnet-IP with the second address-input
     ε            # Map both to:
      '.¡        '#  Split on "."
         b        #  Convert each integer to binary
          8j      #  Add leading spaces to make them size 8
          ð0:     #  And replace those spaces with "0"
             J    #  Join the four parts together to a single string
              X£  #  And only leave the first `X` binary digits as substring
                # After the map: check if both mapped values are the same
                  # (which is output implicitly as result)

1

R 120 bytes

una función - pegué ".32" al primer término

w=function(a,b){f=function(x)as.double(el(strsplit(x,"[./]")));t=f(paste0(a,".32"))-f(b);sum(t[-5]*c(256^(3:0)))<2^t[5]}

y solo por diversión:

require("iptools");w=function(a,b)ips_in_cidrs(a,b)[[2]]

que es 56 bytes


1

PHP ,75 7371 bytes

<?=strtok($argv[2],'/')==long2ip(ip2long($argv[1])&1+~1<<32-strtok(_));

Una bifurcación de la respuesta de @Luis felipe De jesus Muñoz , como una entrada independiente tomando argumentos de la línea de comando. Salidas '1'para Truthy, ''(cadena vacía) para Fasley.

$ php ipsn.php 127.0.0.1 127.0.0.0/24
1
$ php ipsn.php 127.1.2.3 127.0.0.0/24

Pruébalo en línea!

-2 bytes tomando prestado el pequeño truco de @Christophstrtok() . Sin embargo, su respuesta es aún más corta.


1

función de montaje x86, 49 43 bytes

Esto se publica principalmente para satisfacer la solicitud de Peter Cordes de la versión revisada que creé. Probablemente puede desaparecer una vez / si lo incorpora en su respuesta.

Esta función espera esiapuntar a una cadena de entrada, con la dirección y las partes de subred separadas por un espacio o un carácter de nueva línea, y el valor de retorno está en el indicador ZF (que por definición solo tiene dos valores posibles).

 1                                  %use smartalign
 2                                  
 3                                      ;10.4.1.33 10.4.0.0/23         true
 4                                      ;10.4.1.33 10.4.0.0/24         false
 5                                  
 6                                  ;; /codegolf/185005/im-in-your-subnets-golfing-your-code
 7                                  in_subnet:
 8                                  
 9                                      ;xor  ebx,ebx             ; doesn't need to be zeroed first; we end up shifting out the original contents
10                                      ;lea  ecx, [rbx+4]
11 00000000 6A09                        push   9
12 00000002 59                          pop    ecx                  ; ecx = 9 integers (8 in two dotted-quads,
13                                                                  ; 1 mask length)
14                                  
15 00000003 89E7                        mov   edi, esp
16 00000005 83EC0C                      sub   esp, 12
17                                  .quadloop:
18                                  
19 00000008 31D2                        xor   edx,edx               ; standard edx=atoi(rdi) loop terminated by a non-digit char
20 0000000A EB05                        jmp  .digit_entry
21                                   .digitloop:
22 0000000C 6BD20A                      imul   edx, 10
23 0000000F 00C2                        add    dl, al
24                                   .digit_entry:
25 00000011 AC                          lodsb
26 00000012 2C30                        sub    al, '0'
27 00000014 3C09                        cmp    al, 9
28 00000016 76F4                        jbe   .digitloop
29                                      ; al=non-digit character - '0'
30                                      ; RDI pointing to the next character.
31                                      ; EDX = integer
32                                  
33 00000018 4F                          dec    edi
34 00000019 8817                        mov    [edi], dl
35 0000001B E2EB                        loop .quadloop
36                                  
37 0000001D 59                          pop    ecx   ; /mask  (at the top of a dword)
38 0000001E 5A                          pop    edx   ; subnet
39 0000001F 58                          pop    eax   ; host
40 00000020 0FC9                        bswap  ecx   ; cl=network bits  (reusing the quad parse loop left it in the high byte)
41                                  
42                                  ;    xor    cl, -32    ; I think there's some trick like this for 32-n or 31-n, but maybe only if we're masking to &31?  Then neg or not work.
43                                  
44 00000022 31D0                        xor    eax, edx   ; host ^ subnet
45                                  ;    xor    edx, edx   ; edx = 0
46 00000024 F6D9                        neg    cl
47 00000026 7402                        jz     .end
48 00000028 D3E8                        shr    eax, cl    ; count=32 special case isn't special for a 64-bit shift
49                                  .end:    
50 0000002A C3                          ret
51 0000002B 2B                      .size:      db $ - in_subnet

Y la parte del contenedor x86 de Linux:

53                                  global _start
54                                  _start:
55 0000002C 8B742408                    mov    esi, [esp+8]   ; argv[1]
56 00000030 E8CBFFFFFF                  call   in_subnet
57 00000035 0F95C0                      setnz  al
58 00000038 0FB6D8                      movzx  ebx, al
59 0000003B B801000000                  mov    eax, 1         ; _exit syscall
60 00000040 CD80                        int    0x80

-6 bytes debido a la sugerencia de Peter Cordes para devolver el valor en ZF.


Creo que podría salvar a un byte mediante la eliminación de la última xor edx,edxy reemplazar cmovz eax,edxcon jz .nonzero; xor eax,eax; .nonzero:. cmovztodavía gana si tenemos convenio de convocatoria ebx=0.
Daniel Schepler

¿Podemos jzpasar shral setz o al ret? Podemos cambiar el setnza setzy volver 1para un partido si eso ayuda. O incluso decir que nuestro valor de retorno es ZF. Debería haber hecho eso en mi respuesta. (Pero no creo que podamos justificar que se requiera que la persona que llama cree constantes para nosotros, por ejemplo ebx=0. Mi respuesta en Consejos para jugar golf en código de máquina x86 / x64 argumenta que extendería demasiado una convención de llamada personalizada.
Peter Cordes,

Por cierto, yo uso cutpara eliminar algunas columnas de la salida del listado NASM porque todas mis instrucciones son cortos: nasm -felf foo.asm -l/dev/stdout | cut -b -34,$((34+6))-. Además, utilicé mov en lugar de movzx en mi _startllamador porque el estado de salida proviene del byte bajo de arg a sys_exit(). El núcleo ignora los bytes más altos.
Peter Cordes

Supongo que eso funcionaría. Eso lleva la cuenta regresiva a 43 bytes y luego inserto setnz aldespués call in_subneten el contenedor.
Daniel Schepler

Sip. Es fácil imaginar que el caso de uso normal para esta función sería call/ je, en lugar de imprimir o transmitir el resultado. Como señalé en los "consejos", algunas convenciones de llamadas de llamadas al sistema ya hacen esto en la vida real (generalmente con CF = error).
Peter Cordes

1

Java 215 211 207 202 200 199 198 190 180 bytes

Long k,c;boolean a(String i,String s){return(b(i)^b(s))>>32-k.decode(s.split("/")[1])==0;}long b(String i){for(c=k=0l;c<4;k+=k.decode(i.split("[./]")[3+(int)-c])<<8*c++);return k;}

Salidas truepara la verdad y falsepara la falsedad.

Nota: Esto se usa en longlugar de intpara el posible desplazamiento a la derecha de 32.

Pruébalo en línea!

Guardado 1 byte gracias a ceilingcat

Guardado 10 bytes gracias a Peter Cordes


Esto no genera un "valor distinto y consistente" para falsey.
AdmBorkBork

Yo diría que es distinto y consistentemente distinto de cero, pero si ese no es el espíritu del desafío, puedo cambiarlo.
Poke

Un número entero de 64 bits admite desplazamientos a la izquierda en 32. Además, puede desplazar a la derechahost ^ net para desplazar los bits que desea eliminar, en lugar de crear una máscara. Pero supongo que Java necesita una comparación allí para crear un booleano a partir de un entero. Tal vez a !, porque no importa cuál de verdadero o falso produzca para qué salida. (Le pedí al OP que me aclarara si tenían la intención de excluir 0 / no cero, y me dijeron que sí, que estaban al tanto de las consecuencias de esa redacción:
Peter Cordes,

1
@PeterCordes Convertir todo en longhacer me pierde algunos bytes, pero lo compensé al poder eliminar el ternario y hacer el XOR como usted sugiere. Estoy comprobando qué más puedo jugar al golf antes de publicar
Poke

1

Carbón , 36 bytes

≔⪪S/θ≔I⊟θζ⊞θSUMθ÷↨I⪪ι.²⁵⁶X²⁻³²ζ⁼⊟θ⊟θ

Pruébalo en línea! El enlace es a la versión detallada del código. Toma la subred como primer parámetro y emite -solo si la dirección se encuentra dentro de la subred. Explicación:

≔⪪S/θ

Divide la subred /.

≔I⊟θζ

Quítate la máscara y échala al número entero.

⊞θS

Empuje la dirección a la matriz.

UMθ÷↨I⪪ι.²⁵⁶X²⁻³²ζ

Divida ambas direcciones ., conviértalas en enteros, interprete como base 256 y descarte los bits enmascarados.

⁼⊟θ⊟θ

Compara los dos valores.


1

Japt , 26 bytes

Ëq'/
ËÎq. Ë°¤ù8ì¯Ug1,1Ãr¶

Intentalo

-3 bytes gracias a @Shaggy!

La entrada es una matriz con 2 elementos [address, subnet]. Transpilado JS a continuación:

// U: implicit input array
// split elements in U on the / and
// save back to U using a map function
U = U.m(function(D, E, F) {
  return D.q("/")
});
// map the result of the previous operation
// through another function
U.m(function(D, E, F) {
  return D
    // get the address portion of the / split
    // value and split again on .
    .g().q(".")
    // map each octet through another function
    .m(function(D, E, F) {
      // convert the octet to a base 2 string
      // left padded to a length of 8
      return (D++).s(2).ù(8)
    })
    // join the base 2 octets
    .q()
    // take the left bits of the joined octets
    // determined by subnet size
    .s(0, U.g(1, 1))
})
  // at this point, the intermediate result
  // contains 2 masked values, reduce
  // using === to check for equality
  .r("===")


Interesante: no me di cuenta de que podía forzar una cadena a un número ++.
dana

Sí, tal como puedes en JS. Sin embargo, no sirve de nada si necesita reutilizar el valor original más adelante, pero es útil en ocasiones.
Shaggy

La necesidad de la coma en el gmétodo me está molestando; no puedo encontrar una forma de evitarlo en absoluto. Al menos no uno que te ahorre un byte.
Shaggy


0

C # (compilador interactivo de Visual C #) , 134 bytes

a=>a.Select(x=>x.Split('.','/').Take(4).Aggregate(0L,(y,z)=>y<<8|int.Parse(z))>>32-int.Parse(a[1].Split('/')[1])).Distinct().Count()<2

Pruébalo en línea!

Sentencia LINQ que toma una matriz de cadena de 2 elementos como entrada en [address, subnet]formato.

Cada quad punteado se convierte en 32 bits de largo utilizando la manipulación de bits. Los bits se desplazan a la derecha por el tamaño de la subred y los elementos se comparan para la igualdad.

Hubo un par de respuestas de C # en el momento en que se publicó esta respuesta, pero ninguna que utilizara una manipulación de bits pura.

// a: input array containing address and subnet
a=>a
  // iterate over input elements
  .Select(x=>x
    // split element on . and /
    .Split('.','/')
    // the subnet will have 5 elements,
    // we only want the parts before the /
    .Take(4)
    // use an aggregate function to convert dotted quad to 32 bits
    .Aggregate(0L,(y,z)=>y<<8|int.Parse(z))
    // shift bits of aggregate to the right
    >>
    // shift amount determined by subnet size
    32-int.Parse(a[1].Split('/')[1])
  )
  // test for equality by checking if number
  // of unique values is equal to 1
  .Distinct()
  .Count()<2

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.