Jestem w twoich podsieciach i gram w twój kod

17

Wyzwanie

Biorąc pod uwagę IPv4 addressw notacji z kropkami-kwadracikami i IPv4 subnetw notacji CIDR , sprawdź, czy addressjest w subnet. Podaj wyraźną i spójną wartość, jeśli jest w subnet, i osobną odrębną i spójną wartość, jeśli nie jest w subnet. Wartości wyjściowe niekoniecznie muszą być zgodne z prawdą / falsey w twoim języku.

Podstawowy zapis notacji podsieci CIDR

Adresy sieciowe IPv4 mają długość 32 bitów i są podzielone na cztery grupy po 8 bitów dla ułatwienia odczytu. Notacja podsieci CIDR jest maską określonej liczby bitów, zaczynając od lewej strony. Na przykład dla /24podsieci oznacza to, że 8 najbardziej prawych bitów adresu jest dostępnych w tej podsieci. Zatem dwa adresy, które są oddzielone co najwyżej 255i mają tę samą maskę podsieci, znajdują się w tej samej podsieci. Zauważ, że w prawidłowym CIDR wszystkie bity hosta (po prawej stronie) są wyłączone (zera).

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

W innym przykładzie /32podsieć określa, że wszystkie bity są maską podsieci, co zasadniczo oznacza, że ​​dozwolony jest tylko jeden host na /32.

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

Przykłady:

Użycie Truejako „w podsieci” i False„nie w podsieci” jako danych wyjściowych:

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

Zasady i wyjaśnienia

  • Ponieważ analiza wejściowa nie jest interesującym punktem tego wyzwania, masz gwarancję uzyskania prawidłowych adresów IPv4 i masek podsieci.
  • Dane wejściowe i wyjściowe można podać dowolną dogodną metodą .
  • Możesz wydrukować wynik do STDOUT lub zwrócić go jako wynik funkcji. Podaj w swoim zgłoszeniu, jakie wartości może przyjąć wynik.
  • Dopuszczalny jest pełny program lub funkcja.
  • Standardowe luki są zabronione.
  • To jest więc obowiązują wszystkie zwykłe zasady gry w golfa, a wygrywa najkrótszy kod (w bajtach).
AdmBorkBork
źródło
Czy musimy pobierać dane wejściowe w tym samym formacie, co twoje przypadki testowe?
nieznajomości
1
@EmbodimentofIgnorance Nie musisz traktować ich jako jeden na linię, jak w przykładach, ale musisz wziąć je jako kropkowany quad i kropkowaną podsieć, jak w przykładach. (np. zobacz odpowiedź Arnaulda na JavaScript)
AdmBorkBork
Czy można je rozdzielić, np. Ukośnikiem 10.0.0.1/10.0.0.0”/16?
Nick Kennedy
1
@Poke Zgadzam się, że masz rację, ponieważ notacja CIDR opisuje adres IP i rozmiar podsieci. Podobnie jak w, 1.255.1.1/8jest prawidłowym wyrażeniem CIDR , reprezentującym hosta 1.255.1.1w sieci 1.0.0.0za pomocą maski podsieci 255.0.0.0. Jednak wyzwanie wymaga numeru sieci i podsieci, szczególnie w notacji CIDR, która 1.255.1.1/8nie jest prawidłową kombinacją numeru sieci i podsieci.
640 KB
1
Teraz potrzebujemy również wersji IPv6 tego wyzwania
Ferrybig

Odpowiedzi:

13

Python 3 (62 bajty)

Bardzo proste:

from ipaddress import*
lambda i,m:ip_address(i)in ip_network(m)
agtoever
źródło
9
Fajnie, ale czy python ma również wbudowane rozpoznawanie kóz ?
Benjamin Urquhart
3
Oczywiście Mathematica ma wbudowane wszystko - nawet egzoplanety ! Nic nie jest w stanie tego pokonać ... Ale, jak mogłeś zobaczyć, Python pasuje do koziej maty Mathematiki
jeszcze
Zastanawiam się, czy ip_adressobiekt i ip_networkobiekt stanowią any convenient method, być może pozwalając Pythonowi wygrać, chyba że język golfowy oparty na Pythonie ma te typy?
mój zaimek to monicareinstate
Nie dostaniesz go w zakresie 20 bajtów w normalnym Pythonie. Tylko import i lambda są już dłuższe niż odpowiedź Stax. Nic dziwnego, że języki gry w golfa wygrywają z „normalnych” języków ... :-(
agtoever
@someone: Pokonałem Pythona 53 bajtami kodu maszynowego x86-64 . :) Nie jest to tradycyjny język golfowy, a większość wielkości kodu jest przetwarzana ręcznie przez string-> int. (host^net)>>(32-mask)ma tylko 10 bajtów. Ale jest w połowie drogi do zadań nieobejmujących list list lub mapowania funkcji na listę, ponieważ wiele operacji skalarnych można wykonać za pomocą instrukcji 2 lub 3 bajtów, a pętle można zbudować wokół rzeczy w kilku bajtach.
Peter Cordes
4

C # (kompilator Visual C #) , 250 + 31 = 281 bajtów

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

Liczba bajtów obejmuje using System;using System.Linq;

Wypróbuj online!

Napisałem to w JS, jak tylko opublikowano wyzwanie, ale Arnauld pobił mnie do bicia znacznie lepszą odpowiedzią, więc tutaj jest w C #.

Zdecydowanie dużo miejsca na grę w golfa.

Wyjaśnienie:

Funkcja składa się z podfunkcji o nazwie 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;
    }
);

Ta podfunkcja dzieli adres IP ., konwertuje każdą liczbę na ciąg binarny, lewy 0dopełnia każdy ciąg o długości 8 bitów, a następnie konkatenuje ciągi w jeden 32-bitowy ciąg binarny.

Odbywa się to natychmiast na miejscu z a=h(a);podanym adresem IP.
Następnie dzielimy maskę podsieci na adres IP i numer maski za pomocąc=b.Split('/');

Składnik adresu IP jest również przekazywany przez naszą podfunkcję: b=h(c[0]);a numer maski jest analizowany na liczbę całkowitą:var d=int.Parse(c[1]);

Na koniec bierzemy pierwsze dbity obu ciągów binarnych (gdzie djest numerem maski) i porównujemy je:return a.Substring(0,d)==b.Substring(0,d);

Skidsdev
źródło
1
Zbyt zmęczony, żeby to rozpracować, więc właśnie dla ciebie grałem w golfa
Data wygasła
1
W tym też zapomniałem o PadLeft. Wypróbuj online!
Data wygasła
Wiele optymalizacji. Miło mi poinformować, że masz rPadwbudowane ciągi znaków. pastebin link do zbyt długiego linku TIO
mój zaimek to monicareinstate
2
@someone Small FYI: Skracacze URL, takie jak tinyurl.com, są dozwolone w komentarzach do tej SE, w przeciwieństwie do większości. :)
Kevin Cruijssen
1
188 - tinyurl.com/y6xfkbxt - fajne porady dotyczące skracania adresów URL @KevinCruijssen
dana
4

Powłoka Linux POSIX (z net-tools / iputils) (34 bajty nie kończące się, 47 bajtów kończące się)

Co najlepiej nadaje się do analizowania masek sieciowych i adresów niż same narzędzia sieciowe? :)

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

Ostrzeżenie: skrypt może potencjalnie uszkodzić łączność z Internetem, należy zachować ostrożność.

Dane wejściowe: skrypt przyjmuje jako pierwszy argument przetestowany adres IP i testowaną podsieć. jako drugi argument.

Dane wyjściowe: skrypt zwraca prawdziwą wartość (0), jeśli pierwszy argument skryptu należy do podsieci wskazanej w drugim argumencie. W przeciwnym razie nigdy się nie skończy.

Założenia: skrypt musi być uruchamiany jako użytkownik root, w czystym środowisku ( tj. Administrator nie ustawił żadnej innej trasy blackhole, a jeśli uruchomiono poprzednie wystąpienie skryptu, utworzona przez niego trasa blackhole została usunięta ). Skrypt zakłada także „działające połączenie internetowe” ( tzn. Obecna jest poprawna domyślna trasa).


Wyjaśnienie:

Tworzymy trasę blackhole do określonej podsieci. Następnie testujemy łączność z podanym adresem IP za pomocą polecenia ping . Jeśli adres nie należy do podsieci (a ponieważ zakładamy odpowiednio ustawione połączenie internetowe), ping spróbuje wysłać pakiety na ten adres. Pamiętaj, że to, czy ten adres faktycznie odpowiada, nie ma znaczenia, ponieważ ping będzie próbował zawsze. I odwrotnie, jeśli adres należy do podsieci, ping zakończy się niepowodzeniem z ENETUNREACH i zwróci 2, a ponieważ zanegowaliśmy polecenie, skrypt się powiedzie.


Przykład

Sprawdź, czy 5.5.5.5 należy do 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...]

(Oczyść za pomocą sudo ip route del 8.8.8.0/24 po uruchomieniu polecenia).

Sprawdź, czy 5.5.5.5 należy do 5.5.5.0/24:

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

(Oczyść za pomocą sudo ip route del 5.5.5.0/24 po uruchomieniu polecenia).

Sprawdź, czy 8.8.8.8 należy do 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...]

(Wyczyść za pomocąsudo ip route del 5.5.5.0/24 po uruchomieniu polecenia).


Wersja 47-bajtowa, jeśli nie zezwalamy na nie kończące się skrypty

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

Zgodnie z komentarzem @ Grimy, oto wersja, która zawsze kończy się i zwraca 0 (prawda), jeśli adres znajduje się w podsieci, i 1 (fałsz) w przeciwnym razie. Sprawiamy, że ping kończy się -c1flagą, która ogranicza liczbę wysłanych pakietów do 1. Jeśli adres odpowiedział, ping zwróci 0, a jeśli nie, ping zwróci 1. Tylko jeśli adres należy do podholowanej podsieci, ping zwróci 2, dlatego testujemy w ostatnim poleceniu.

yoann
źródło
3
Mimo że jest sprytny, nie spełnia wymogu wyprowadzania wyraźnej i spójnej wartości, jeśli adres nie znajduje się w podsieci (ciągłe działanie nie jest liczone jako dane wyjściowe , zobacz także to ).
Grimmy,
1
@Grimy: Ale nie działa on po cichu wiecznie, więc obowiązuje tylko Twój drugi link, a nie pierwszy. Myślę też, że pingumarłby od SIGPIPE, gdyby działał ze stdout + stderr podłączonymi do innego programu, a czytnik zamknął potok. I to jest najbardziej prawdopodobny przypadek użycia, ponieważ status wyjścia może być udany w obu przypadkach (jeśli dodamy -c1opcję pingowania, aby ustawić liczbę). Ale na pewno odczytanie jego wyniku var=$(/a.sh)nie powiedzie się; potrzebujesz czytnika, który zatrzyma się po podjęciu decyzji, zamiast czytać cały wynik, a następnie patrzeć na niego.
Peter Cordes
@Grimy Fair point (chociaż dla argumentu mógłbym powiedzieć, że mamy tutaj dwie spójne wartości, ponieważ pingzakończą się one w mniej niż, powiedzmy, jednej sekundzie w przypadku czarnego adresu). Dodałem wersję końcową dla dodatkowych 13 bajtów! :)
yoann
3

JavaScript (ES6), 82 bajty

Pobiera dane wejściowe jako (address)(subnet). Zwraca wartość logiczną.

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

Wypróbuj online!

Arnauld
źródło
3

PHP , 101 92 88 bajtów

-13 bajtów od @gwaugh

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

Wypróbuj online!

Luis Felipe De Jesus Munoz
źródło
2
Baw się dobrze grając w golfa (Ty!):function($i,$r){return!((ip2long($i)^ip2long(strtok($r,'/')))>>32-strtok(_));}
Christoph
@Christoph bardzo miło! Nigdy nie przyszło mi do głowy, że możesz użyć dowolnego tokena do drugiego połączenia z strtok(). Twój jest o 4 bajty krótszy niż moja bardzo podobna odpowiedź poniżej. Rekwizyty!
640 KB
@Christoph Powinieneś opublikować swoje rozwiązanie jako oddzielną odpowiedź, ponieważ jest ono lepsze niż moje.
Luis Felipe De Jesus Munoz
3

PowerPC / PPC64 C, 116 114 bajtów

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

(Testowany na Ubuntu 18.04 x86_64 przy użyciu powerpc64-linux-gnu-gcc -static i qemu-user.)

Program przyjmuje dwa wiersze na standardowym wejściu i jako kod wyjścia zwraca 1, jeśli adres jest zgodny, i 0, jeśli nie. (Tak więc zależy to od specyfikacji, która nie wymaga prawdziwej wartości dla dopasowania i wartości falsey dla niedopasowania.) Pamiętaj, że jeśli biegniesz interaktywnie, będziesz musiał zasygnalizować EOF ( ^D) trzy razy po wejściu do drugiej linii.

Polega to na tym, że PowerPC jest big-endian, a także na tej platformie zwracającej 0 za przesunięcie w prawo 32-bitowej wartości bez znaku o 32. Czyta oktety do wartości bez znaku jeden po drugim, wraz z długością maski sieci w innym bajcie ; następnie pobiera xor dwóch niepodpisanych 32-bitowych adresów i przenosi niepotrzebne bity. Wreszcie ma zastosowanie !do spełnienia wymogu zwrotu tylko dwóch różnych wartości.

Uwaga: To może być możliwe, aby zgolić dwa bajty zastępując u+3ze pi wymagające kompilacja -O0. Ale to żyje bardziej niebezpiecznie, niż mi zależy.

Dziękujemy Peterowi Cordesowi za inspirację do tego rozwiązania.


Bardziej przenośne C, 186 171 167 bajtów

Tutaj zachowam bardziej przenośną wersję, która ma 167 bajtów.

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

Ten program pobiera dwa wiersze na standardowym wejściu i zwraca kod wyjścia 1, jeśli adres znajduje się w podsieci, i 0, jeśli nie jest. (Tak więc zależy to od specyfikacji, która nie wymaga prawdziwej wartości dla dopasowań i wartości falsey dla niezgodności.)

Podział podstawowego wyrażenia:

  • a^e, b^f, c^g, d^hOblicza XOR adresu i maskę bajt bajcie.
  • (((a^e)<<8|b^f)<<8|c^g)<<8|d^h następnie łączy je w jedną 32-bitową wartość bez znaku metodą Hornera.
  • ...>>32-nnastępnie odsuwa bity różnicy xor, które nie są istotne dla maski podsieci (pamiętając, że -ma wyższy priorytet w C niż <<)
  • Jest jednak jedna gotcha: jeśli n = 0, to ~0U<<32daje niezdefiniowane zachowanie, zakładając, że unsignedma on 32 bity (czyli na praktycznie wszystkich obecnych platformach). Z drugiej strony, jeśli n = 0, to dowolny adres będzie zgodny, więc n&&...da poprawny wynik (wykorzystując zachowanie zwarcia &&).
  • Wreszcie, aby spełnić wymóg, że wyjście może być tylko jedną z dwóch wartości, stosujemy !do wyjścia 0 lub 1.

-15 bajtów ze względu na komentarze sufitcatcat i AdmBorkBork

-4 bajty z powodu komentarza Petera Cordesa

Daniel Schepler
źródło
1
Używanie kodów wyjścia do zwracania wartości jest jedną z domyślnych metod we / wy i dlatego jest dozwolone.
AdmBorkBork
@ceilingcat Oczywiście, jak głupio ze mnie tęsknić.
Daniel Schepler
@AdmBorkBork OK, dziękuję, zmieniłem go, aby używać kodu wyjścia.
Daniel Schepler
idea: celuj w implementację C little-endian lub big-endian (code-golf nie wymaga przenośnego kodu) i wskaż wskaźniki wyjściowe pun w bajtach an unsigned. np. z char*p=&awtedyp++,p++,p++,... lub p--,...jako argumenty scanf. Ciąg formatujący musiałby jednak być "%hhu.%hhu...", więc jest to znaczący kompromis między tym dodatkowym rozmiarem a deklarowaniem mniejszej liczby zmiennych i możliwością wykonania(a^b)>>(32-count)
Peter Cordes
1
@PeterCordes Tak, odpowiednia zmiana działa, dzięki.
Daniel Schepler
2

Stax , 22 bajty

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

Uruchom i debuguj

Pobiera parametry wejściowe oddzielone spacją na standardowym wejściu.

Rozpakowane, niepolowane i skomentowane, wygląda to tak.

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

Uruchom ten

rekurencyjny
źródło
2

x86-64 funkcja kodu maszynowego, 53 48 bajtów

dziennik zmian:

  • -2 jz w trakcie zmiany zamiast używać zmiany 64-bitowej do obsługi >>(32-0)specjalnego przypadku.
  • -3 zwraca w ZF zamiast AL, oszczędzając 3 bajty dla a setnz al .

(Zobacz także odpowiedź na 32-bitowy kod maszynowy Daniela Scheplera opartą na tym , która następnie ewoluowała, aby użyć innych pomysłów, które mieliśmy. moją najnowszą wersję tego na dole tej odpowiedzi).


Zwraca ZF = 0 dla hosta nie podsieci, ZF = 1 dla podsieci, dzięki czemu można rozgałęzić wynik za pomocąje host_matches_subnet

Można wywoływać za pomocą konwencji wywoływania Systemu V x86-64 jako
bool not_in_subnet(int dummy_rdi, const char *input_rsi); przypadku dodawania setnz al.

Łańcuch wejściowy zawiera zarówno host, jak i sieć, oddzielone dokładnie 1 cyfrą. Pamięć po końcu szerokości CIDR musi zawierać co najmniej 3 bajty niebędące cyframi przed końcem strony. (W większości przypadków nie powinno to stanowić problemu, na przykład dla argumentu cmdline). Wersja 32-bitowa Daniela nie ma tego ograniczenia.

3 razy uruchamiamy tę samą pętlę parsowania quad z kropkami, uzyskując dwa adresy IPv4 i otrzymując /maskjako liczbę całkowitą w wysokim bajcie dwordu. (To dlatego musi istnieć czytelna pamięć po /mask, ale nie ma znaczenia, czy są cyfry ASCII.)

Robimy, (host ^ subnet) >> (32-mask)aby przesunąć bity hosta (te, które mogą się nie zgadzać), pozostawiając jedynie różnicę między podsiecią a hostem. Aby rozwiązać /0specjalny przypadek, w którym musimy przesunąć o 32, przeskakujemy zmianę przy liczeniu = 0. ( neg clustawia ZF, który możemy rozgałęzić i pozostawić jako wartość zwracaną, jeśli nie przesuniemy). Zauważ, że 32-mask mod 32 = -maskprzesunięcia skalarne x86 maskują ich liczbę przez & 31lub & 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

(nie zaktualizowany do najnowszej wersji) Wypróbuj online!

w tym _startwywoływanie go argv[1]i zwracanie statusu wyjścia.

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

Działa dobrze, jeśli podasz argument wiersza poleceń zawierający znak nowej linii zamiast spacji. Ale to musi być zamiast , nie tak dobrze.


x86 32-bitowa funkcja kodu maszynowego, 38 bajtów

Wykonaj 9 liczb całkowitych -> uint8_t parsuje i „wypychasz” je na stos, gdzie wyrzucamy je jako dwory lub używamy ostatniego jeszcze w CL. W ogóle unika czytania poza końcem łańcucha.

Ponadto decma tylko 1 bajt w trybie 32-bitowym.

    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

Testuj dzwoniącego

   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
źródło
Jestem ciekawy, jak wyglądałaby 32-bitowa liczba bajtów asm, gdyby zamiast tego cmp/jcc, o którym wspomniałeś, zrobiłeś coś podobnego xor edx,edx;neg cl;cmovz eax,edx;shr eax,cl- a może masz już gdzieś wartość 0. (A potem nie potrzebowałbyś sub cl,32instrukcji.)
Daniel Schepler
1
Tak, wygląda na to, że edipowinna wynosić 0, gdy pętla wychodzi, więc xor eax,edx;neg cl;cmovz eax,edi;shr eax,clpowinna działać.
Daniel Schepler
1
Jeśli dobrze policzyłem, cmove eax,edima 3 bajty, co jest wymywaniem usuniętym, sub cl,32a następnie shr cl,eaxzapisuje jeden bajt ponad, shr cl,raxa 32-bitowy dec edizapisuje jeden bajt ponad 64-bit dec edi. Mój zestaw następnie daje .byte 0x33(w składni binutils GNU) = 51 dla in_subnet.size.
Daniel Schepler
Niezły pomysł, dzięki. (W składni Intela shr eax,cl, w porównaniu ze shr %cl, %eaxskładnią AT&T, twój ostatni komentarz odwrócił to.) Trochę ciężko jest zaktualizować odpowiedzi na kod maszynowy (i przenieść port _startwywołujący i ponownie opisać konwencję wywoływania dla trybu 32-bitowego. .), więc mogę się nie obejść. Czuję się dziś leniwy. >. <
Peter Cordes
1
Właśnie próbowałem zaimplementować komentarz, który umieściłeś na mojej odpowiedzi na temat pozbycia się podwójnej pętli i zamiast tego przechowywania w zmiennych stosu - a nawet z dodatkowym kodem do zainicjowania wskaźnika edizapisu, zapisu danych wyjściowych itp., W efekcie zaoszczędziłem 2 bajty w sieci. (Przynajmniej raz zdałem sobie sprawę, że push ecx;push ecx;push ecxbył krótszy niż sub esp,12; i wydawało mi się, że to pranie, czy przygotowałem wcześniej edii użyłem, std;stosb;cldczy też właśnie przechowałem dec edi;mov [edi],al.
Daniel Schepler
1

Galaretka , 23 bajty

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

Wypróbuj online!

Łącze monadyczne, które bierze adres i podsieć oddzielone ukośnikiem i zwraca 1 dla wartości true i 0 dla wartości false.

Dzięki @gwaugh za wskazanie błędu w oryginale - nie udało się zapewnić, aby lista binarna miała 32 długości.

Nick Kennedy
źródło
1

Perl 5 -Mbigint -MSocket=:all -p , 72 bajtów

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

Wypróbuj online!

Xcali
źródło
1

05AB1E , 21 bajtów

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

Zajmuje podsieć przed adresem.

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

'/¡              '# 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
źródło
1

R 120 bajtów

funkcja - wkleiłem „.32” do pierwszego terminu

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

i dla zabawy:

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

czyli 56 bajtów

Zahiro Mor
źródło
1

PHP ,75 73, 71 bajtów

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

Rozwidlenie odpowiedzi @Luis felipe De jesus Munoz , jako samodzielne pobieranie danych z linii poleceń. Wyjścia '1'dla Truthy, ''(pusty string) dla 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

Wypróbuj online!

-2 bajty pożyczanie małej sztuczki @Christophstrtok() . Jego odpowiedź jest jednak jeszcze krótsza!

640 KB
źródło
1

funkcja montażu x86, 49 43 bajty

Jest to głównie publikowane w celu spełnienia prośby Petera Cordesa o poprawioną wersję, którą stworzyłem. Prawdopodobnie może odejść raz / jeśli uwzględni to w swojej odpowiedzi.

Ta funkcja oczekuje esina ciąg wejściowy, w którym adres i części podsieci są oddzielone spacją lub znakiem nowego wiersza, a zwracana wartość jest w flagi ZF (która z definicji ma tylko dwie możliwe wartości).

 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

Część otoki 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 bajtów z powodu sugestii Petera Cordesa, aby zwrócić wartość w ZF.

Daniel Schepler
źródło
Chyba mógłbym zaoszczędzić jeden bajt, usuwając ostatni xor edx,edxi zastępując cmovz eax,edxgo jz .nonzero; xor eax,eax; .nonzero:. cmovznadal wygrywa, jeśli mamy konwencję wywoływania ebx=0.
Daniel Schepler
Możemy po prostu jznad shrdo setz lub ret? Możemy zamienić setnzsię setzi powrócić 1na mecz, czy to pomaga. Lub nawet powiedzieć, że naszą wartością zwrotną jest ZF. Powinienem był to zrobić w mojej odpowiedzi. (Ale nie sądzę, abyśmy mogli uzasadnić wymaganie od osoby dzwoniącej utworzenia stałych, np ebx=0.. Moja odpowiedź na temat wskazówek dotyczących gry w golfa w kodzie maszynowym x86 / x64 dowodzi, że zbyt daleko posunęłaby się konwencja wywoływania niestandardowego.
Peter Cordes
BTW, używam cutusunąć niektóre kolumny z wydruki NASMa ponieważ wszystkie moje instrukcje są krótkie: nasm -felf foo.asm -l/dev/stdout | cut -b -34,$((34+6))-. Użyłem także mov zamiast movzx w moim programie _startwywołującym, ponieważ status wyjścia pochodzi z małego bajtu argumentu arg sys_exit(). Jądro ignoruje wyższe bajty.
Peter Cordes
Myślę, że to zadziała. To odlicza do 43 bajtów, a następnie wstawiam setnz alpo call in_subnetw opakowaniu.
Daniel Schepler
Tak. Łatwo sobie wyobrazić, że normalnym przypadkiem użycia tej funkcji byłoby call/ je, zamiast drukowania lub dalszego przekazywania wyniku. Jak wskazałem w „poradach”, niektóre konwencje wywołań systemowych już to robią w prawdziwym życiu (zwykle z CF = błąd).
Peter Cordes
1

Java 215 211 207 202 200 199 198 190 180 bajtów

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

Wyjścia truedla prawdy i falsefałszu.

Uwaga: Używa longzamiast intpotencjalnego przesunięcia w prawo o 32.

Wypróbuj online!

Zaoszczędzono 1 bajt dzięki pułapce cat

Zaoszczędź 10 bajtów dzięki Peterowi Cordesowi

Szturchać
źródło
Nie daje to „wyraźnej i spójnej wartości” dla falsey.
AdmBorkBork
Twierdziłbym, że jest wyraźnie i konsekwentnie niezerowy, ale jeśli to nie jest duch wyzwania, mogę to zmienić.
Poke
64-bitowa liczba całkowita obsługuje przesunięcie w lewo o 32. Ponadto możesz przesunąć w prawo,host ^ net aby przesunąć bity, które chcesz usunąć, zamiast tworzyć maskę. Ale myślę, że Java potrzebuje tam porównania, aby utworzyć wartość logiczną z liczby całkowitej. Może a !, ponieważ nie ma znaczenia, które z prawd czy fałszów produkujesz dla których wyników. (Poprosiłem PO o wyjaśnienie, czy zamierzają wykluczyć 0 / niezerowe, i powiedzieli, że tak, byli świadomi konsekwencji tego sformułowania:
Peter Cordes
1
@PeterCordes Konwersja wszystkiego na longto, że stracę trochę bajtów, ale nadrabiam to, mogąc usunąć trójskładnik i wykonać XOR, jak sugerujesz. Sprawdzam, co jeszcze mogę
Poke
1

Węgiel drzewny , 36 bajtów

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

Wypróbuj online! Link jest do pełnej wersji kodu. Traktuje podsieć jako pierwszy parametr i wyświetla dane wyjściowe -tylko wtedy, gdy adres znajduje się w podsieci. Wyjaśnienie:

≔⪪S/θ

Podziel podsieć /.

≔I⊟θζ

Zdejmij maskę i rzuć ją na liczbę całkowitą.

⊞θS

Wciśnij adres do tablicy.

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

Podziel oba adresy ., przekonwertuj je na liczby całkowite, zinterpretuj jako bazę 256 i odrzuć zamaskowane bity.

⁼⊟θ⊟θ

Porównaj dwie wartości.

Neil
źródło
1

Japt , 26 bajtów

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

Spróbuj

-3 bajty dzięki @Shaggy!

Dane wejściowe to tablica z 2 elementami [address, subnet]. Transponowane JS poniżej:

// 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
źródło
26 bajtów
Kudłaty
Ciekawe - nie zdawałem sobie sprawy, że możesz zmusić ciąg do liczby ++.
dana
Tak, jak możesz w JS. Nie ma to jednak sensu, jeśli chcesz później użyć pierwotnej wartości, ale czasami jest to przydatne.
Kudłaty
gDenerwuje mnie potrzeba przecinka w metodzie; w ogóle nie mogę tego rozwiązać. Przynajmniej nie taki, który uratuje ci bajt.
Kudłaty
0

C # (interaktywny kompilator Visual C #) , 187 bajtów

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

Mogę zdecydowanie pograć w golfa bardziej.

Wypróbuj online!

Wcielenie ignorancji
źródło
0

C # (interaktywny kompilator Visual C #) , 134 bajty

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

Wypróbuj online!

Instrukcja LINQ, która przyjmuje 2-elementową tablicę ciągów jako dane wejściowe [address, subnet] formacie.

Każdy kropkowany quad jest przetwarzany na 32 bity długości za pomocą manipulacji bitami. Bity są przesunięte w prawo o rozmiar podsieci, a elementy są porównywane pod kątem równości.

W chwili opublikowania tej odpowiedzi było kilka odpowiedzi w języku C #, ale żadna nie korzystała z czystej manipulacji bitami.

// 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
źródło