Saya di subnet Anda, bermain golf kode Anda

17

Tantangan

Diberi IPv4 addressdalam notasi quad-dotted, dan IPv4 subnetpada notasi CIDR , tentukan apakah IPv4 addressberada di dalam subnet. Keluarkan nilai yang berbeda dan konsisten jika berada dalam subnet, dan nilai yang berbeda dan konsisten terpisah jika tidak ada dalam subnet. Nilai-nilai output tidak harus benar-benar benar / salah dalam bahasa Anda.

CIDR subnet notasi primer singkat

Alamat jaringan IPv4 panjangnya 32 bit, dibagi menjadi empat kelompok 8 bit untuk kemudahan membaca. Notasi subnet CIDR adalah topeng dari jumlah bit yang ditentukan, mulai paling kiri. Misalnya, untuk sebuah /24subnet, ini berarti 8 bit alamat yang paling tepat tersedia di subnet itu. Jadi dua alamat yang dipisahkan oleh paling banyak 255, dan memiliki subnet mask yang sama, berada di subnet yang sama. Perhatikan bahwa CIDR yang valid memiliki semua bit host (sisi kanan) tidak disetel (nol).

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

Untuk contoh lain, sebuah /32subnet menentukan bahwa semua bit adalah subnet mask, yang pada dasarnya berarti bahwa hanya satu host yang diizinkan per /32.

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

Contoh:

Menggunakan Trueuntuk "di subnet" dan Falseuntuk "tidak di subnet" sebagai 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

Aturan dan Klarifikasi

  • Karena parsing input bukan poin menarik dari tantangan ini, Anda dijamin untuk mendapatkan alamat IPv4 dan subnet mask yang valid.
  • Input dan output dapat diberikan dengan metode apa pun yang mudah .
  • Anda dapat mencetak hasilnya ke STDOUT atau mengembalikannya sebagai hasil fungsi. Silakan sebutkan dalam kiriman Anda nilai apa yang bisa diambil oleh output.
  • Program lengkap atau fungsi dapat diterima.
  • Celah standar dilarang.
  • Ini adalah sehingga semua aturan golf biasa berlaku, dan kode terpendek (dalam byte) menang.
AdmBorkBork
sumber
Apakah kita harus mengambil input dalam format yang sama dengan kasus uji Anda?
Perwujudan Ketidaktahuan
1
@EmbodimentofIgnorance Anda tidak harus menganggapnya satu per baris seperti pada contoh, tetapi Anda harus menganggapnya sebagai titik-titik dan titik-titik-titik seperti pada contoh. (misalnya, lihat jawaban JavaScript oleh Arnauld)
AdmBorkBork
Apakah boleh memisahkan mereka dengan garis miring, misalnya 10.0.0.1/10.0.0.0”/16?
Nick Kennedy
1
@ Poke Saya setuju Anda benar karena notasi CIDR menjelaskan alamat IP dan ukuran subnet. Seperti dalam, 1.255.1.1/8adalah ekspresi CIDR yang valid , mewakili host 1.255.1.1dalam jaringan 1.0.0.0dengan subnet mask dari 255.0.0.0. Namun tantangannya meminta nomor jaringan dan subnet khusus dalam notasi CIDR, yang 1.255.1.1/8bukan nomor jaringan dan kombinasi subnet yang valid.
640KB
1
Sekarang kita juga membutuhkan versi IPv6 dari tantangan ini
Ferrybig

Jawaban:

13

Python 3 (62 byte)

Sangat mudah:

from ipaddress import*
lambda i,m:ip_address(i)in ip_network(m)
agtoever
sumber
9
Bagus, tetapi apakah ular sanca memiliki bawaan untuk mengenali kambing juga?
Benjamin Urquhart
3
Tentu saja Mathematica memiliki built-in untuk semuanya - bahkan untuk exoplanet ! Tidak ada yang bisa mengalahkan itu ... Tapi seperti yang bisa Anda lihat, Python cocok dengan kambing-formatace Mathematica
agtoever
Saya bertanya-tanya apakah ip_adressobjek dan ip_networkobjek merupakan any convenient method, mungkin membiarkan Python menang, kecuali jika bahasa golf berbasis python menjadikannya sebagai tipenya?
kata ganti saya adalah monicareinstate
Anda tidak akan mendapatkannya dalam kisaran 20 byte dalam Python normal. Hanya impor dan lambda sudah lebih lama dari jawaban Stax. Ini tidak mengherankan bahwa bahasa golf menang dari bahasa "normal" ... :-(
agtoever
@ seseorang: Saya mengalahkan Python dengan 53 byte kode mesin x86-64 . :) Bukan bahasa golf tradisional, dan sebagian besar ukuran kode adalah parsing string-> int secara manual. (host^net)>>(32-mask)hanya 10 byte. Tapi itu setengah jalan di antara untuk tugas-tugas yang tidak melibatkan daftar daftar, atau memetakan fungsi ke daftar, karena banyak operasi skalar dapat dilakukan dengan instruksi 2 atau 3 byte, dan loop dapat dibangun di sekitar hal-hal dalam beberapa byte.
Peter Cordes
4

C # (Visual C # Compiler) , 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 termasuk using System;using System.Linq;

Cobalah online!

Saya menulis ini di JS segera setelah tantangan diposting, tetapi Arnauld mengalahkan saya sampai tepat dengan jawaban yang jauh lebih baik, jadi ini dia dalam C #.

Pasti banyak ruang untuk bermain golf.

Penjelasan:

Fungsi terdiri dari sub-fungsi yang disebut 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;
    }
);

Subfungsi ini membagi Alamat IP aktif ., mengubah setiap nomor menjadi string biner, dengan bantalan kiri masing-masing string0 menjadi 8 bit, kemudian menggabungkan string menjadi satu string biner 32-bit.

Ini segera dilakukan di tempat dengan a=h(a);pada Alamat IP yang diberikan.
Kami kemudian membagi Subnet mask menjadi Alamat IP dan nomor mask denganc=b.Split('/');

Komponen Alamat IP juga dilewatkan melalui sub-fungsi kami: b=h(c[0]);dan nomor mask diurai ke integer:var d=int.Parse(c[1]);

Akhirnya kita mengambil dbit pertama dari kedua string biner (di mana dnomor mask) dan membandingkannya:return a.Substring(0,d)==b.Substring(0,d);

Skidsdev
sumber
1
Terlalu lelah untuk menyelesaikan ini, jadi saya hanya men
Data Kedaluwarsa
1
Sebenarnya lupa tentang PadLeft di dalamnya juga Coba online!
Data Kedaluwarsa
Banyak optimasi. Dengan senang hati saya memberi tahu Anda bahwa Anda rPadmemiliki string bawaan. tautan pastebin ke tautan TIO yang terlalu panjang
kata ganti saya adalah monicareinstate
2
@someone Small FYI: Penyingkat URL seperti tinyurl.com diizinkan dalam komentar di SE ini, tidak seperti kebanyakan. :)
Kevin Cruijssen
1
188 - tinyurl.com/y6xfkbxt - tips memperpendek url yang bagus @KevinCruijssen
dana
4

Linux POSIX shell (dengan net-tools / iputils) (34 byte non-terminating, 47 byte terminating)

Apa yang paling cocok untuk mengurai topeng dan alamat jaringan daripada utilitas jaringan itu sendiri? :)

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

Peringatan: skrip berpotensi merusak konektivitas Internet Anda, harap jalankan dengan hati-hati.

Input: skrip mengambil alamat IP yang diuji sebagai argumen pertama, dan subnet yang diuji. sebagai argumen kedua.

Keluaran: skrip mengembalikan nilai kebenaran (0) jika argumen pertama skrip milik subnet yang ditunjukkan dalam argumen kedua. Kalau tidak, itu tidak akan pernah berakhir.

Asumsi: skrip harus dijalankan sebagai pengguna root, di lingkungan yang bersih ( yaitu , tidak ada rute lubang hitam lain yang telah ditetapkan oleh administrator, dan jika instance skrip sebelumnya telah dijalankan, rute lubang hitam yang dibuatnya telah dihapus ). Skrip juga mengasumsikan "koneksi Internet yang berfungsi" ( yaitu , rute default yang valid ada).


Penjelasan:

Kami membuat rute blackhole ke subnet yang ditentukan. Kami kemudian menguji konektivitas ke alamat IP yang disediakan dengan menggunakan ping . Jika alamat tersebut bukan milik subnet (dan karena kami menganggap koneksi Internet diatur dengan benar), ping akan mencoba mengirim paket ke alamat itu. Perhatikan bahwa apakah alamat ini benar-benar merespons tidak masalah, karena ping akan terus mencoba selamanya. Sebaliknya, jika alamat itu milik subnet, ping akan gagal dengan ENETUNREACH dan mengembalikan 2, dan karena kita meniadakan perintah, skrip akan berhasil.


Contoh

Uji apakah 5.5.5.5 milik 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...]

(Bersihkan dengan sudo ip route del 8.8.8.0/24setelah menjalankan perintah).

Uji apakah 5.5.5.5 milik 5.5.5.0/24:

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

(Bersihkan dengan sudo ip route del 5.5.5.0/24setelah menjalankan perintah).

Uji apakah 8.8.8.8 milik 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...]

(Bersihkan dengan sudo ip route del 5.5.5.0/24setelah menjalankan perintah).


Versi 47 byte jika kita melarang skrip yang tidak berhenti

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

Sesuai komentar @ Grimy, inilah versi yang selalu berakhir, dan mengembalikan 0 (benar) jika alamatnya ada di subnet, dan 1 (salah) sebaliknya. Kami membuat ping berakhir dengan -c1bendera yang membatasi jumlah paket yang dikirim ke 1. Jika alamat merespons, ping akan mengembalikan 0, dan jika tidak, ping akan kembali 1. Hanya jika alamat milik subnet yang dihitamkan akan melakukan ping kembali 2, yang dengan demikian kita uji terhadap pada perintah terakhir.

yoann
sumber
3
Meskipun pintar, ini tidak memenuhi persyaratan untuk menghasilkan nilai yang berbeda dan konsisten jika alamat tersebut tidak ada di subnet ( berjalan selamanya tidak dihitung sebagai output , lihat juga ini ).
Grimmy
1
@ Grimy: Tapi itu tidak berjalan diam - diam selamanya, jadi hanya tautan kedua Anda yang berlaku, bukan yang pertama. Juga saya pikir pingakan mati dari SIGPIPE jika dijalankan dengan stdout + stderr disalurkan ke program lain, dan pembaca menutup pipa. Dan itu adalah kasus penggunaan yang paling mungkin karena status keluar dapat berhasil dengan cara apa pun (jika kami menambahkan -c1opsi untuk melakukan ping untuk mengatur penghitungan.) Tetapi tentu saja, membaca hasilnya dengan var=$(/a.sh)akan gagal; Anda akan membutuhkan pembaca yang berhenti setelah memutuskan, daripada membaca seluruh output dan kemudian melihatnya.
Peter Cordes
@Grimy Fair point (walaupun demi argumen saya dapat mengatakan bahwa kami memiliki dua nilai yang konsisten di sini, karena pingakan berakhir dalam waktu kurang dari, katakanlah, satu detik dalam kasus alamat yang dihitamkan). Saya menambahkan versi terminating untuk tambahan 13 byte! :)
yoann
3

JavaScript (ES6), 82 byte

Mengambil input sebagai (address)(subnet) . Mengembalikan nilai Boolean.

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

Cobalah online!

Arnauld
sumber
3

PHP , 101 92 88 byte

-13 byte dari @gwaugh

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

Cobalah online!

Luis felipe De jesus Munoz
sumber
2
Bersenang-senang bermain golf itu (Ty!):function($i,$r){return!((ip2long($i)^ip2long(strtok($r,'/')))>>32-strtok(_));}
Christoph
@Christoph sangat bagus! Tidak pernah terpikir oleh saya bahwa Anda bisa menggunakan token apa pun untuk panggilan kedua strtok(). Milik Anda 4 byte lebih pendek dari jawaban saya yang sangat mirip di bawah ini. Atribut!
640KB
@Christoph Anda harus memposting solusi Anda sebagai jawaban yang terpisah karena lebih baik daripada saya.
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]);}

(Diuji pada x86_64 Ubuntu 18.04 menggunakan powerpc64-linux-gnu-gcc -static dan qemu-user.)

Program mengambil dua baris pada input standar, dan sebagai kode keluarnya mengembalikan 1 jika alamat cocok dan 0 jika tidak. (Jadi ini tergantung pada spesifikasi yang tidak membutuhkan nilai kebenaran untuk pertandingan dan nilai kesalahan untuk ketidakcocokan.) Perhatikan bahwa jika Anda menjalankan secara interaktif, Anda perlu memberi sinyal EOF ( ^D) tiga kali setelah memasukkan baris kedua.

Ini bergantung pada PowerPC sebagai big-endian, dan juga pada platform yang mengembalikan 0 untuk menggeser nilai 32-bit yang tidak ditandatangani oleh 32. Ia membaca oktet menjadi nilai yang tidak ditandai satu-per-satu, bersama dengan panjang netmask pada byte lain ; kemudian mengambil xor dari dua alamat 32-bit yang tidak ditandatangani dan menggeser bit yang tidak relevan. Akhirnya, itu berlaku !untuk memenuhi persyaratan mengembalikan hanya dua nilai yang berbeda.

Catatan: mungkin mungkin untuk mencukur dua byte dengan mengganti u+3dengan pdan membutuhkan kompilasi dengan -O0. Tapi itu hidup lebih berbahaya daripada yang aku pedulikan.

Terima kasih kepada Peter Cordes untuk inspirasi untuk solusi ini.


Lebih portabel C, 186 171 167 byte

Di sini saya akan mempertahankan versi yang lebih portabel yang berjalan 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);}

Program ini mengambil dua baris pada input standar, dan mengembalikan kode keluar 1 jika alamatnya ada di subnet, dan 0 jika tidak. (Jadi ini bergantung pada spesifikasi yang tidak membutuhkan nilai kebenaran untuk pertandingan dan nilai palsu untuk tidak cocok.)

Rincian ekspresi inti:

  • a^e, b^f, c^g, d^hMenghitung XOR dari alamat dan topeng byte-by-byte.
  • (((a^e)<<8|b^f)<<8|c^g)<<8|d^h kemudian menggabungkan mereka ke dalam nilai 32-bit unsigned tunggal dengan metode seperti Horner.
  • ...>>32-nkemudian menggeser bit dari perbedaan xor yang tidak relevan dengan subnet mask (mengingat bahwa -memiliki prioritas lebih tinggi dalam C daripada <<)
  • Ada satu gotcha, meskipun: jika n = 0 maka ~0U<<32akan memberikan perilaku yang tidak terdefinisi dengan asumsi unsigned32 bit (yang ada di hampir semua platform saat ini). Di sisi lain, jika n = 0 maka alamat mana pun akan cocok, sehingga n&&...akan memberikan hasil yang benar (memanfaatkan perilaku hubungan arus pendek &&).
  • Akhirnya, untuk memenuhi persyaratan bahwa output hanya bisa menjadi salah satu dari dua nilai, kami berlaku !untuk output 0 atau 1.

-15 byte karena komentar oleh ceilingcat dan AdmBorkBork

-4 byte karena komentar dari Peter Cordes

Daniel Schepler
sumber
1
Menggunakan kode keluar untuk mengembalikan nilai adalah salah satu metode I / O default dan karenanya diizinkan.
AdmBorkBork
@ceilingcat Tentu saja, betapa konyolnya aku melewatkan itu.
Daniel Schepler
@ AdmBorkBork OK, terima kasih, saya telah mengubahnya untuk menggunakan kode keluar.
Daniel Schepler
ide: target implementasi C little-endian atau big-endian (kode-golf tidak memerlukan kode portabel) dan ketik-pun output pointer ke byte dari sebuah unsigned. misalnya dengan char*p=&akemudian p++,p++,p++,...atau p--,...sebagai scanf args. Namun, format string perlu "%hhu.%hhu...", jadi itu adalah tradeoff yang signifikan antara ukuran ekstra vs mendeklarasikan lebih sedikit vars dan mampu melakukannya(a^b)>>(32-count)
Peter Cordes
1
@PeterCordes Yup, shift yang tepat berfungsi, terima kasih.
Daniel Schepler
2

Stax , 22 byte

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

Jalankan dan debug itu

Dibutuhkan parameter input yang dipisahkan oleh ruang pada input standar.

Dibongkar, tidak diserang, dan dikomentari, sepertinya ini.

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

Jalankan yang ini

rekursif
sumber
2

fungsi kode mesin x86-64, 53 48 byte

changelog:

  • -2 jz alih-alih shift alih-alih menggunakan shift 64-bit untuk menangani >>(32-0)case khusus.
  • -3 kembali dalam ZF bukan AL, menghemat 3 byte untuk setnz al .

(Lihat juga jawaban kode mesin 32-bit Daniel Schepler berdasarkan ini, yang kemudian berevolusi untuk menggunakan beberapa ide lain yang kami miliki. Saya menyertakan versi terbaru saya tentang itu di bagian bawah jawaban ini.)


Mengembalikan ZF = 0 untuk host tidak di subnet, ZF = 1 untuk di subnet, sehingga Anda dapat bercabang pada hasilnya denganje host_matches_subnet

Callable dengan konvensi pemanggilan System V x86-64 seolah-
bool not_in_subnet(int dummy_rdi, const char *input_rsi);olah Anda menambahkansetnz al .

String input berisi host dan jaringan, dipisahkan dengan tepat 1 karakter non-digit. Memori yang mengikuti ujung lebar CIDR harus mengandung setidaknya 3 byte non-digit sebelum akhir halaman. (Seharusnya tidak menjadi masalah dalam kebanyakan kasus, seperti untuk argumen cmdline.) Versi 32-bit Daniel tidak memiliki batasan ini.

Kami menjalankan loop parse bertitik-quad yang sama 3 kali, mendapatkan dua alamat IPv4, dan mendapatkan /masksebagai integer dalam byte tinggi kata. (Inilah sebabnya mengapa harus ada memori yang dapat dibaca setelah /mask, tetapi tidak masalah jika ada angka ASCII.)

Kami lakukan (host ^ subnet) >> (32-mask)untuk menggeser bit host (yang diizinkan untuk tidak cocok), hanya menyisakan perbedaan antara subnet dan host. Untuk menyelesaikan /0kasus khusus di mana kita perlu menggeser sebesar 32, kita melompati shift dengan hitungan = 0. ( neg clset ZF, yang bisa kita percabang dan tinggalkan sebagai nilai balik jika kita tidak menggeser.) Perhatikan itu 32-mask mod 32 = -mask, dan x86 pergeseran skalar menyamarkan jumlah mereka dengan & 31atau & 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

(tidak diperbarui dengan versi terbaru) Cobalah secara online!

termasuk a _startyang memanggilnya argv[1]dan mengembalikan status keluar.

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

Ini berfungsi dengan baik jika Anda melewati argumen baris perintah yang berisi baris baru dan bukan spasi. Tetapi harus sebaliknya , tidak juga.


fungsi kode mesin x86 32-bit, 38 byte

Do 9 integer -> uint8_t mem-parsing dan "mendorong" mereka di stack, di mana kita mematikannya sebagai kata-kata atau menggunakan yang terakhir masih di CL. Hindari membaca melewati ujung string sama sekali.

Juga, dechanya 1 byte dalam mode 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

Penelepon uji

   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
sumber
Saya ingin tahu bagaimana hitungan 32-bit asm byte akan berlaku jika alih-alih cmp/jccyang Anda sebutkan Anda melakukan sesuatu seperti xor edx,edx;neg cl;cmovz eax,edx;shr eax,cl- atau mungkin Anda sudah memiliki nilai 0 nongkrong di suatu tempat. (Dan kemudian Anda tidak akan memerlukan sub cl,32instruksi.)
Daniel Schepler
1
Yup, sepertinya ediharus 0 ketika loop keluar, jadi xor eax,edx;neg cl;cmovz eax,edi;shr eax,clharus bekerja.
Daniel Schepler
1
Jika saya menghitung dengan benar, cmove eax,edimemiliki 3 byte yang merupakan wash over yang dihapus sub cl,32kemudian shr cl,eaxmenyimpan satu byte lebih shr cl,raxdan 32-bit dec edimenyimpan satu byte lebih dari 64-bit dec edi. Majelis saya kemudian memberikan .byte 0x33(dalam sintaks GNU binutils) = 51 untuk in_subnet.size.
Daniel Schepler
Ide bagus, terima kasih. (Dalam sintaks Intel shr eax,cl, vs. shr %cl, %eaxdalam sintaks AT&T, komentar terakhir Anda membalikkan itu.) Agak sulit untuk memperbarui jawaban kode mesin (dan port _startpemanggil dan uraikan kembali konvensi pemanggilan untuk mode 32-bit .. .), jadi saya mungkin tidak bisa melakukannya. Merasa malas hari ini. >. <
Peter Cordes
1
Saya baru saja mencoba menerapkan komentar yang Anda berikan pada jawaban saya tentang menyingkirkan loop ganda dan bukannya menyimpan ke dalam variabel stack - dan bahkan dengan kode tambahan untuk menginisialisasi pointer editulis, tulis output, dll. Akhirnya menghemat 2 byte dalam jaring (Paling tidak satu kali saya sadari push ecx;push ecx;push ecxlebih pendek dari sub esp,12; dan itu sepertinya merupakan pembasuhan apakah saya telah ditetapkan sebelumnya edidan digunakan std;stosb;cldatau apakah saya baru saja disimpan menggunakan dec edi;mov [edi],al.
Daniel Schepler
1

Jelly , 23 byte

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

Cobalah online!

Tautan monadik yang mengambil alamat dan subnet dipisahkan oleh garis miring dan mengembalikan 1 untuk true dan 0 untuk false.

Terima kasih kepada @gwaugh karena menunjukkan kekurangan pada aslinya - gagal memastikan daftar binernya 32 panjang.

Nick Kennedy
sumber
1

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

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

Cobalah online!

Xcali
sumber
1

05AB1E , 21 byte

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

Mengambil subnet sebelum alamat.

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

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

R 120 byte

fungsi - saya tempelkan ".32" ke istilah pertama

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

dan hanya untuk bersenang-senang:

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

yaitu 56 byte

Zahiro Mor
sumber
1

PHP ,75 73, 71 byte

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

Sebuah fork jawaban @Luis felipe De jesus Munoz , sebagai mandiri mengambil input dari argumen baris perintah. Output '1'untuk Truthy, ''(string kosong) untuk 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

Cobalah online!

-2 byte meminjam sedikit trik untuk Christophstrtok() . Jawabannya masih lebih pendek!

640KB
sumber
1

fungsi perakitan x86, 49 43 byte

Ini sebagian besar diposting untuk memenuhi permintaan Peter Cordes untuk versi revisi yang saya buat. Mungkin bisa hilang sekali / jika dia memasukkannya ke dalam jawabannya.

Fungsi ini berharap esiuntuk menunjuk ke string input, dengan bagian alamat dan subnet dipisahkan baik oleh spasi atau karakter baris baru, dan nilai kembali berada di bendera ZF (yang menurut definisi hanya memiliki dua nilai yang mungkin).

 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

Dan bagian pembungkus x86 Linux:

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

-6 byte karena saran dari Peter Cordes untuk mengembalikan nilai dalam ZF.

Daniel Schepler
sumber
Saya kira saya bisa menyimpan satu byte dengan menghapus yang terakhir xor edx,edxdan mengganti cmovz eax,edxdengan jz .nonzero; xor eax,eax; .nonzero:. cmovzmasih menang jika kita memiliki konvensi panggilan ebx=0.
Daniel Schepler
Bisakah kita hanya jzatas shrke Setz atau ret itu? Kami dapat menukar setnzke setzdan kembali 1untuk pertandingan jika itu membantu. Atau bahkan mengatakan bahwa nilai pengembalian kami adalah ZF. Seharusnya saya melakukan itu dalam jawaban saya. (Tapi saya tidak berpikir kita dapat membenarkan mengharuskan penelepon membuat konstanta untuk kita, seperti ebx=0. Jawaban saya pada Tips untuk bermain golf dalam kode mesin x86 / x64 berargumen bahwa terlalu jauh akan memperpanjang konvensi panggilan kustom.
Peter Cordes
BTW, saya menggunakan cutuntuk menghapus beberapa kolom dari NASM daftar output karena semua instruksi saya singkat: nasm -felf foo.asm -l/dev/stdout | cut -b -34,$((34+6))-. Juga, saya menggunakan mov daripada movzx di _startpemanggil saya karena status keluar berasal dari byte rendah dari arg ke sys_exit(). Kernel mengabaikan byte yang lebih tinggi.
Peter Cordes
Saya kira itu akan berhasil. Itu mengambil hitungan ke 43 byte dan kemudian saya masukkan setnz alsetelah call in_subnetdalam bungkus.
Daniel Schepler
Ya. Mudah untuk membayangkan kasus penggunaan normal untuk fungsi inicall / je, daripada mencetak atau meneruskan hasilnya. Seperti yang saya tunjukkan dalam "tips", beberapa konvensi pemanggilan sistem sudah melakukan ini dalam kehidupan nyata (biasanya dengan CF = kesalahan).
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;}

Keluaran trueuntuk kebenaran dan falsekepalsuan.

Catatan: Ini menggunakan longalih-alih intuntuk potensi pergeseran kanan 32.

Cobalah online!

Disimpan 1 byte berkat ceilingcat

Disimpan 10 byte berkat Peter Cordes

Menyodok
sumber
Ini tidak menghasilkan "nilai yang berbeda dan konsisten" untuk falsey.
AdmBorkBork
Saya berpendapat bahwa itu jelas dan konsisten bukan nol tetapi jika itu bukan semangat tantangan, saya bisa mengubahnya.
Poke 3-19
Bilangan bulat 64-bit mendukung pergeseran-kiri sebesar 32. Selain itu, Anda dapat menggeser ke kananhost ^ net untuk menggeser bit yang ingin Anda hapus, alih-alih benar-benar membuat topeng. Tapi saya kira Java perlu membandingkan di sana untuk membuat boolean dari integer. Mungkin! , karena tidak masalah mana yang benar atau salah yang Anda hasilkan untuk output mana. (Saya meminta OP untuk klarifikasi tentang apakah mereka bermaksud mengecualikan 0 / non-nol, dan mereka menjawab ya mereka sadar akan konsekuensi dari kata-kata itu:
Peter Cordes
1
@PeterCordes Mengubah segala sesuatu untuk longtidak kehilangan saya beberapa byte tapi saya menebusnya dengan bisa menghapus ternary dan melakukan XOR seperti yang Anda sarankan. Saya sedang memeriksa apa lagi yang bisa saya mainkan sebelum memposting
Poke
1

Arang , 36 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Mengambil subnet sebagai parameter pertama dan dan output -hanya jika alamatnya berada di dalam subnet. Penjelasan:

≔⪪S/θ

Split subnet aktif /.

≔I⊟θζ

Lepaskan topeng dan cor ke integer.

⊞θS

Dorong alamat ke array.

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

Membagi kedua alamat ., mengonversinya menjadi bilangan bulat, mengartikannya sebagai basis 256, dan membuang bit bertopeng.

⁼⊟θ⊟θ

Bandingkan kedua nilai tersebut.

Neil
sumber
1

Japt , 26 byte

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

Cobalah

-3 byte terima kasih kepada @Shaggy!

Input adalah array dengan 2 elemen [address, subnet]. JS yang dialihkan di bawah ini:

// 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
sumber
26 byte
Shaggy
Menarik - Saya tidak menyadari Anda bisa memaksa string ke nomor ++.
dana
Yup, sama seperti Anda bisa di JS. Tidak ada gunanya, meskipun, jika Anda perlu menggunakan kembali nilai asli nanti, tapi itu berguna kadang-kadang.
Shaggy
Kebutuhan akan koma dalam gmetode ini mengganggu saya; tidak bisa menemukan jalan keluar sama sekali. Setidaknya tidak satu yang akan menghemat satu byte.
Shaggy
0

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

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

Saya pasti bisa menurunkan ini lebih banyak.

Cobalah online!

Perwujudan Ketidaktahuan
sumber
0

C # (Visual C # Interactive Compiler) , 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

Cobalah online!

Pernyataan LINQ yang menggunakan array string 2-elemen sebagai input [address, subnet] format.

Setiap quad putus-putus dikonversi menjadi 32 bit yang panjang menggunakan manipulasi bit. Bit digeser dengan benar oleh ukuran subnet dan elemen dibandingkan untuk kesetaraan.

Ada beberapa jawaban C # pada saat jawaban ini diposting, tetapi tidak ada yang menggunakan manipulasi bit murni.

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