Sono nelle tue sottoreti, sto giocando a golf il tuo codice


17

Sfida

Dato un IPv4 addressin notazione con punti tratteggiati e un IPv4 subnetin notazione con CIDR , determinare se addressè presente in subnet. Produce un valore distinto e coerente se si trova in subnet, e un valore distinto e coerente se non è insubnet . I valori di output non devono necessariamente essere verità / falsità nella tua lingua.

Breve introduzione alla notazione della sottorete CIDR

Gli indirizzi di rete IPv4 hanno una lunghezza di 32 bit, suddivisi in quattro gruppi di 8 bit per facilitare la lettura. La notazione della sottorete CIDR è una maschera del numero specificato di bit, a partire dall'estrema sinistra. Ad esempio, per una /24sottorete, ciò significa che gli 8 bit più a destra dell'indirizzo sono disponibili in quella sottorete. Pertanto, due indirizzi separati al massimo 255e con la stessa maschera di sottorete si trovano nella stessa sottorete. Si noti che il CIDR valido ha tutti i bit host (il lato destro) non impostati (zeri).

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

Per un altro esempio, una /32sottorete specifica che tutti i bit sono la maschera di sottorete, il che significa essenzialmente che è consentito un solo host per /32.

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

Esempi:

Utilizzando Trueper "nella sottorete" e Falseper "non nella sottorete" come output:

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

Regole e chiarimenti

  • Poiché l'analisi dell'input non è il punto interessante di questa sfida, si garantisce di ottenere indirizzi IPv4 e maschere di sottorete validi.
  • Input e output possono essere dati da qualsiasi metodo conveniente .
  • È possibile stampare il risultato su STDOUT o restituirlo come risultato di una funzione. Indicare nella richiesta quali valori può assumere l'output.
  • È accettabile un programma completo o una funzione.
  • Scappatoie standardSono vietate le .
  • Si tratta di quindi si applicano tutte le normali regole del golf e vince il codice più breve (in byte).

Dobbiamo ricevere input nello stesso formato dei casi di test?
Incarnazione dell'ignoranza

1
@EmbodimentofIgnorance Non è necessario prenderli come uno per riga come negli esempi, ma è necessario prenderli come un quadretto tratteggiato e una sottorete tratteggiata come negli esempi. (ad esempio, vedi la risposta JavaScript di Arnauld)
AdmBorkBork

Va bene averli separati da una barra, ad esempio 10.0.0.1/10.0.0.0”/16?
Nick Kennedy,

1
@Poke Sono d'accordo che hai ragione in quanto la notazione CIDR descrive un indirizzo IP e una dimensione della sottorete. Come in, 1.255.1.1/8è un'espressione CIDR valida , che rappresenta l'host 1.255.1.1all'interno della rete 1.0.0.0con una subnet mask di 255.0.0.0. Tuttavia, la sfida richiede il numero di rete e la sottorete specificatamente nella notazione CIDR, che 1.255.1.1/8non è un numero di rete e una combinazione di sottorete validi.
640KB

1
Ora abbiamo anche bisogno di una versione IPv6 di questa sfida
Ferrybig

Risposte:


13

Python 3 (62 byte)

Molto semplice:

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


3
Ovviamente Mathematica ha un sistema integrato per tutto, anche per gli esopianeti ! Niente può batterlo ... Ma come hai potuto vedere, Python si abbina alla formica di capra di Mathematica
agtoever

Mi chiedo se un ip_adressoggetto e un ip_networkoggetto costituiscano any convenient method, eventualmente lasciando vincere Python, a meno che un linguaggio da golf basato su Python non abbia questi come tipi?
mio pronome è monicareinstate

Non lo otterrai nell'intervallo di 20 byte in Python normale. Solo l'importazione e la lambda sono già più lunghe della risposta Stax. Non sorprende che le lingue del golf vincano da lingue "normali" ... :-(
agtoever

@someone: ho battuto Python con 53 byte di codice macchina x86-64 . :) Non è un linguaggio di golf tradizionale e la maggior parte delle dimensioni del codice analizza string-> int manualmente. (host^net)>>(32-mask)è solo 10 byte. Ma è a metà strada per le attività che non coinvolgono elenchi di elenchi o che mappano una funzione su un elenco, perché molte operazioni scalari possono essere eseguite con un'istruzione da 2 o 3 byte e i cicli possono essere costruiti attorno alle cose in pochi byte.
Peter Cordes,

4

C # (compilatore Visual C #) , 250 + 31 = 281 byte

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

Provalo online!

L'ho scritto in JS non appena è stata pubblicata la sfida, ma Arnauld mi ha battuto sul pugno con una risposta molto migliore, quindi eccolo qui in C #.

Sicuramente un sacco di spazio per il golf.

Spiegazione:

La funzione è costituita da una sotto-funzione chiamata 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;
    }
);

Questa sottofunzione divide l'indirizzo IP ., converte ogni numero in una stringa binaria, sposta a sinistra ogni stringa con0 una lunghezza di 8 bit, quindi concatena le stringhe in una stringa binaria a 32 bit.

Ciò viene immediatamente eseguito sul posto con a=h(a);l'indirizzo IP indicato.
Abbiamo quindi diviso la subnet mask in un indirizzo IP e un numero di maschera conc=b.Split('/');

Anche il componente Indirizzo IP viene passato attraverso la nostra sotto-funzione: b=h(c[0]);e il numero di maschera viene analizzato in un numero intero:var d=int.Parse(c[1]);

Infine prendiamo i primi dbit di entrambe le stringhe binarie (dove si dtrova il numero della maschera) e li confrontiamo:return a.Substring(0,d)==b.Substring(0,d);


1
Troppo stanco di risolverlo, quindi ho appena giocato
Dati scaduti

1
In realtà ho dimenticato PadLeft anche in quello Provalo online!
Dati scaduti

Molte ottimizzazioni. Sono felice di informarti che la tua rPadè una stringa integrata. link pastebin al link TIO che è troppo lungo da solo
mio pronome è monicareinstate

2
@someone Small FYI: accorciatori di URL come tinyurl.com sono ammessi nei commenti su questa SE, a differenza della maggior parte. :)
Kevin Cruijssen

1
188 - tinyurl.com/y6xfkbxt - buoni consigli per accorciare l'URL @KevinCruijssen
dana

4

Shell POSIX Linux (con net-tools / iputils) (34 byte non terminanti, 47 byte terminanti)

Qual è il più adatto per analizzare maschere e indirizzi di rete rispetto alle stesse utility di rete? :)

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

Attenzione: lo script è potenzialmente dannoso per la tua connettività Internet, eseguilo con cura.

Ingresso: lo script prende l'indirizzo IP testato come primo argomento e la sottorete testata. come secondo argomento.

Output: lo script restituisce un valore di verità (0) se il primo argomento dello script appartiene alla sottorete indicata nel secondo argomento. Altrimenti, non terminerà mai.

Presupposti: lo script deve essere eseguito come utente root, in un ambiente pulito ( ovvero , nessun'altra route blackhole è stata impostata dall'amministratore e se è stata eseguita un'istanza precedente dello script, la route blackhole che ha creato è stata rimossa ). Lo script presuppone anche una "connessione Internet funzionante" ( ovvero , è presente una route predefinita valida).


Spiegazione:

Creiamo un percorso blackhole alla sottorete specificata. Testiamo quindi la connettività all'indirizzo IP fornito usando il ping . Se l'indirizzo non appartiene alla sottorete (e poiché ipotizziamo una connessione Internet correttamente impostata), ping tenterà di inviare i pacchetti a quell'indirizzo. Nota che non risponde effettivamente a questo indirizzo, poiché il ping continuerà a provare per sempre. Al contrario, se l'indirizzo appartiene alla sottorete, il ping fallirà con ENETUNREACH e restituirà 2, e poiché abbiamo annullato il comando, lo script avrà esito positivo.


Esempio

Verifica se 5.5.5.5 appartiene 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...]

(Pulire con sudo ip route del 8.8.8.0/24dopo aver eseguito il comando).

Verifica se 5.5.5.5 appartiene a 5.5.5.0/24:

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

(Pulire con sudo ip route del 5.5.5.0/24dopo aver eseguito il comando).

Verifica se 8.8.8.8 appartiene 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...]

(Pulire con sudo ip route del 5.5.5.0/24dopo aver eseguito il comando).


Versione a 47 byte se non consentiamo script non terminanti

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

Secondo il commento di @ Grimy, ecco la versione che termina sempre e restituisce 0 (verità) se l'indirizzo si trova nella sottorete e 1 (falsa) in caso contrario. Facciamo terminare il ping con il -c1flag che limita il numero di pacchetti inviati a 1. Se l'indirizzo ha risposto, il ping restituirà 0 e, in caso contrario, il ping restituirà 1. Solo se l'indirizzo appartiene alla sottorete blackhol restituirà il ping 2, che è quindi ciò contro cui testiamo nell'ultimo comando.


3
Sebbene intelligente, questo non soddisfa il requisito di produrre un valore distinto e coerente se l'indirizzo non si trova nella sottorete (l' esecuzione per sempre non conta come output , vedere anche questo ).
Grimmy,

1
@Grimy: Ma non funziona in silenzio per sempre, quindi si applica solo il tuo secondo link, non il primo. Inoltre penso pingche morirebbe da SIGPIPE se funzionasse con stdout + stderr convogliato in un altro programma e il lettore chiudesse la pipa. E questo è il caso d'uso più probabile perché lo stato di uscita può avere esito positivo in entrambi i casi (se aggiungessimo -c1un'opzione al ping per impostare il conteggio). Ma certo, leggere il suo output con var=$(/a.sh)fallirebbe; avresti bisogno di un lettore che si fermasse dopo aver deciso, piuttosto che leggere l'intero risultato e poi guardarlo.
Peter Cordes,

@Grimy Fair point (anche se per l'argomento potrei dire che qui abbiamo due valori coerenti, poiché pingterminerà in meno di, diciamo, un secondo in caso di un indirizzo blackholed). Ho aggiunto una versione di terminazione per ulteriori 13 byte! :)
Yoann

3

JavaScript (ES6), 82 byte

Accetta input come (address)(subnet). Restituisce un valore 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))

Provalo online!


3

PHP , 101 92 88 byte

-13 byte da @gwaugh

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

Provalo online!


2
Mi sono divertito un po 'a giocare a golf (Ty!):function($i,$r){return!((ip2long($i)^ip2long(strtok($r,'/')))>>32-strtok(_));}
Christoph

@Christoph molto bello! Non mi è mai venuto in mente che potresti usare qualsiasi token per la seconda chiamata strtok(). Il tuo è di 4 byte in meno rispetto alla mia risposta molto simile qui sotto. Puntelli!
640 KB

@Christoph Dovresti pubblicare la tua soluzione come una risposta separata poiché è migliore della mia.
Luis felipe De jesus Munoz,

3

PowerPC / PPC64 C, 116 114 byte

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

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

Il programma prende le due righe sull'input standard e come codice di uscita restituisce 1 se l'indirizzo corrisponde e 0 se non lo è. (Pertanto, ciò dipende dal fatto che le specifiche non richiedono un valore di verità per una corrispondenza e un valore di falsa per una mancata corrispondenza.) Nota: se si esegue in modo interattivo, è necessario segnalare EOF (^D ) tre volte dopo aver inserito la seconda riga.

Ciò si basa sul fatto che PowerPC è big-endian e anche su quella piattaforma che restituisce 0 per spostare a destra un valore senza segno a 32 bit di 32. Legge gli ottetti in valori senza segno uno per uno, insieme alla lunghezza della maschera di rete in un altro byte ; quindi prende il xor dei due indirizzi a 32 bit senza segno e sposta i bit irrilevanti. Infine, si applica !per soddisfare il requisito di restituire solo due valori distinti.

Nota: potrebbe essere possibile radere due byte sostituendo u+3con pe richiedendo la compilazione con -O0. Questo è vivere più pericolosamente di quanto mi importi, però.

Grazie a Peter Cordes per l'ispirazione per questa soluzione.


Più portatile C, 186 171 167 byte

Qui conserverò una versione più portatile che esegue 167 byte.

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

Questo programma accetta le due righe sull'input standard e restituisce il codice di uscita 1 se l'indirizzo si trova nella sottorete e 0 se non lo è. (Quindi questo si basa sulla specifica che non richiede un valore di verità per le partite e un valore di falsa per le non partite.)

Una suddivisione dell'espressione principale:

  • a^e, b^f, c^g, d^hCalcola la xor dell'indirizzo e la maschera byte per byte.
  • (((a^e)<<8|b^f)<<8|c^g)<<8|d^h quindi li combina in un singolo valore a 32 bit senza segno con un metodo simile a Horner.
  • ...>>32-nquindi sposta i bit della differenza xo che non sono rilevanti per la subnet mask (tenendo presente che -ha una precedenza maggiore in C rispetto a <<)
  • C'è un gotcha, però: se n = 0 allora ~0U<<32darà un comportamento indefinito supponendo che unsignedsia 32 bit (che è praticamente su tutte le piattaforme attuali). D'altra parte, se n = 0 allora qualsiasi indirizzo corrisponderà, quindi n&&...darà il risultato corretto (sfruttando il comportamento di cortocircuito di &&).
  • Infine, per soddisfare il requisito secondo cui l'output può essere solo uno dei due valori, applichiamo !all'output 0 o 1.

-15 byte a causa dei commenti di ceilingcat e AdmBorkBork

-4 byte a causa del commento di Peter Cordes


1
L'uso dei codici di uscita per restituire valori è uno dei metodi I / O predefiniti ed è quindi consentito.
AdmBorkBork

@ceilingcat Certo, quanto sono sciocco da parte mia perdere questo.
Daniel Schepler,

@AdmBorkBork OK, grazie, l'ho cambiato per usare il codice di uscita.
Daniel Schepler,

idea: indirizzare un'implementazione C little-endian o big-endian (code-golf non richiede codice portatile) e digitare puntatori di output pun-tip sui byte di un unsigned. ad esempio con char*p=&aallora p++,p++,p++,...o p--,...come scanf args. La stringa di formato dovrebbe essere "%hhu.%hhu..."però, quindi è un compromesso significativo tra quella dimensione extra rispetto alla dichiarazione di meno errori e alla possibilità di farlo(a^b)>>(32-count)
Peter Cordes

1
@PeterCordes Sì, il turno giusto funziona, grazie.
Daniel Schepler,

2

Stax , 22 byte

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

Esegui ed esegui il debug

Prende i parametri di input separati da spazio sullo standard input.

Disimballato, non golfato e commentato, sembra così.

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

Esegui questo


2

funzione codice macchina x86-64, 53 48 byte

changelog:

  • -2 jz rispetto al turno invece di utilizzare un turno a 64 bit per gestire il >>(32-0)caso speciale.
  • -3 ritorna in ZF invece di AL, risparmiando 3 byte per a setnz al .

(Vedi anche la risposta del codice macchina a 32 bit di Daniel Schepler basata su questo, che poi si è evoluto per usare alcune altre idee che avevamo. Sto includendo la mia ultima versione di quella in fondo a questa risposta.)


Restituisce ZF = 0 per l'host no nella sottorete, ZF = 1 per nella sottorete, quindi puoi diramare il risultato conje host_matches_subnet

Callable con la convenzione di chiamata System V x86-64 come
bool not_in_subnet(int dummy_rdi, const char *input_rsi); se si aggiungesse setnz al.

La stringa di input contiene sia l'host che la rete, separati da esattamente 1 carattere non cifra. La memoria che segue la fine della larghezza CIDR deve contenere almeno 3 byte senza cifre prima della fine di una pagina. (Non dovrebbe essere un problema nella maggior parte dei casi, come per un cmdline arg.) La versione a 32 bit di Daniel non ha questa limitazione.

Eseguiamo lo stesso ciclo di analisi tratteggiato quad-quadruplo 3 volte, ottenendo i due indirizzi IPv4 e ottenendo il /masknumero intero nel byte alto di una parola. (Questo è il motivo per cui ci deve essere una memoria leggibile dopo il /mask, ma non importa se ci sono cifre ASCII.)

Facciamo (host ^ subnet) >> (32-mask)spostare i bit dell'host (quelli a cui non è possibile corrispondere), lasciando solo la differenza tra la sottorete e l'host. Per risolvere il /0caso speciale in cui dobbiamo spostare di 32, saltiamo sopra lo spostamento conteggio = 0. ( neg climposta ZF, che possiamo ramificare e lasciare come valore di ritorno se non spostiamo.) Notate che 32-mask mod 32 = -mask, e gli spostamenti scalari x86 mascherano il loro conteggio di & 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

(non aggiornato con l'ultima versione) Provalo online!

tra cui un _startche lo chiama argv[1]e restituisce uno stato di uscita.

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

Funziona bene se si passa un arg della riga di comando contenente una nuova riga anziché uno spazio. Ma deve essere invece , non pure.


x86 Funzione codice macchina a 32 bit, 38 byte

Esegui 9 numeri interi -> uint8_t analizza e "inseriscili" nello stack, dove li espelliamo come password o utilizziamo l'ultimo ancora in CL. Evita di leggere oltre la fine della stringa.

Inoltre, decè solo 1 byte in modalità 32 bit.

    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

Prova il chiamante

   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

Sono curioso di sapere come andrebbe il conteggio dei byte asm a 32 bit se invece di quello cmp/jccche hai menzionato avessi fatto qualcosa del genere xor edx,edx;neg cl;cmovz eax,edx;shr eax,cl- o forse hai già un valore 0 in giro da qualche parte. (E poi non avresti bisogno delle sub cl,32istruzioni.)
Daniel Schepler

1
Sì, sembra che edidovrebbe essere 0 quando il ciclo termina, quindi xor eax,edx;neg cl;cmovz eax,edi;shr eax,cldovrebbe funzionare.
Daniel Schepler,

1
Se ho contato le cose nel modo giusto, cmove eax,ediha 3 byte che è un lavaggio rispetto alla rimozione, sub cl,32quindi shr cl,eaxsalva un byte su shr cl,raxe 32 bit dec edisalva un byte su 64 bit dec edi. Il mio assembly quindi dà .byte 0x33(nella sintassi binutils GNU) = 51 per in_subnet.size.
Daniel Schepler,

Bella idea, grazie. (Nella sintassi Intel è shr eax,cl, rispetto shr %cl, %eaxalla sintassi AT&T, il tuo ultimo commento lo ha invertito.) È un po 'un lavoro ingrato aggiornare le risposte del codice macchina (e portare il _startchiamante e descrivere nuovamente la convenzione di chiamata per la modalità a 32 bit .. .), quindi potrei non aggirarlo. Mi sento pigro oggi. >. <
Peter Cordes,

1
Ho appena provato a implementare il commento che hai posto sulla mia risposta sull'eliminazione del doppio loop e invece sull'archiviazione in variabili stack - e anche con il codice aggiuntivo per inizializzare il puntatore di ediscrittura, scrivere l'output, ecc., Ha finito per salvare 2 byte in rete. (Almeno una volta mi sono reso conto che push ecx;push ecx;push ecxera più corto di sub esp,12; e sembrava essere un lavaggio se ho predecrementato edie usato std;stosb;cldo se ho appena conservato usando dec edi;mov [edi],al.
Daniel Schepler

1

Gelatina , 23 byte

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

Provalo online!

Collegamento monadico che accetta un indirizzo e una sottorete separati da una barra e restituisce 1 per true e 0 per false.

Grazie a @gwaugh per aver sottolineato un difetto nell'originale, non è stato possibile garantire che l'elenco binario fosse lungo 32.



1

05AB1E , 21 byte

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

Prende la sottorete prima dell'indirizzo.

Provalo online o verifica tutti i casi di test .

Spiegazione:

'/¡              '# 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 byte

una funzione - ho incollato ".32" al primo termine

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 solo per divertimento:

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

che è di 56 byte


1

PHP ,75 73, 71 byte

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

Un fork della risposta di @Luis felipe De jesus Munoz , mentre un autonomo prende input dalla riga di comando. Output '1'per Truthy, ''(stringa vuota) per 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

Provalo online!

-2 byte prendendo in prestito il piccolo trucco di @Christoph per strtok(). La sua risposta è comunque più breve!


1

funzione di assemblaggio x86, 49 43 byte

Questo è principalmente pubblicato per soddisfare la richiesta di Peter Cordes per la versione rivista che ho creato. Probabilmente può andare via una volta / se lo incorpora nella sua risposta.

Questa funzione prevede esidi puntare a una stringa di input, con le parti dell'indirizzo e della sottorete separate da uno spazio o da un carattere di nuova riga e il valore restituito è nel flag ZF (che per definizione ha solo due possibili valori).

 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 la parte 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 byte a causa del suggerimento di Peter Cordes di restituire il valore in ZF.


Immagino di poter salvare un byte rimuovendo l'ultimo xor edx,edxe sostituendolo cmovz eax,edxcon jz .nonzero; xor eax,eax; .nonzero:. cmovzvince ancora se abbiamo una convenzione di convocazione ebx=0.
Daniel Schepler,

Possiamo semplicemente jzpassare shral setz o al ret? Possiamo scambiarlo setnzcon setze tornare 1a una partita se questo aiuta. O addirittura dire che il nostro valore di ritorno è ZF. Avrei dovuto farlo nella mia risposta. (Ma non credo che possiamo giustificare la necessità di richiedere al chiamante di creare costanti per noi, come ebx=0. La mia risposta su Suggerimenti per giocare a golf nel codice macchina x86 / x64 sostiene che si estenderebbe troppo lontano una convenzione di chiamata personalizzata.
Peter Cordes

BTW, io uso cutper rimuovere alcune colonne dall'output messa in vendita di NASM perché tutti i miei istruzioni sono brevi: nasm -felf foo.asm -l/dev/stdout | cut -b -34,$((34+6))-. Inoltre, ho usato mov invece di movzx nel mio _startchiamante perché lo stato di uscita viene dal byte basso dell'arg a sys_exit(). Il kernel ignora i byte più alti.
Peter Cordes,

Immagino che avrebbe funzionato. Questo porta il conto alla rovescia a 43 byte e quindi inserisco setnz aldopo call in_subnetnel wrapper.
Daniel Schepler,

Sì. È facile immaginare il caso d'uso normale per questa funzionecall / je, piuttosto che stampare o passare ulteriormente il risultato. Come ho sottolineato nei "suggerimenti", alcune convenzioni di chiamata di sistema fanno già questo nella vita reale (di solito con CF = errore).
Peter Cordes,

1

Java 215 211 207 202 200 199 198 190 180 byte

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

Uscite trueper verità efalse falsità.

Nota: utilizza longinvece diint il potenziale spostamento a destra di 32.

Provalo online!

1 byte salvato grazie a ceilingcat

Risparmiato 10 byte grazie a Peter Cordes


Questo non produce un "valore distinto e coerente" per falso.
AdmBorkBork,

Direi che è chiaramente e costantemente diverso da zero, ma se questo non è lo spirito della sfida, posso cambiarlo.
Colpisce

Un numero intero a 64 bit supporta gli spostamenti a sinistra di 32. Inoltre, puoi spostare a destrahost ^ net per spostare i bit che desideri rimuovere, invece di creare effettivamente una maschera. Ma suppongo che Java abbia bisogno di un confronto lì dentro per creare un valore booleano da un numero intero. Forse a !, perché non importa quale di vero o falso produci per quale output. (Ho chiesto al PO un chiarimento sull'intenzione di escludere 0 / diverso da zero e hanno detto sì di essere a conoscenza delle conseguenze di tale formulazione:
Peter Cordes,

1
@PeterCordes La conversione di tutto in longmi fa perdere qualche byte ma lo compenso potendo rimuovere il ternario e fare l'XOR come suggerisci. Sto verificando cos'altro posso giocare a golf prima di pubblicare
Poke

1

Carbone , 36 byte

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

Provalo online!Il collegamento è alla versione dettagliata del codice. Prende la sottorete come primo parametro e viene emessa -solo se l'indirizzo si trova all'interno della sottorete. Spiegazione:

≔⪪S/θ

Dividi la sottorete / .

≔I⊟θζ

Rimuovere la maschera e lanciarla su un numero intero.

⊞θS

Inserire l'indirizzo nell'array.

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

Dividi entrambi gli indirizzi . , convertili in numeri interi, interpretali come base 256 e scarta i bit mascherati.

⁼⊟θ⊟θ

Confronta i due valori.


1

Japt , 26 byte

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

Provalo

-3 byte grazie a @Shaggy!

L'input è un array con 2 elementi [address, subnet]. JS traspilato di seguito:

// 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("===")


Interessante: non avevo realizzato che potresti forzare una stringa in un numero ++.
dana,

Sì, proprio come puoi in JS. Non serve, tuttavia, se è necessario ripristinare il valore originale in un secondo momento, ma a volte è utile.
Shaggy,

La necessità della virgola nel gmetodo mi dà fastidio; non riesco a trovare un modo per aggirare. Almeno non uno che ti farà risparmiare un byte.
Shaggy,


0

C # (compilatore interattivo Visual C #) , 134 byte

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

Provalo online!

Istruzione LINQ che accetta un array di stringhe a 2 elementi come input in [address, subnet] formato.

Ogni quadratino punteggiato viene convertito in 32 bit di lunghezza usando la manipolazione dei bit. I bit vengono spostati a destra in base alla dimensione della sottorete e gli elementi vengono confrontati per l'uguaglianza.

C'erano un paio di risposte C # al momento della pubblicazione di questa risposta, ma nessuna utilizzava la pura manipolazione dei bit.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.