Je suis dans vos sous-réseaux, je joue à votre code

17

Défi

Étant donné un IPv4 addressen notation quadrillée et un IPv4 subneten notation CIDR , déterminez si le addressest dans le subnet. Sortez une valeur distincte et cohérente si elle est dans le subnet, et une valeur distincte distincte et cohérente si elle n'est pas dans le subnet. Les valeurs de sortie ne doivent pas nécessairement être véridiques / falsey dans votre langue.

Brève introduction à la notation du sous-réseau CIDR

Les adresses réseau IPv4 ont une longueur de 32 bits, divisées en quatre groupes de 8 bits pour faciliter la lecture. La notation de sous-réseau CIDR est un masque du nombre spécifié de bits, commençant à l'extrême gauche. Par exemple, pour un /24sous - réseau, cela signifie que les 8 bits les plus à droite de l'adresse sont disponibles dans ce sous-réseau. Ainsi, deux adresses qui sont séparées par au plus 255et qui ont le même masque de sous-réseau se trouvent dans le même sous-réseau. Notez que les CIDR valides ont tous les bits d'hôte (le côté droit) non définis (zéros).

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

Pour un autre exemple, un /32sous - réseau spécifie que tous les bits sont le masque de sous-réseau, ce qui signifie essentiellement qu'un seul hôte est autorisé par /32.

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

Exemples:

Utiliser Truepour "dans le sous-réseau" et Falsepour "pas dans le sous-réseau" en sortie:

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

Règles et clarifications

  • Étant donné que l'analyse des entrées n'est pas le point intéressant de ce défi, vous êtes assuré d'obtenir des adresses IPv4 et des masques de sous-réseau valides.
  • L'entrée et la sortie peuvent être fournies par n'importe quelle méthode pratique .
  • Vous pouvez imprimer le résultat dans STDOUT ou le renvoyer en tant que résultat de fonction. Veuillez indiquer dans votre soumission les valeurs que la sortie peut prendre.
  • Un programme complet ou une fonction sont acceptables.
  • Les failles standard sont interdites.
  • Il s'agit de donc toutes les règles de golf habituelles s'appliquent et le code le plus court (en octets) l'emporte.
AdmBorkBork
la source
Doit-on prendre les entrées dans le même format que vos cas de test?
Incarnation de l'ignorance
1
@EmbodimentofIgnorance Vous n'avez pas à les prendre comme un par ligne comme dans les exemples, mais vous devez les prendre comme un quadrilatère et un sous-réseau en pointillés comme dans les exemples. (par exemple, voir la réponse JavaScript d'Arnauld)
AdmBorkBork
Est-il acceptable de les séparer par une barre oblique, par exemple 10.0.0.1/10.0.0.0”/16?
Nick Kennedy
1
@Poke Je suis d'accord que vous avez raison en ce que la notation CIDR décrit une adresse IP et une taille de sous-réseau. Comme dans, 1.255.1.1/8est une expression CIDR valide , représentant l'hôte 1.255.1.1au sein du réseau 1.0.0.0avec un masque de sous-réseau de 255.0.0.0. Cependant, le défi demande le numéro de réseau et le sous-réseau spécifiquement en notation CIDR, qui 1.255.1.1/8n'est pas une combinaison de numéro de réseau et de sous-réseau valide.
640 Ko
1
Maintenant, nous avons également besoin d'une version IPv6 de ce défi
Ferrybig

Réponses:

13

Python 3 (62 octets)

Très simple:

from ipaddress import*
lambda i,m:ip_address(i)in ip_network(m)
toujours
la source
9
Bien, mais le python a-t-il une fonction intégrée pour reconnaître également les chèvres ?
Benjamin Urquhart
3
Bien sûr, Mathematica a une fonction intégrée pour tout - même pour les exoplanètes ! Rien ne peut battre cela ... Mais comme vous auriez pu le voir, Python correspond à la chèvre-forme de Mathematica
agtoever
Je me demande si un ip_adressobjet et un ip_networkobjet constituent any convenient method, laissant peut-être gagner Python, à moins qu'un langage de golf basé sur python n'ait ces types?
mon pronom est monicareinstate
Vous ne l'obtiendrez pas dans la plage de 20 octets en Python normal. Seuls l'importation et lambda sont déjà plus longs que la réponse Stax. Il n'est pas surprenant que les langues de golf gagnent des langues "normales" ... :-(
agtoever
@someone: J'ai battu Python avec 53 octets de code machine x86-64 . :) Ce n'est pas un langage de golf traditionnel, et la plus grande partie de la taille du code analyse manuellement string-> int. (host^net)>>(32-mask)n'est que de 10 octets. Mais c'est à mi-chemin entre les tâches n'impliquant pas de listes de listes ou mappant une fonction sur une liste, car de nombreuses opérations scalaires peuvent être effectuées avec une instruction de 2 ou 3 octets, et des boucles peuvent être construites autour de choses en quelques octets.
Peter Cordes
4

C # (Visual C # Compiler) , 250 + 31 = 281 octets

(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 comprend using System;using System.Linq;

Essayez-le en ligne!

J'ai écrit cela dans JS dès que le défi a été publié, mais Arnauld m'a battu au poing avec une bien meilleure réponse, donc ici c'est en C # à la place.

Certainement beaucoup de place pour le golf.

Explication:

La fonction se compose d'une sous-fonction appelée 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;
    }
);

Cette sous-fonction divise l'adresse IP ., convertit chaque nombre en une chaîne binaire, remplit chaque chaîne de gauche avec 0une longueur de 8 bits, puis concatène les chaînes en une chaîne binaire de 32 bits.

Cela se fait immédiatement sur place avec a=h(a);l'adresse IP donnée.
Nous avons ensuite divisé le masque de sous-réseau en une adresse IP et un numéro de masque avecc=b.Split('/');

Le composant d'adresse IP est également transmis via notre sous-fonction: b=h(c[0]);et le numéro de masque est analysé en un entier:var d=int.Parse(c[1]);

Enfin, nous prenons les premiers dbits des deux chaînes binaires (où dest le numéro de masque) et les comparons:return a.Substring(0,d)==b.Substring(0,d);

Skidsdev
la source
1
Trop fatigué pour résoudre
Données expirées
1
En fait, j'ai oublié PadLeft aussi. Essayez-le en ligne!
Données expirées
Beaucoup d'optimisations. Je suis heureux de vous informer que votre rPadest une chaîne intégrée. lien pastebin vers le lien TIO qui est trop long seul
mon pronom est monicareinstate
2
@someone Small FYI: les raccourcisseurs d'URL comme tinyurl.com sont autorisés dans les commentaires sur cette SE, contrairement à la plupart. :)
Kevin Cruijssen
1
188 - tinyurl.com/y6xfkbxt - bons conseils de raccourcissement d'url @KevinCruijssen
dana
4

Shell Linux POSIX (avec net-tools / iputils) (34 octets sans terminaison, 47 octets avec terminaison)

Qu'est-ce qui convient le mieux pour analyser les masques et les adresses réseau que les utilitaires réseau eux-mêmes? :)

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

Attention: le script peut potentiellement endommager votre connectivité Internet, veuillez l'exécuter avec précaution.

Entrée: le script prend l'adresse IP testée comme premier argument et le sous-réseau testé. comme deuxième argument.

Sortie: le script renvoie une valeur véridique (0) si le premier argument du script appartient au sous-réseau indiqué dans le deuxième argument. Sinon, il ne se terminera jamais.

Hypothèses: le script doit être exécuté en tant qu'utilisateur root, dans un environnement propre ( c'est-à - dire qu'aucune autre route blackhole n'a été définie par l'administrateur, et si une instance précédente du script a été exécutée, la route blackhole qu'il a créée a été supprimée ). Le script suppose également une "connexion Internet fonctionnelle" ( c'est -à- dire qu'une route par défaut valide est présente).


Explication:

Nous créons une route de trou noir vers le sous-réseau spécifié. Nous testons ensuite la connectivité à l'adresse IP fournie en utilisant ping . Si l'adresse n'appartient pas au sous-réseau (et puisque nous supposons une connexion Internet correctement définie), ping essaiera d'envoyer des paquets à cette adresse. Notez que la réponse de cette adresse n'a pas d'importance, car ping continuera d'essayer indéfiniment. Inversement, si l'adresse appartient au sous-réseau, le ping échouera avec ENETUNREACH et renverra 2, et puisque nous avons annulé la commande, le script réussira.


Exemple

Vérifier si 5.5.5.5 appartient à 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...]

(Nettoyer avec sudo ip route del 8.8.8.0/24 après avoir exécuté la commande).

Testez si 5.5.5.5 appartient à 5.5.5.0/24:

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

(Nettoyer avec sudo ip route del 5.5.5.0/24 après avoir exécuté la commande).

Testez si 8.8.8.8 appartient à 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...]

(Nettoyer avecsudo ip route del 5.5.5.0/24 après avoir exécuté la commande).


Version 47 octets si nous interdisons les scripts sans terminaison

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

Selon le commentaire de @ Grimy, voici la version qui se termine toujours, et retourne 0 (véridique) si l'adresse est dans le sous-réseau, et 1 (faux) sinon. Nous faisons terminer ping avec l' -c1indicateur qui limite le nombre de paquets envoyés à 1. Si l'adresse a répondu, ping renverra 0, et sinon, ping renverra 1. Seulement si l'adresse appartient au sous-réseau blackholed, ping renverra 2, qui est donc ce contre quoi nous testons dans la dernière commande.

yoann
la source
3
Bien qu'intelligent, cela ne répond pas à l'exigence de sortie d'une valeur distincte et cohérente si l'adresse n'est pas dans le sous-réseau (l' exécution pour toujours ne compte pas comme une sortie , voir aussi ceci ).
Grimmy
1
@Grimy: Mais il ne s'exécute pas en silence pour toujours, donc seul votre 2e lien s'applique, pas le premier. Je pense aussi que pingje mourrais de SIGPIPE s'il fonctionnait avec stdout + stderr canalisé dans un autre programme, et que le lecteur fermait le tuyau. Et c'est le cas d'utilisation le plus probable, car le statut de sortie peut être réussi dans tous les cas (si nous avons ajouté une -c1option de ping pour définir le nombre.) Mais bien sûr, la lecture de sa sortie avec var=$(/a.sh)échouerait; vous auriez besoin d'un lecteur qui s'est arrêté après avoir décidé, plutôt que de lire la sortie entière et de la regarder.
Peter Cordes
@Grimy Fair point (bien que, pour les besoins de l'argument, je puisse dire que nous avons ici deux valeurs cohérentes, car pingse terminera en moins d'une seconde, par exemple, en cas d'adresse noire). J'ai ajouté une version de terminaison pour 13 octets supplémentaires! :)
yoann
3

JavaScript (ES6), 82 octets

Prend l'entrée comme (address)(subnet). Renvoie une valeur booléenne.

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

Essayez-le en ligne!

Arnauld
la source
3

PHP , 101 92 88 octets

-13 octets de @gwaugh

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

Essayez-le en ligne!

Luis felipe De jesus Munoz
la source
2
Je me suis amusé à jouer au golf (Ty!):function($i,$r){return!((ip2long($i)^ip2long(strtok($r,'/')))>>32-strtok(_));}
Christoph
@Christoph très sympa! Il ne m'est jamais venu à l'esprit que vous pourriez simplement utiliser n'importe quel jeton pour le deuxième appel à strtok(). Le vôtre est 4 octets plus court que ma réponse très similaire ci-dessous. Accessoires!
640 Ko
@Christoph Vous devez publier votre solution en tant que réponse séparée car elle est meilleure que la mienne.
Luis felipe De jesus Munoz
3

PowerPC / PPC64 C, 116 114 octets

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

(Testé sur x86_64 Ubuntu 18.04 à l'aide de powerpc64-linux-gnu-gcc -static et qemu-user.)

Le programme prend les deux lignes sur l'entrée standard et comme code de sortie, il renvoie 1 si l'adresse correspond et 0 si ce n'est pas le cas. (Cela dépend donc de la spécification ne nécessitant pas de valeur véridique pour une correspondance et une valeur de falsey pour une non-correspondance.) Notez que si vous exécutez de manière interactive, vous devrez signaler EOF ( ^D) trois fois après avoir entré la deuxième ligne.

Cela repose sur PowerPC étant big-endian, et également sur cette plate-forme renvoyant 0 pour décaler à droite une valeur non signée de 32 bits par 32. Il lit les octets en valeurs non signées un par un, avec la longueur du masque de réseau dans un autre octet ; puis il prend le xor des deux adresses 32 bits non signées et décale les bits non pertinents. Enfin, il s'applique !pour satisfaire à l'exigence de ne renvoyer que deux valeurs distinctes.

Remarque: Il peut être possible de raser deux octets en remplaçant u+3par pet en exigeant une compilation avec -O0. C'est vivre plus dangereusement que je ne le pense, cependant.

Merci à Peter Cordes pour l'inspiration de cette solution.


Plus portable C, 186 171 167 octets

Ici, je vais conserver une version plus portable qui fonctionne sur 167 octets.

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

Ce programme prend les deux lignes sur l'entrée standard et renvoie le code de sortie 1 si l'adresse est dans le sous-réseau et 0 si ce n'est pas le cas. (Cela dépend donc de la spécification ne nécessitant pas une valeur véridique pour les correspondances et une valeur de falsey pour les non-correspondances.)

Une ventilation de l'expression principale:

  • a^e, b^f, c^g, d^hCalcule le OU exclusif de l'adresse et le masque octet par octet.
  • (((a^e)<<8|b^f)<<8|c^g)<<8|d^h puis les combine en une seule valeur 32 bits non signée par une méthode de type Horner.
  • ...>>32-ndécale ensuite les bits de la différence xor qui ne sont pas pertinents pour le masque de sous-réseau (en gardant à l'esprit que la -priorité en C est plus élevée que <<)
  • Il y a cependant un problème: si n = 0, ~0U<<32cela donnera un comportement indéfini en supposant unsigned32 bits (ce qu'il est sur pratiquement toutes les plates-formes actuelles). D'un autre côté, si n = 0, alors n'importe quelle adresse correspondra, donc n&&...donnera le résultat correct (en profitant du comportement de court-circuitage de &&).
  • Enfin, pour répondre à l'exigence selon laquelle la sortie ne peut être que l'une des deux valeurs, nous appliquons la !sortie 0 ou 1.

-15 octets en raison des commentaires de plafondcat et AdmBorkBork

-4 octets en raison du commentaire de Peter Cordes

Daniel Schepler
la source
1
L'utilisation de codes de sortie pour renvoyer des valeurs est l' une des méthodes d'E / S par défaut et est donc autorisée.
AdmBorkBork
@ceilingcat Bien sûr, quelle idiotie de ma part de manquer ça.
Daniel Schepler
@AdmBorkBork OK, merci, je l'ai changé pour utiliser le code de sortie.
Daniel Schepler
idée: cibler une implémentation C en petit ou en gros (le code-golf ne nécessite pas de code portable) et taper les pointeurs de sortie sur les octets d'un unsigned. par exemple avec char*p=&athen p++,p++,p++,...ou p--,...as scanf args. La chaîne de format devrait "%hhu.%hhu..."cependant être , c'est donc un compromis important entre cette taille supplémentaire et la déclaration de moins de vars et la possibilité de le faire(a^b)>>(32-count)
Peter Cordes
1
@PeterCordes Yup, le bon décalage fonctionne, merci.
Daniel Schepler
2

Stax , 22 octets

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

Exécuter et déboguer

Il prend les paramètres d'entrée séparés par des espaces sur l'entrée standard.

Déballé, non golfé et commenté, il ressemble à ceci.

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

Exécutez celui-ci

récursif
la source
2

Fonction de code machine x86-64, 53 48 octets

journal des modifications:

  • -2 jzsur le décalage au lieu d'utiliser un décalage 64 bits pour gérer le >>(32-0)cas spécial.
  • -3 retourne en ZF au lieu de AL, économisant 3 octets pour a setnz al.

(Voir également la réponse du code machine de 32 bits de Daniel Schepler basée sur cela, qui a ensuite évolué pour utiliser d'autres idées que nous avions. J'inclus ma dernière version de cela au bas de cette réponse.)


Renvoie ZF = 0 pour l'hôte qui n'est pas dans le sous-réseau, ZF = 1 pour dans le sous-réseau, afin que vous puissiez vous connecter au résultat avecje host_matches_subnet

Appelable avec la convention d'appel System V x86-64 comme
bool not_in_subnet(int dummy_rdi, const char *input_rsi);si vous ajoutiez setnz al.

La chaîne d'entrée contient à la fois l'hôte et le réseau, séparés par exactement 1 caractère non numérique. La mémoire suivant la fin de la largeur CIDR doit contenir au moins 3 octets non numériques avant la fin d'une page. (Cela ne devrait pas être un problème dans la plupart des cas, comme pour un argument cmdline.) La version 32 bits de Daniel n'a pas cette limitation.

Nous exécutons la même boucle d'analyse quadruple en pointillé 3 fois, obtenant les deux adresses IPv4 et obtenant le /masksous forme d'entier dans l'octet haut d'un dword. (C'est pourquoi il doit y avoir une mémoire lisible après le /mask, mais peu importe s'il y a des chiffres ASCII.)

Nous faisons (host ^ subnet) >> (32-mask)pour décaler les bits d'hôte (ceux autorisés à ne pas correspondre), ne laissant que la différence entre le sous-réseau et l'hôte. Pour résoudre le /0cas spécial où nous devons décaler de 32, nous sautons par-dessus le décalage sur count = 0. ( neg cldéfinit ZF, que nous pouvons ramifier et laisser comme valeur de retour si nous ne décalons pas.) Notez que 32-mask mod 32 = -mask, et les décalages scalaires x86 masquent leur nombre par & 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

(non mis à jour avec la dernière version) Essayez-le en ligne!

y compris un _startqui l'appelle argv[1]et renvoie un état de sortie.

## 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

Cela fonctionne très bien si vous passez un argument de ligne de commande contenant une nouvelle ligne au lieu d'un espace. Mais ce doit être à la place , pas aussi bien.


Fonction de code machine x86 32 bits, 38 octets

Faites 9 entiers -> uint8_t analyse et "poussez-les" sur la pile, où nous les supprimons comme dwords ou utilisons le dernier encore dans CL. Évite la lecture après la fin de la chaîne.

En outre, decn'est que de 1 octet en mode 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

Appelant de test

   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
la source
Je suis curieux de savoir comment le nombre d'octets asm 32 bits irait si au lieu de celui cmp/jccque vous avez mentionné, vous avez fait quelque chose comme xor edx,edx;neg cl;cmovz eax,edx;shr eax,cl- ou peut-être que vous avez déjà une valeur 0 quelque part. (Et puis vous n'auriez pas besoin de l' sub cl,32instruction.)
Daniel Schepler
1
Oui, il edidevrait être égal à 0 lorsque la boucle se termine, donc cela xor eax,edx;neg cl;cmovz eax,edi;shr eax,cldevrait fonctionner.
Daniel Schepler
1
Si j'ai compté les choses correctement, cmove eax,edia 3 octets, ce qui est un lavage sur le supprimé, sub cl,32puis shr cl,eaxenregistre un octet sur shr cl,raxet 32 ​​bits dec edienregistre un octet sur 64 bits dec edi. Mon assemblage donne alors .byte 0x33(dans la syntaxe GNU binutils) = 51 pour in_subnet.size.
Daniel Schepler
Belle idée, merci. (Dans la syntaxe Intel, c'est shr eax,cl, par rapport shr %cl, %eaxà la syntaxe AT&T, votre dernier commentaire a inversé cela.) C'est une corvée de mettre à jour les réponses du code machine (et de porter l' _startappelant et de décrire la convention d'appel pour le mode 32 bits.) .), donc je pourrais ne pas y arriver. Se sentir paresseux aujourd'hui. >. <
Peter Cordes
1
J'ai juste essayé d'implémenter le commentaire que vous avez mis sur ma réponse à propos de se débarrasser de la double boucle et de le stocker à la place dans des variables de pile - et même avec le code supplémentaire pour initialiser le pointeur d' ediécriture, écrire la sortie, etc., il a fini par économiser 2 octets en net. (Au moins une fois, je me suis rendu compte qu'il push ecx;push ecx;push ecxétait plus court que sub esp,12; et cela semblait être un lavage si je prédécrémentais ediet utilisais std;stosb;cldou si je stockais juste en utilisant dec edi;mov [edi],al.
Daniel Schepler
1

Gelée , 23 octets

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

Essayez-le en ligne!

Lien monadique qui prend une adresse et un sous-réseau séparés par une barre oblique et renvoie 1 pour vrai et 0 pour faux.

Merci à @gwaugh d'avoir signalé une faille dans l'original - cela n'a pas permis de s'assurer que la liste binaire était longue de 32.

Nick Kennedy
la source
1

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

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

Essayez-le en ligne!

Xcali
la source
1

05AB1E , 21 octets

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

Prend le sous-réseau avant l'adresse.

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

'/¡              '# 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
la source
1

R 120 octets

une fonction - j'ai collé ".32" au premier terme

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

et juste pour le plaisir:

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

qui est de 56 octets

Zahiro Mor
la source
1

PHP ,75 73, 71 octets

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

Une fourchette de la réponse de @Luis felipe De jesus Munoz , en tant que standalone prenant une entrée des arguments de la ligne de commande. Sorties '1'pour Truthy, ''(chaîne vide) pour 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

Essayez-le en ligne!

-2 octets empruntant la petite astuce de @Christoph pour strtok(). Mais sa réponse est encore plus courte!

640 Ko
la source
1

fonction d'assemblage x86, 49 43 octets

Ceci est principalement affiché pour satisfaire la demande de Peter Cordes pour la version révisée que j'ai créée. Il peut probablement disparaître une fois / s'il l'intègre dans sa réponse.

Cette fonction s'attend esià pointer vers une chaîne d'entrée, avec les parties d'adresse et de sous-réseau séparées par un espace ou un caractère de nouvelle ligne, et la valeur de retour est dans l'indicateur ZF (qui, par définition, n'a que deux valeurs possibles).

 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

Et la partie wrapper Linux x86:

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 octets en raison de la suggestion de Peter Cordes de renvoyer la valeur en ZF.

Daniel Schepler
la source
Je suppose que je pourrais économiser un octet en supprimant le dernier xor edx,edxet en le remplaçant cmovz eax,edxpar jz .nonzero; xor eax,eax; .nonzero:. cmovzgagne toujours si nous avons la convention d'appel ebx=0.
Daniel Schepler
Pouvons-nous juste jzsur shrle setz ou le ret? Nous pouvons échanger le setnzto setzet revenir 1pour un match si cela vous aide. Ou même dire que notre valeur de retour est ZF. J'aurais dû le faire dans ma réponse. (Mais je ne pense pas que nous puissions justifier d'obliger l'appelant à créer des constantes pour nous, comme ebx=0. Ma réponse sur les astuces pour jouer au golf dans le code machine x86 / x64 soutient que ce serait étirer une convention d'appel personnalisée trop loin.
Peter Cordes
BTW, je l' utilise cutpour supprimer certaines colonnes de la sortie liste MSNA parce que toutes mes instructions sont courtes: nasm -felf foo.asm -l/dev/stdout | cut -b -34,$((34+6))-. En outre, j'ai utilisé mov au lieu de movzx dans mon _startappelant car le statut de sortie provient de l'octet de poids faible de l'argument vers sys_exit(). Le noyau ignore les octets supérieurs.
Peter Cordes
Je suppose que ça marcherait. Cela ramène le décompte à 43 octets puis j'insère setnz alaprès call in_subnetdans le wrapper.
Daniel Schepler
Ouaip. Facile à imaginer le cas d'utilisation normal de cette fonction serait call/ je, plutôt que d'imprimer ou de transmettre le résultat. Comme je l'ai souligné dans les "astuces", certaines conventions d'appels d'appels système le font déjà dans la vie réelle (généralement avec CF = erreur).
Peter Cordes
1

Java 215211207202200199198190180180 octets

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

Sorties truepour véridique et falsepour fausse.

Remarque: Cela utilise longau lieu de intpour le décalage à droite potentiel de 32.

Essayez-le en ligne!

1 octet sauvé grâce au plafond

10 octets enregistrés grâce à Peter Cordes

Poussée
la source
Cela ne donne pas de "valeur distincte et cohérente" pour falsey.
AdmBorkBork
Je dirais que c'est nettement et systématiquement différent de zéro, mais si ce n'est pas l'esprit du défi, je peux le changer.
Poke
Un entier 64 bits prend en charge les décalages vers la gauche par 32. En outre, vous pouvez déplacer vers la droitehost ^ net pour décaler les bits que vous souhaitez supprimer, au lieu de créer réellement un masque. Mais je suppose que Java a besoin d'une comparaison pour créer un booléen à partir d'un entier. Peut-être un !, car peu importe le vrai ou le faux que vous produisez pour quelle sortie. (J'ai demandé au PO des éclaircissements pour savoir s'il avait l'intention d'exclure 0 / non nul, et il a répondu oui, il était conscient des conséquences de cette formulation:
Peter Cordes
1
@PeterCordes Tout convertir en longme fait perdre quelques octets, mais je compense cela en étant capable de supprimer le ternaire et de faire le XOR comme vous le suggérez. Je vérifie quoi d'autre je peux jouer au golf avant de poster
Poke
1

Fusain , 36 octets

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

Essayez-le en ligne! Le lien est vers la version détaillée du code. Prend le sous-réseau comme premier paramètre et -ne sort que si l'adresse se trouve dans le sous-réseau. Explication:

≔⪪S/θ

Divisez le sous-réseau /.

≔I⊟θζ

Retirez le masque et transformez-le en entier.

⊞θS

Envoyez l'adresse au tableau.

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

Divisez les deux adresses ., convertissez-les en nombres entiers, interprétez-les comme base 256 et supprimez les bits masqués.

⁼⊟θ⊟θ

Comparez les deux valeurs.

Neil
la source
1

Japt , 26 octets

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

Essayez-le

-3 octets grâce à @Shaggy!

L'entrée est un tableau à 2 éléments [address, subnet]. Transposé JS ci-dessous:

// 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
la source
26 octets
Shaggy
Intéressant - je ne savais pas que vous pouviez contraindre une chaîne à un nombre avec ++.
dana
Ouaip, tout comme vous pouvez dans JS. Cependant, cela ne sert à rien si vous devez réutiliser la valeur d'origine plus tard, mais c'est pratique à l'occasion.
Shaggy
Le besoin de virgule dans la gméthode me dérange; ne peut pas du tout trouver un moyen de le contourner. Au moins pas un qui vous fera économiser un octet.
Shaggy
0

C # (Visual C # Interactive Compiler) , 187 octets

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

Je peux définitivement jouer au golf plus bas.

Essayez-le en ligne!

Incarnation de l'ignorance
la source
0

C # (Visual C # Interactive Compiler) , 134 octets

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

Essayez-le en ligne!

Instruction LINQ qui prend un tableau de chaînes à 2 éléments en entrée dans [address, subnet] format.

Chaque quadruple pointillé est converti en 32 bits de long en utilisant la manipulation de bits. Les bits sont décalés vers la droite de la taille du sous-réseau et les éléments sont comparés pour l'égalité.

Il y avait quelques réponses C # au moment où cette réponse a été publiée, mais aucune qui utilisait de la manipulation de bits purs.

// 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
la source