Estou nas suas sub-redes, jogando seu código

17

Desafio

Dado um IPv4 addressna notação quad-dotted, e um IPv4 subnetna notação CIDR , determine se ele addressestá no subnet. Emita um valor distinto e consistente se estiver no subnete um valor distinto e consistente separado se não estiver no subnet. Os valores de saída não precisam necessariamente ser verdade / falsey no seu idioma.

Resumo da notação de sub-rede CIDR

Os endereços de rede IPv4 têm 32 bits de comprimento, divididos em quatro grupos de 8 bits para facilitar a leitura. A notação de sub-rede CIDR é uma máscara do número especificado de bits, iniciando à esquerda. Por exemplo, para uma /24sub - rede, isso significa que os 8 bits mais à direita do endereço estão disponíveis nessa sub-rede. Assim, dois endereços separados por no máximo 255e com a mesma máscara de sub-rede estão na mesma sub-rede. Observe que o CIDR válido possui todos os bits do host (lado direito) desabilitados (zeros).

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

Para outro exemplo, uma /32sub - rede especifica que todos os bits são a máscara de sub-rede, significando essencialmente que apenas um host é permitido por /32.

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

Exemplos:

Usando Truepara "na sub-rede" e Falsepara "não na sub-rede" como saída:

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

Regras e esclarecimentos

  • Como a análise de entrada não é o ponto interessante desse desafio, você garante endereços IPv4 válidos e máscaras de sub-rede.
  • A entrada e a saída podem ser fornecidas por qualquer método conveniente .
  • Você pode imprimir o resultado em STDOUT ou retorná-lo como resultado da função. Indique na sua submissão quais valores a saída pode assumir.
  • Um programa completo ou uma função são aceitáveis.
  • As brechas padrão são proibidas.
  • Isso é portanto todas as regras usuais de golfe se aplicam e o código mais curto (em bytes) vence.
AdmBorkBork
fonte
Temos que receber entradas no mesmo formato que seus casos de teste?
Modalidade de ignorância
1
@EmbodimentofIgnorance Você não precisa tomá-los como uma por linha, como nos exemplos, mas precisa usá-los como um quadriculado pontilhado e sub-rede pontilhada, como nos exemplos. (por exemplo, veja a resposta do JavaScript por Arnauld)
AdmBorkBork
Tudo bem separá-los por uma barra, por exemplo 10.0.0.1/10.0.0.0”/16?
Nick Kennedy
1
Concordo que você esteja correto, pois a notação CIDR descreve um endereço IP e um tamanho de sub-rede. Como em, 1.255.1.1/8é uma expressão CIDR válida , representando o host 1.255.1.1na rede 1.0.0.0com uma máscara de sub-rede de 255.0.0.0. No entanto, o desafio pede o número da rede e a sub-rede especificamente na notação CIDR, que 1.255.1.1/8não é uma combinação válida de número de rede e sub-rede.
640KB
1
Agora também precisamos de uma versão IPv6 desse desafio
Ferrybig

Respostas:

13

Python 3 (62 bytes)

Muito simples:

from ipaddress import*
lambda i,m:ip_address(i)in ip_network(m)
de qualquer maneira
fonte
9
Bom, mas o python também tem um built-in para reconhecer cabras ?
Benjamin Urquhart
3
É claro que o Mathematica tem um build-in para tudo - até para exoplanetas ! Nada pode bater isso ... Mas como você poderia ter visto, Python corresponde cabra-formace do Mathematica
agtoever
Gostaria de saber se um ip_adressobjeto e um ip_networkobjeto constituem any convenient method, possivelmente deixando o Python vencer, a menos que uma linguagem de golfe baseada em python os tenha como seus tipos?
meu pronome é monicareinstate
Você não o alcançará no intervalo de 20 bytes no Python normal. Somente a importação e o lambda já são maiores que a resposta Stax. Não é surpresa que os idiomas do golfe ganhem dos idiomas "normais" ... :-(
agtoever
@ alguém: Eu venci o Python com 53 bytes de código de máquina x86-64 . :) Não é uma linguagem tradicional de golfe, e a maior parte do tamanho do código está analisando string-> int manualmente. (host^net)>>(32-mask)é de apenas 10 bytes. Mas é meio caminho andado para tarefas que não envolvem listas de listas ou mapear uma função em uma lista, porque muitas operações escalares podem ser feitas com uma instrução de 2 ou 3 bytes e podem ser construídos loops em poucos bytes.
Peter Cordes
4

C # (Compilador 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 inclui using System;using System.Linq;

Experimente online!

Eu escrevi isso em JS assim que o desafio foi lançado, mas Arnauld me venceu com uma resposta muito melhor, então aqui está em C #.

Definitivamente muito espaço para jogar golfe.

Explicação:

A função consiste em uma subfunção chamada 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;
    }
);

Essa subfunção divide o endereço IP ., converte cada número em uma seqüência de caracteres binária, coloca cada uma das strings à esquerda com 08 bits de comprimento e concatena as seqüências de caracteres em uma seqüência de caracteres binária de 32 bits.

Isso é feito imediatamente no local a=h(a);especificado no endereço IP.
Em seguida, dividimos a máscara de sub-rede em um endereço IP e um número de máscara comc=b.Split('/');

O componente Endereço IP também é passado através de nossa sub-função: b=h(c[0]);e o número da máscara é analisado para um número inteiro:var d=int.Parse(c[1]);

Finalmente, pegamos os primeiros dbits das duas cadeias binárias (onde destá o número da máscara) e os comparamos:return a.Substring(0,d)==b.Substring(0,d);

Skidsdev
fonte
1
Cansado demais para resolver isso, então eu apenas joguei o seu para você
Data de
1
Na verdade, esqueci o PadLeft nisso também Experimente online!
Dados expirados
Muitas otimizações. É um prazer informar que você rPadé um incorporador de strings. link pastebin para o link TIO que é muito longo sozinho
meu pronome é monicareinstate
2
@ alguém Pequeno FYI: abreviadores de URL como tinyurl.com são permitidos em comentários neste SE, ao contrário da maioria. :)
Kevin Cruijssen
1
188 - tinyurl.com/y6xfkbxt - dicas de encurtamento de URL agradável @KevinCruijssen
dana
4

Shell Linux POSIX (com net-tools / iputils) (34 bytes sem finalização, 47 bytes com finalização)

O que é mais adequado para analisar máscaras e endereços de rede do que os próprios utilitários de rede? :)

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

Aviso: o script é potencialmente prejudicial à sua conectividade com a Internet, execute com cuidado.

Entrada: o script usa o endereço IP testado como primeiro argumento e a sub-rede testada. como segundo argumento.

Saída: o script retornará um valor de verdade (0) se o primeiro argumento do script pertencer à sub-rede indicada no segundo argumento. Caso contrário, nunca será encerrado.

Pressupostos: o script deve ser executado como usuário raiz, em um ambiente limpo ( ou seja , nenhuma outra rota do buraco negro foi definida pelo administrador e, se uma instância anterior do script foi executada, a rota do buraco negro criada foi removida ) O script também assume uma "conexão com a Internet em funcionamento" ( ou seja , uma rota padrão válida está presente).


Explicação:

Criamos uma rota de buraco negro para a sub-rede especificada. Em seguida, testamos a conectividade com o endereço IP fornecido usando ping . Se o endereço não pertencer à sub-rede (e como assumimos uma conexão com a Internet configurada corretamente), o ping tentará enviar pacotes para esse endereço. Observe que, se esse endereço realmente responder, não importa, pois o ping continuará tentando para sempre. Por outro lado, se o endereço pertencer à sub-rede, o ping falhará com ENETUNREACH e retornará 2 e, como negamos o comando, o script será bem-sucedido.


Exemplo

Teste se 5.5.5.5 pertence 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...]

(Limpe sudo ip route del 8.8.8.0/24após executar o comando).

Teste se 5.5.5.5 pertence a 5.5.5.0/24:

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

(Limpe sudo ip route del 5.5.5.0/24após executar o comando).

Teste se 8.8.8.8 pertence 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...]

(Limpe sudo ip route del 5.5.5.0/24após executar o comando).


Versão de 47 bytes, se não permitirmos scripts que não terminem

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

De acordo com o comentário de @ Grimy, aqui está a versão que sempre termina e retorna 0 (verdadeiro) se o endereço estiver na sub-rede e 1 (falso) caso contrário. Fazemos o término do ping com o -c1sinalizador que limita o número de pacotes enviados a 1. Se o endereço respondeu, o ping retornará 0 e, caso contrário, o ping retornará 1. Somente se o endereço pertencer à sub-rede com o buraco negro, o ping retornará 2, que é, portanto, contra o que testamos no último comando.

yoann
fonte
3
Embora inteligente, isso não atende ao requisito de gerar um valor distinto e consistente se o endereço não estiver na sub-rede (a execução permanente não conta como saída , veja também isso ).
Grimmy
1
@ Grimy: Mas ele não roda silenciosamente para sempre, então apenas o seu segundo link se aplica, e não o primeiro. Também acho pingque morreria do SIGPIPE se estivesse rodando com o stdout + stderr canalizado para outro programa, e o leitor fechou o pipe. E esse é o caso de uso mais provável, porque o status de saída pode ser bem-sucedido de qualquer maneira (se adicionarmos uma -c1opção para executar ping para definir a contagem) var=$(/a.sh). você precisaria de um leitor que parasse depois de decidir, em vez de ler toda a saída e depois analisá-la.
Peter Cordes
@ Grimy Fair point (embora, para o argumento, eu possa dizer que temos dois valores consistentes aqui, uma vez pingque terminará em menos de, digamos, um segundo no caso de um endereço oculto). Eu adicionei uma versão final para 13 bytes extras! :)
yoann
3

JavaScript (ES6), 82 bytes

Toma entrada como (address)(subnet). Retorna um 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))

Experimente online!

Arnauld
fonte
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);}

Experimente online!

Luis felipe De jesus Munoz
fonte
2
Nos divertimos jogando golfe (Ty!):function($i,$r){return!((ip2long($i)^ip2long(strtok($r,'/')))>>32-strtok(_));}
Christoph
@Christoph muito bom! Nunca me ocorreu que você pudesse usar qualquer token para a segunda chamada strtok(). O seu é 4 bytes mais curto do que minha resposta muito semelhante abaixo. Adereços!
640KB
@Christoph Você deve postar sua solução como uma resposta separada, pois é melhor que a minha.
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]);}

(Testado no x86_64 Ubuntu 18.04 usando powerpc64-linux-gnu-gcc -static e qemu-user.)

O programa pega as duas linhas na entrada padrão e, como código de saída, retorna 1 se o endereço corresponder e 0 se não corresponder. (Portanto, isso depende da especificação que não exige um valor verdadeiro para uma correspondência e um valor de falsey para uma incompatibilidade.) Observe que, se você estiver executando interativamente, precisará sinalizar EOF ( ^D) três vezes após entrar na segunda linha.

Isso depende do PowerPC ser big-endian e também dessa plataforma retornar 0 para deslocar para a direita um valor não assinado de 32 bits por 32. Ele lê os octetos em valores não assinados um a um, juntamente com o comprimento da máscara de rede em outro byte ; então pega o xor dos dois endereços de 32 bits não assinados e desloca os bits irrelevantes. Por fim, aplica-se !a satisfazer o requisito de retornar apenas dois valores distintos.

Nota: pode ser possível raspar dois bytes, substituindo u+3com pe exigindo compilação com -O0. Mas isso é viver de maneira mais perigosa do que eu gostaria.

Agradecemos a Peter Cordes pela inspiração para esta solução.


C mais portátil, 186 171 167 bytes

Aqui vou preservar uma versão mais portátil que executa 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 pega as duas linhas na entrada padrão e retorna o código de saída 1 se o endereço estiver na sub-rede e 0 se não estiver. (Portanto, isso depende da especificação que não exige um valor verdadeiro para correspondências e um valor de falsey para não correspondências.)

Um detalhamento da expressão principal:

  • a^e, b^f, c^g, d^hCalcula o XOR do endereço e a máscara byte-por-byte.
  • (((a^e)<<8|b^f)<<8|c^g)<<8|d^h depois os combina em um único valor de 32 bits não assinado por um método semelhante ao Horner.
  • ...>>32-nentão desloca os bits da diferença xor que não são relevantes para a máscara de sub-rede (lembrando que -tem maior precedência em C que <<)
  • Porém, existe uma pegadinha: se n = 0, ~0U<<32o comportamento indefinido será assumido como unsignedsendo de 32 bits (que está em praticamente todas as plataformas atuais). Por outro lado, se n = 0, qualquer endereço corresponderá e, portanto n&&..., fornecerá o resultado correto (aproveitando o comportamento de curto-circuito de &&).
  • Por fim, para atender ao requisito de que a saída possa ter apenas um dos dois valores, aplicamos !a saída 0 ou 1.

-15 bytes devido a comentários de ceilingcat e AdmBorkBork

-4 bytes devido a comentário de Peter Cordes

Daniel Schepler
fonte
1
O uso de códigos de saída para retornar valores é um dos métodos de E / S padrão e, portanto, é permitido.
AdmBorkBork
@ceilingcat Claro, que tolice da minha parte sentir falta disso.
Daniel Schepler
@AdmBorkBork OK, obrigado, eu mudei para usar o código de saída.
Daniel Schepler
idéia: direcionar uma implementação C little-endian ou big-endian (code-golf não requer código portátil) e ponteiros de saída tipo-pun nos bytes de um unsigned. por exemplo, com char*p=&aentão p++,p++,p++,...ou p--,...como scanf args. A string de formato precisaria ser "%hhu.%hhu...", portanto, é uma troca significativa entre esse tamanho extra vs. declarar menos vars e ser capaz de fazer(a^b)>>(32-count)
Peter Cordes
1
@ PeterCordes Sim, a mudança certa funciona, obrigado.
Daniel Schepler
2

Stax , 22 bytes

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

Execute e depure

Os parâmetros de entrada são separados por espaço na entrada padrão.

Descompactado, não jogado e comentado, parece com isso.

'/:/~       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?

Execute este

recursivo
fonte
2

função de código de máquina x86-64, 53 48 bytes

changelog:

  • -2 jzdurante o turno em vez de usar um turno de 64 bits para lidar com o >>(32-0)caso especial.
  • -3 retorna em ZF em vez de AL, economizando 3 bytes para a setnz al.

(Veja também a resposta de código de máquina de Daniel Schepler de 32 bits com base nisso, que evoluiu para usar algumas outras idéias que tínhamos. Estou incluindo minha versão mais recente disso na parte inferior desta resposta.)


Retorna ZF = 0 para o host que não está na sub-rede, ZF = 1 para na sub-rede, para que você possa ramificar o resultado comje host_matches_subnet

É possível chamar com a convenção de chamada do System V x86-64 como
bool not_in_subnet(int dummy_rdi, const char *input_rsi);se você adicionasse setnz al.

A sequência de entrada contém o host e a rede, separados por exatamente 1 caractere sem dígito. A memória após o final da largura do CIDR deve conter pelo menos 3 bytes sem dígito antes do final de uma página. (Na maioria dos casos, não deve ser um problema, como para um argumento cmdline.) A versão de 32 bits de Daniel não tem essa limitação.

Executamos o mesmo loop de análise quad-dotted-quad três vezes, obtendo os dois endereços IPv4 e obtendo o /masknúmero inteiro no byte alto de um dword. (É por isso que deve haver memória legível após o /mask, mas não importa se há dígitos ASCII.)

Fazemos (host ^ subnet) >> (32-mask)para mudar os bits do host (os que podem ser incompatíveis), deixando apenas a diferença entre a sub-rede e o host. Para resolver o /0caso especial em que precisamos mudar em 32, saltamos sobre o deslocamento na contagem = 0. ( neg cldefine ZF, no qual podemos ramificar e deixar o valor de retorno se não mudarmos.) Observe que 32-mask mod 32 = -maskas mudanças escalares x86 mascaram sua contagem por & 31ou & 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

(não atualizado com a versão mais recente) Experimente online!

incluindo um _startque chama argv[1]e retorna um status de saída.

## 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 bem se você passar uma linha de comando arg contendo uma nova linha em vez de um espaço. Mas tem que ser em vez disso , não tão bem.


função de código de máquina x86 de 32 bits, 38 bytes

Faça 9 inteiro -> uint8_t analise e "empurre" eles na pilha, onde os exibimos como dwords ou usamos o último ainda no CL. Evita a leitura além do final da string.

Além disso, decpossui apenas 1 byte no 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

Chamador de teste

   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
Peter Cordes
fonte
Estou curioso para saber como seria a contagem de 32 bytes de asm se, em vez do cmp/jccque você mencionou, fizesse algo como xor edx,edx;neg cl;cmovz eax,edx;shr eax,cl- ou talvez você já tenha um valor 0 em algum lugar. (E então você não precisaria das sub cl,32instruções.)
Daniel Schepler
1
Sim, parece que edideve ser 0 quando o loop sair, portanto, xor eax,edx;neg cl;cmovz eax,edi;shr eax,cldeve funcionar.
Daniel Schepler
1
Se eu contei as coisas direito, cmove eax,editem 3 bytes, que é uma lavagem sobre os removidos sub cl,32e shr cl,eaxsalva um byte shr cl,raxe 32 bits dec edisalva um byte sobre 64 bits dec edi. Minha montagem então fornece .byte 0x33(na sintaxe GNU binutils) = 51 para in_subnet.size.
Daniel Schepler
Boa ideia, obrigado. (Na sintaxe da Intel shr eax,cl, shr %cl, %eaxem comparação com a AT&T, seu último comentário reverteu isso.) É um pouco complicado atualizar as respostas do código da máquina (e portar o _startchamador e re-descrever a convenção de chamada no modo de 32 bits.) .), para que eu não consiga resolver isso. Sentindo-se preguiçoso hoje. >. <
Peter Cordes
1
Eu apenas tentei implementar o comentário que você colocou na minha resposta sobre como se livrar do loop duplo e, em vez disso, armazenar em variáveis ​​de pilha - e mesmo com o código extra para inicializar o ponteiro de edigravação, escrever a saída etc., acabou economizando 2 bytes na rede. (Pelo menos uma vez eu percebi que push ecx;push ecx;push ecxera mais curto do que sub esp,12; e parecia ser uma lavagem se eu predecedi edie usei std;stosb;cldou se apenas armazenei usando dec edi;mov [edi],al.)
Daniel Schepler
1

Gelatina , 23 bytes

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

Experimente online!

Link monádico que pega o endereço e a sub-rede separados por uma barra e retorna 1 para verdadeiro e 0 para falso.

Agradecemos a @gwaugh por apontar uma falha no original - ela falhou em garantir que a lista binária tivesse 32 comprimentos.

Nick Kennedy
fonte
1

Perl 5 -Mbigint -MSocket=:all -p , 72 bytes

sub c{unpack N,inet_aton pop}<>=~/(.*)\/(.*)/;$_=c($_)-&c($1)<2**(32-$2)

Experimente online!

Xcali
fonte
1

05AB1E , 21 bytes

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

Leva a sub-rede antes do endereço.

Experimente online ou verifique todos os casos de teste .

Explicação:

'/¡              '# 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)
Kevin Cruijssen
fonte
1

R 120 bytes

uma função - colei ".32" no primeiro termo

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

e apenas por diversão:

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

que é 56 bytes

Zahiro Mor
fonte
1

PHP ,75 73, 71 bytes

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

Uma bifurcação da resposta de @Luis felipe De jesus Munoz , como uma autônoma recebendo informações dos argumentos da linha de comando. Saídas '1'para Truthy, ''(string vazia) 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

Experimente online!

-2 bytes emprestando o pequeno truque de @Christoph para strtok(). Sua resposta ainda é mais curta!

640KB
fonte
1

função de montagem x86, 49. 43 bytes

Isso é publicado principalmente para atender à solicitação de Peter Cordes da versão revisada que eu criei. Provavelmente pode desaparecer uma vez / se ele incorporá-lo em sua resposta.

Essa função espera esiapontar para uma sequência de entrada, com as partes de endereço e sub-rede separadas por um espaço ou por um caractere de nova linha, e o valor de retorno está no sinalizador ZF (que, por definição, possui apenas dois valores possíveis).

 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

E a parte do wrapper x86 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 devido à sugestão de Peter Cordes para retornar o valor em ZF.

Daniel Schepler
fonte
Eu acho que eu poderia salvar um byte removendo o último xor edx,edxe substituindo cmovz eax,edxpor jz .nonzero; xor eax,eax; .nonzero:. cmovzainda ganha se tivermos convocado convenção ebx=0.
Daniel Schepler
Podemos apenas jzpassar shrpara o setz ou o ret? Podemos trocar o setnzpara setze retornar 1para uma partida, se isso ajudar. Ou até mesmo diga que nosso valor de retorno é ZF. Eu deveria ter feito isso na minha resposta. (Mas acho que não podemos justificar exigir que o chamador crie constantes para nós, como ebx=0. Minha resposta em Dicas para jogar golfe em código de máquina x86 / x64 argumenta que esticaria muito demais uma convenção de chamada personalizada.
Peter Cordes
BTW, eu uso cutpara remover algumas colunas da lista de saída NASM porque todas as minhas instruções são curtas: nasm -felf foo.asm -l/dev/stdout | cut -b -34,$((34+6))-. Além disso, usei mov em vez de movzx no meu _startchamador porque o status de saída vem do byte baixo do arg para sys_exit(). O kernel ignora os bytes mais altos.
Peter Cordes
Eu acho que isso funcionaria. Isso leva a contagem até 43 bytes e depois insiro setnz aldepois call in_subnetno wrapper.
Daniel Schepler
Sim. É fácil imaginar o caso de uso normal para essa função call/ je, em vez de imprimir ou repassar o resultado. Como apontei nas "dicas", algumas convenções de chamada de sistema já fazem isso na vida real (geralmente com CF = erro).
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;}

Saídas truepara verdade e falsefalsidade.

Nota: Isso usa em longvez de intpara o possível deslocamento à direita de 32.

Experimente online!

Guardado 1 byte graças a ceilingcat

Economizou 10 bytes graças a Peter Cordes

Cutucar
fonte
Isso não gera um "valor distinto e consistente" para o falsey.
AdmBorkBork
Eu diria que é distintamente e consistentemente diferente de zero, mas se esse não for o espírito do desafio, eu posso mudá-lo.
Puxão
Um número inteiro de 64 bits suporta turnos à esquerda em 32. Além disso, você pode alternar com a direitahost ^ net para alterar os bits que deseja remover, em vez de realmente criar uma máscara. Mas acho que o Java precisa de uma comparação para criar um booleano a partir de um número inteiro. Talvez a !, porque não importa qual verdadeiro ou falso você produz para qual saída. (Solicitei esclarecimentos ao OP sobre se pretendiam excluir 0 / diferente de zero, e eles disseram que estavam cientes das consequências dessa redação:
Peter Cordes
1
@ PeterCordes Converter tudo para longme perder alguns bytes, mas eu o compenso removendo o ternário e fazendo o XOR como você sugere. Estou verificando o que mais posso jogar golfe antes de postar
Poke
1

Carvão , 36 bytes

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

Experimente online! Link é a versão detalhada do código. Toma a sub-rede como o primeiro parâmetro ee produz -somente se o endereço estiver dentro da sub-rede. Explicação:

≔⪪S/θ

Divida a sub-rede /.

≔I⊟θζ

Remova a máscara e jogue-a no número inteiro.

⊞θS

Envie o endereço para a matriz.

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

Divida os dois endereços ., converta-os em números inteiros, interprete como base 256 e descarte os bits mascarados.

⁼⊟θ⊟θ

Compare os dois valores.

Neil
fonte
1

Japonês , 26 bytes

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

Tente

-3 bytes graças a @Shaggy!

Entrada é uma matriz com 2 elementos [address, subnet]. JS transpilado abaixo:

// 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("===")
dana
fonte
26 bytes
Shaggy
Interessante - não sabia que era possível coagir uma string a um número ++.
dana
Sim, assim como você pode em JS. Porém, não adianta, se você precisar reutilizar o valor original mais tarde, mas é útil ocasionalmente.
Shaggy
A necessidade de vírgula no gmétodo está me irritando; não consigo descobrir uma maneira de contornar isso. Pelo menos não um que economize um byte.
Shaggy
0

C # (compilador interativo do Visual C #) , 187 bytes

a=>{var b=a.Select(x=>x.Split(".").SelectMany(g=>Convert.ToString(int.Parse(g.Split("/")[0]),2).PadLeft(8)).Take(int.Parse(a[1].Split("/")[1])));return b.First().SequenceEqual(b.Last());}

Definitivamente, eu posso jogar mais isso.

Experimente online!

Modalidade de ignorância
fonte
0

C # (compilador interativo do 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

Experimente online!

Instrução LINQ que usa uma matriz de cadeia de 2 elementos como entrada no [address, subnet]formato.

Cada quadra pontilhada é convertida em 32 bits de comprimento usando a manipulação de bits. Os bits são deslocados à direita pelo tamanho da sub-rede e os elementos são comparados quanto à igualdade.

Havia algumas respostas de C # no momento em que essa resposta foi postada, mas nenhuma que usava manipulação 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
dana
fonte