Tôi đang ở trong mạng con của bạn, chơi mã của bạn


17

Thử thách

Đưa ra một IPv4 addresstheo ký hiệu bốn chấm và một IPv4 subnettrong ký hiệu CIDR , xác định xem addresscó trong ký hiệu đó khôngsubnet . Xuất ra một giá trị riêng biệt và nhất quán nếu nó nằm trong subnetvà một giá trị riêng biệt và nhất quán riêng biệt nếu nó không nằm trong subnet. Các giá trị đầu ra không nhất thiết phải trung thực / falsey trong ngôn ngữ của bạn.

Tóm tắt ký hiệu mạng con CIDR

Địa chỉ mạng IPv4 có độ dài 32 bit, được chia thành bốn nhóm 8 bit để dễ đọc. Ký hiệu mạng con CIDR là mặt nạ của số bit được chỉ định, bắt đầu từ ngoài cùng bên trái. Ví dụ, đối với một /24mạng con, điều này có nghĩa là 8 bit bên phải của địa chỉ có sẵn trong mạng con đó. Do đó, hai địa chỉ cách nhau tối đa 255và có cùng mặt nạ mạng con, nằm trong cùng một mạng con. Lưu ý rằng CIDR hợp lệ có tất cả các bit máy chủ (phía bên phải) không được đặt (số không).

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

Đối với một ví dụ khác, một /32mạng con chỉ định rằng tất cả các bit là mặt nạ mạng con, về cơ bản có nghĩa là chỉ có một máy chủ được phép trên mỗi /32.

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

Ví dụ:

Sử dụng Truecho "trong mạng con" và Falsecho "không phải trong mạng con" làm đầu ra:

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

Quy tắc và làm rõ

  • Vì phân tích cú pháp đầu vào không phải là điểm thú vị của thử thách này, bạn được đảm bảo có được địa chỉ IPv4 và mặt nạ mạng con hợp lệ.
  • Đầu vào và đầu ra có thể được đưa ra bởi bất kỳ phương pháp thuận tiện .
  • Bạn có thể in kết quả sang STDOUT hoặc trả lại dưới dạng kết quả hàm. Vui lòng nêu trong bài nộp của bạn những giá trị mà đầu ra có thể mất.
  • Một chương trình đầy đủ hoặc một chức năng được chấp nhận.
  • Sơ hở tiêu chuẩn bị cấm.
  • Đây là vì vậy tất cả các quy tắc chơi gôn thông thường đều được áp dụng và mã ngắn nhất (tính bằng byte) sẽ thắng.

Chúng tôi có phải lấy đầu vào ở cùng định dạng với các trường hợp thử nghiệm của bạn không?
Hiện thân của sự thiếu hiểu biết

1
@EmbodimentofIgnorance Bạn không cần phải xem chúng dưới dạng một dòng như trong các ví dụ, nhưng bạn cần phải xem chúng như một mạng con rải rác và mạng con chấm như trong các ví dụ. (ví dụ: xem câu trả lời JavaScript của Arnauld)
admBorkBork

Bạn có thể tách chúng ra bằng một dấu gạch chéo 10.0.0.1/10.0.0.0”/16không?
Nick Kennedy

1
@Poke Tôi đồng ý rằng bạn đúng trong ký hiệu CIDR mô tả địa chỉ IP và kích thước mạng con. Như trong, 1.255.1.1/8là một biểu thức CIDR hợp lệ , đại diện cho máy chủ 1.255.1.1trong mạng 1.0.0.0với mặt nạ mạng con là 255.0.0.0. Tuy nhiên, thách thức yêu cầu số mạng và mạng con cụ thể trong ký hiệu CIDR, đây 1.255.1.1/8không phải là kết hợp số mạng và mạng con hợp lệ.
640KB

1
Bây giờ chúng tôi cũng cần một phiên bản IPv6 của thử thách này
Ferrybig

Câu trả lời:


13

Python 3 (62 byte)

Rất đơn giản:

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

9
Đẹp, nhưng trăn có tích hợp để nhận biết dê không?
Benjamin Urquhart

3
Tất nhiên Mathicala có tích hợp sẵn cho mọi thứ - ngay cả đối với các ngoại hành tinh ! Không gì có thể vượt qua điều đó ... Nhưng như bạn có thể thấy, Python phù hợp với hình dạng con dê của Mathematica
bất chấp

Tôi tự hỏi liệu một ip_adressđối tượng và một ip_networkđối tượng có cấu thành any convenient method, có thể để Python chiến thắng không, trừ khi một ngôn ngữ chơi gôn dựa trên trăn có những kiểu này không?
đại từ của tôi là monicareinstate

Bạn sẽ không nhận được nó trong phạm vi 20 byte trong Python bình thường. Chỉ nhập và lambda đã dài hơn câu trả lời Stax. Không có gì ngạc nhiên khi các ngôn ngữ chơi gôn giành chiến thắng từ các ngôn ngữ "bình thường" ... :-(
bất chấp

@someone: Tôi đánh bại Python với 53 byte mã máy x86-64 . :) Không phải là ngôn ngữ chơi golf truyền thống và hầu hết kích thước mã là phân tích chuỗi-> int theo cách thủ công. (host^net)>>(32-mask)chỉ có 10 byte. Nhưng đó là một nửa giữa các nhiệm vụ không liên quan đến danh sách danh sách hoặc ánh xạ hàm vào danh sách, bởi vì nhiều thao tác vô hướng có thể được thực hiện bằng lệnh 2 hoặc 3 byte và các vòng lặp có thể được xây dựng xung quanh mọi thứ trong một vài byte.
Peter Cordes

4

C # (Trình biên dịch C # trực quan) , 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 bao gồm using System;using System.Linq;

Hãy thử trực tuyến!

Tôi đã viết điều này trong JS ngay khi thử thách được đăng, nhưng Arnauld đã đánh tôi bằng cú đấm với câu trả lời tốt hơn nhiều, vì vậy đây là ở C #.

Chắc chắn rất nhiều phòng để chơi golf.

Giải trình:

Hàm này bao gồm một hàm phụ gọi là 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;
    }
);

Hàm phụ này phân tách Địa chỉ IP trên ., chuyển đổi từng số thành chuỗi nhị phân, phần đệm bên trái mỗi chuỗi có độ 0dài 8 bit, sau đó nối các chuỗi thành một chuỗi nhị phân 32 bit.

Điều này ngay lập tức được thực hiện tại chỗ với a=h(a);trên Địa chỉ IP đã cho.
Sau đó chúng tôi chia mặt nạ mạng con thành Địa chỉ IP và số mặt nạ vớic=b.Split('/');

Thành phần Địa chỉ IP cũng được chuyển qua chức năng phụ của chúng tôi: b=h(c[0]);và số mặt nạ được phân tách thành một số nguyên:var d=int.Parse(c[1]);

Cuối cùng, chúng tôi lấy các dbit đầu tiên của cả hai chuỗi nhị phân (trong đó dlà số mặt nạ) và so sánh chúng:return a.Substring(0,d)==b.Substring(0,d);


1
Quá mệt mỏi để làm việc này vì vậy tôi chỉ chơi Golf cho bạn
Dữ liệu hết hạn vào

1
Thực tế đã quên PadLeft trong đó quá Hãy thử trực tuyến!
Dữ liệu hết hạn

Rất nhiều tối ưu hóa. Tôi rất vui khi thông báo cho bạn rằng rPadchuỗi của bạn được tích hợp sẵn. liên kết pastebin đến liên kết TIO quá dài một mình
đại từ của tôi là monicareinstate

2
@someone FYI nhỏ: Các công cụ rút ngắn URL như tinyurl.com được cho phép trong các nhận xét về SE này, không giống như hầu hết. :)
Kevin Cruijssen

1
188 - tinyurl.com/y6xfkbxt - mẹo rút ngắn url đẹp @KevinCruijssen
dana

4

Shell POSIX của Linux (với các công cụ mạng / iputils) (34 byte không kết thúc, 47 byte kết thúc)

Điều gì phù hợp nhất để phân tích mặt nạ mạng và địa chỉ hơn các tiện ích mạng? :)

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

Cảnh báo: tập lệnh có khả năng gây hại cho kết nối Internet của bạn, vui lòng chạy cẩn thận.

Đầu vào: tập lệnh lấy địa chỉ IP được kiểm tra làm đối số đầu tiên và mạng con được kiểm tra. như đối số thứ hai.

Đầu ra: tập lệnh trả về giá trị trung thực (0) nếu đối số đầu tiên của tập lệnh thuộc về mạng con được chỉ định trong đối số thứ hai. Nếu không, nó sẽ không bao giờ chấm dứt.

Giả định: tập lệnh phải được chạy với tư cách người dùng root, trong môi trường sạch ( nghĩa là không có tuyến đường lỗ đen nào khác được đặt bởi quản trị viên và nếu một phiên bản trước đó của tập lệnh đã được chạy, tuyến đường lỗ đen mà nó tạo ra đã bị xóa ). Kịch bản cũng giả sử "kết nối Internet đang hoạt động" ( nghĩa là có một tuyến mặc định hợp lệ).


Giải trình:

Chúng tôi tạo một tuyến lỗ đen đến mạng con được chỉ định. Sau đó, chúng tôi sẽ kiểm tra kết nối với địa chỉ IP được cung cấp bằng cách sử dụng ping . Nếu địa chỉ không thuộc về mạng con (và vì chúng tôi giả sử kết nối Internet được đặt đúng), ping sẽ cố gắng gửi các gói đến địa chỉ đó. Lưu ý rằng liệu địa chỉ này có thực sự phản hồi hay không, vì ping sẽ tiếp tục cố gắng. Ngược lại, nếu địa chỉ thuộc về mạng con, ping sẽ thất bại với ENETUNREACH và trả về 2 và vì chúng tôi đã từ chối lệnh, tập lệnh sẽ thành công.


Thí dụ

Kiểm tra xem 5.5.5.5 có thuộc về 8.8.8.0/24 không

$ 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...]

(Làm sạch với sudo ip route del 8.8.8.0/24sau khi chạy lệnh).

Kiểm tra xem 5.5.5.5 có thuộc 5.5.5.0/24 hay không:

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

(Làm sạch với sudo ip route del 5.5.5.0/24sau khi chạy lệnh).

Kiểm tra xem 8.8.8.8 có thuộc 5.5.5.0/24 hay không:

$ 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...]

(Làm sạch với sudo ip route del 5.5.5.0/24sau khi chạy lệnh).


Phiên bản 47 byte nếu chúng tôi không cho phép các tập lệnh không kết thúc

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

Theo nhận xét của @ Grimy, đây là phiên bản luôn kết thúc và trả về 0 (trung thực) nếu địa chỉ nằm trong mạng con và 1 (giả mạo) nếu không. Chúng tôi thực hiện chấm dứt ping với -c1cờ giới hạn số lượng gói đã gửi thành 1. Nếu địa chỉ được trả lời, ping sẽ trả về 0 và nếu không, ping sẽ trả về 1. Chỉ khi địa chỉ thuộc mạng con được phủ đen sẽ ping trở lại 2, đó là những gì chúng ta kiểm tra trong lệnh cuối cùng.


3
Mặc dù thông minh, điều này không đáp ứng yêu cầu xuất ra một giá trị riêng biệt và nhất quán nếu địa chỉ không nằm trong mạng con ( chạy mãi mãi không được tính là đầu ra , xem thêm điều này ).
Grimmy

1
@Grimy: Nhưng nó không âm thầm chạy mãi mãi, vì vậy chỉ áp dụng liên kết thứ 2 của bạn chứ không phải liên kết đầu tiên. Ngoài ra tôi nghĩ pingsẽ chết vì SIGPIPE nếu nó đang chạy với thiết bị xuất chuẩn + stderr được dẫn vào một chương trình khác và đầu đọc đã đóng đường ống. Và đó là trường hợp sử dụng rất có thể vì trạng thái thoát có thể thành công theo cách nào đó (nếu chúng tôi đã thêm -c1tùy chọn ping để đặt số đếm.) Nhưng chắc chắn, đọc kết quả đầu ra của nó var=$(/a.sh)sẽ thất bại; bạn sẽ cần một người đọc dừng lại sau khi quyết định, thay vì đọc toàn bộ đầu ra và sau đó nhìn vào nó.
Peter Cordes

@Grimy Điểm công bằng (mặc dù vì lý do tôi có thể nói rằng chúng ta có hai giá trị nhất quán ở đây, vì pingsẽ chấm dứt trong ít hơn, giả sử, một giây trong trường hợp địa chỉ bị bôi đen). Tôi đã thêm một phiên bản kết thúc cho thêm 13 byte! :)
yoann

3

JavaScript (ES6), 82 byte

Đưa đầu vào là (address)(subnet). Trả về giá trị 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))

Hãy thử trực tuyến!


3

PHP , 101 92 88 byte

-13 byte từ @gwaugh

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

Hãy thử trực tuyến!


2
Có một số hoạt động vui chơi golf (Ty!):function($i,$r){return!((ip2long($i)^ip2long(strtok($r,'/')))>>32-strtok(_));}
Christoph

@Christoph rất hay! Tôi chưa bao giờ nghĩ rằng bạn chỉ có thể sử dụng bất kỳ mã thông báo nào cho cuộc gọi thứ hai strtok(). Của bạn ngắn hơn 4 byte so với câu trả lời rất giống của tôi dưới đây. Đạo cụ!
640KB

@Christoph Bạn nên đăng giải pháp của mình dưới dạng câu trả lời riêng vì nó tốt hơn của tôi.
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]);}

(Đã thử nghiệm trên x86_64 Ubuntu 18.04 bằng cách sử dụng powerpc64-linux-gnu-gcc -static và qemu-user.)

Chương trình lấy hai dòng trên đầu vào tiêu chuẩn và làm mã thoát của nó, nó trả về 1 nếu địa chỉ khớp và 0 nếu không. (Vì vậy, điều này phụ thuộc vào thông số kỹ thuật không yêu cầu giá trị trung thực cho trận đấu và giá trị chim ưng cho sự không phù hợp.) Lưu ý rằng nếu bạn đang chạy tương tác, bạn sẽ cần phải báo hiệu EOF ( ^D) ba lần sau khi vào dòng thứ hai.

Điều này phụ thuộc vào PowerPC là công cụ lớn và cũng trên nền tảng đó trả về 0 để dịch chuyển giá trị không dấu 32 bit sang 32. Nó đọc các octet thành các giá trị không dấu từng cái một, cùng với độ dài netmask trong một byte khác ; sau đó nó lấy xor của hai địa chỉ 32 bit không dấu và chuyển ra các bit không liên quan. Cuối cùng, nó được áp dụng !để đáp ứng yêu cầu chỉ trả lại hai giá trị riêng biệt.

Lưu ý: Nó có thể là có thể cạo hai byte bằng cách thay thế u+3với pvà đòi hỏi biên soạn với -O0. Tuy nhiên, điều đó sống nguy hiểm hơn tôi quan tâm.

Cảm ơn Peter Cordes đã truyền cảm hứng cho giải pháp này.


C di động hơn, 186 171 167 byte

Ở đây tôi sẽ bảo tồn một phiên bản di động hơn, chạy được 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);}

Chương trình này lấy hai dòng trên đầu vào tiêu chuẩn và trả về mã thoát 1 nếu địa chỉ nằm trong mạng con và 0 nếu không có. (Vì vậy, điều này không phụ thuộc vào đặc điểm kỹ thuật không yêu cầu giá trị trung thực cho các kết quả khớp và giá trị falsey cho các kết quả không khớp.)

Bảng phân tích biểu thức cốt lõi:

  • a^e, b^f, c^g, d^hTính toán xor của địa chỉ và mặt nạ byte-by-byte.
  • (((a^e)<<8|b^f)<<8|c^g)<<8|d^h sau đó kết hợp chúng thành một giá trị 32 bit không dấu bằng một phương thức giống Horner.
  • ...>>32-nsau đó loại bỏ các bit của chênh lệch xor không liên quan đến mặt nạ mạng con (lưu ý rằng -có độ ưu tiên cao hơn trong C so với <<)
  • Tuy nhiên, có một gotcha: nếu n = 0 thì ~0U<<32sẽ đưa ra hành vi không xác định giả sử unsignedlà 32 bit (có trên hầu hết tất cả các nền tảng hiện tại). Mặt khác, nếu n = 0 thì bất kỳ địa chỉ nào cũng khớp, do đó n&&...sẽ cho kết quả chính xác (lợi dụng hành vi ngắn mạch của &&).
  • Cuối cùng, để đáp ứng yêu cầu đầu ra chỉ có thể là một trong hai giá trị, chúng tôi áp dụng !cho đầu ra 0 hoặc 1.

-15 byte do nhận xét của Barecat và admBorkBork

-4 byte do nhận xét của Peter Cordes


1
Sử dụng mã thoát để trả về giá trị là một trong những phương thức I / O mặc định và do đó được cho phép.
admBorkBork

@ceilingcat Tất nhiên, thật ngớ ngẩn khi tôi bỏ lỡ điều đó.
Daniel Schepler

@AdmBorkBork OK, cảm ơn, tôi đã thay đổi nó để sử dụng mã thoát.
Daniel Schepler

ý tưởng: nhắm mục tiêu triển khai C endian endian hoặc big endian (code-golf không yêu cầu mã di động) và con trỏ đầu ra kiểu chơi chữ vào các byte của một unsigned. ví dụ như char*p=&asau đó p++,p++,p++,...hoặc p--,...như scanf args. "%hhu.%hhu..."Mặc dù vậy, chuỗi định dạng sẽ cần phải có , vì vậy đó là một sự đánh đổi đáng kể giữa kích thước bổ sung đó so với việc khai báo ít vars hơn và có thể thực hiện(a^b)>>(32-count)
Peter Cordes

1
@PeterCordes Yup, ca làm việc đúng, cảm ơn.
Daniel Schepler

2

Stax , 22 byte

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

Chạy và gỡ lỗi nó

Nó lấy các tham số đầu vào được phân tách bằng dấu cách trên đầu vào tiêu chuẩn.

Giải nén, không được chỉnh sửa và nhận xét, nó trông như thế này.

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

Chạy cái này


2

Hàm mã máy x86-64, 53 48 byte

thay đổi:

  • -2 jzqua ca thay vì sử dụng ca 64 bit để xử lý >>(32-0)trường hợp đặc biệt.
  • -3 trả về trong ZF thay vì AL, tiết kiệm 3 byte cho a setnz al.

(Xem thêm câu trả lời mã máy 32 bit của Daniel Schepler dựa trên điều này, sau đó đã phát triển để sử dụng một số ý tưởng khác mà chúng tôi có. Tôi bao gồm phiên bản mới nhất của tôi ở dưới cùng của câu trả lời này.)


Trả về ZF = 0 cho máy chủ không nằm trong mạng con, ZF = 1 cho mạng con, do đó bạn có thể phân nhánh trên kết quả vớije host_matches_subnet

Có thể gọi với quy ước gọi System V x86-64 như
bool not_in_subnet(int dummy_rdi, const char *input_rsi);thể bạn thêm vào setnz al.

Chuỗi đầu vào chứa cả máy chủ và mạng, được phân tách bằng chính xác 1 ký tự không có chữ số. Bộ nhớ theo sau chiều rộng CIDR phải chứa ít nhất 3 byte không có chữ số trước khi kết thúc trang. (Không nên là vấn đề trong hầu hết các trường hợp, như đối với cmdline arg.) Phiên bản 32 bit của Daniel không có giới hạn này.

Chúng tôi chạy cùng một vòng lặp parse-quad parse 3 lần, nhận hai địa chỉ IPv4 và lấy /masksố nguyên dưới dạng byte cao của một từ. (Đây là lý do tại sao phải có bộ nhớ có thể đọc được sau /mask, nhưng không thành vấn đề nếu có các chữ số ASCII.)

Chúng tôi làm (host ^ subnet) >> (32-mask)để thay đổi các bit máy chủ (những bit được phép không khớp), chỉ để lại sự khác biệt giữa mạng con và máy chủ. Để giải quyết /0trường hợp đặc biệt khi chúng ta cần thay đổi 32, chúng ta nhảy qua ca làm việc với số lượng = 0. ( neg clđặt ZF, mà chúng ta có thể phân nhánh để lại làm giá trị trả về nếu chúng ta không thay đổi.) Lưu ý rằng 32-mask mod 32 = -mask, và x86 vô hướng thay đổi số đếm của chúng bằng & 31hoặc & 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

(không cập nhật với phiên bản mới nhất) Hãy thử trực tuyến!

bao gồm một _startlệnh gọi nó argv[1]và trả về trạng thái thoát.

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

Nó hoạt động tốt nếu bạn vượt qua một dòng lệnh arg chứa một dòng mới thay vì khoảng trắng. Nhưng nó phải được thay thế , không phải là tốt.


Chức năng mã máy x86 32 bit, 38 byte

Thực hiện 9 số nguyên -> uint8_t phân tích cú pháp và "đẩy" chúng trên ngăn xếp, trong đó chúng tôi bật chúng ra dưới dạng từ khóa hoặc sử dụng cái cuối cùng vẫn còn trong CL. Tránh đọc qua cuối chuỗi.

Ngoài ra, decchỉ có 1 byte ở chế độ 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

Người gọi thử

   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

Tôi tò mò về việc số byte asm 32 bit sẽ diễn ra như thế nào thay vì số lượng cmp/jccbạn đã đề cập, bạn đã làm một cái gì đó giống như xor edx,edx;neg cl;cmovz eax,edx;shr eax,cl- hoặc có thể bạn đã có giá trị 0 treo ở đâu đó. (Và sau đó bạn sẽ không cần sub cl,32hướng dẫn.)
Daniel Schepler

1
Yup, có vẻ như edilà 0 khi vòng lặp thoát, vì vậy xor eax,edx;neg cl;cmovz eax,edi;shr eax,clsẽ hoạt động.
Daniel Schepler

1
Nếu tôi đếm đúng, cmove eax,edicó 3 byte là phần bị loại bỏ sub cl,32sau đó shr cl,eaxlưu một byte trên shr cl,raxvà 32 bit sẽ dec edilưu một byte trên 64 bit dec edi. Tập hợp của tôi sau đó đưa ra .byte 0x33(theo cú pháp GNU binutils) = 51 cho in_subnet.size.
Daniel Schepler

Ý tưởng hay, cảm ơn. (Theo cú pháp của Intel shr eax,cl, so với shr %cl, %eaxcú pháp AT & T, nhận xét cuối cùng của bạn đã đảo ngược điều đó.) Đó là một chút việc để cập nhật câu trả lời mã máy (và chuyển _startngười gọi và mô tả lại quy ước gọi cho chế độ 32 bit .. .), vì vậy tôi có thể không nhận được nó. Cảm thấy lười biếng ngày hôm nay. >. <
Peter Cordes

1
Tôi vừa thử thực hiện nhận xét mà bạn đưa ra câu trả lời của tôi về việc loại bỏ vòng lặp kép và thay vào đó lưu trữ vào các biến ngăn xếp - và thậm chí với mã bổ sung để khởi tạo con trỏ ghi vào edi, viết đầu ra, v.v ... cuối cùng nó đã tiết kiệm được 2 byte trong lưới. (Ít nhất một lần tôi nhận ra push ecx;push ecx;push ecxlà ngắn hơn sub esp,12; và dường như đó là một sự tẩy rửa cho dù tôi đã edisử dụng trước và sử dụng std;stosb;cldhay liệu tôi chỉ lưu trữ bằng cách sử dụng dec edi;mov [edi],al.
Daniel Schepler

1

Thạch , 23 byte

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

Hãy thử trực tuyến!

Liên kết đơn có một địa chỉ và mạng con được phân tách bằng dấu gạch chéo và trả về 1 là true và 0 cho false.

Cảm ơn @gwaugh đã chỉ ra một lỗ hổng trong bản gốc - không thể đảm bảo danh sách nhị phân dài 32.



1

05AB1E , 21 byte

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

Lấy mạng con trước địa chỉ.

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

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

một chức năng - Tôi đã dán ".32" cho thuật ngữ đầu tiên

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

và chỉ để cho vui:

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

đó là 56 byte


1

PHP ,75 73, 71 byte

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

Một nhánh của câu trả lời @Luis felipe De jesus Munoz , như một độc lập lấy đầu vào từ dòng lệnh args. Đầu ra '1'cho Truthy, ''(chuỗi trống) cho 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

Hãy thử trực tuyến!

-2 byte vay @Christoph chút lừa 's cho strtok(). Câu trả lời của anh vẫn còn ngắn hơn!


1

chức năng lắp ráp x86, 49 43 byte

Điều này chủ yếu được đăng để đáp ứng yêu cầu của Peter Cordes cho phiên bản sửa đổi mà tôi đã tạo. Nó có thể biến mất một lần / nếu anh ta kết hợp nó vào câu trả lời của mình.

Hàm này dự kiến esitrỏ đến một chuỗi đầu vào, với các phần địa chỉ và mạng con được phân tách bằng dấu cách hoặc ký tự dòng mới và giá trị trả về nằm trong cờ ZF (theo định nghĩa chỉ có hai giá trị có thể).

 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

Và phần bao bọc 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 do đề xuất từ ​​Peter Cordes trả về giá trị trong ZF.


Tôi đoán tôi có thể lưu một byte bằng cách loại bỏ cái cuối cùng xor edx,edxvà thay thế cmovz eax,edxbằng jz .nonzero; xor eax,eax; .nonzero:. cmovzvẫn thắng nếu chúng ta có hội nghị gọi ebx=0.
Daniel Schepler

Chúng ta có thể chỉ jzqua shrsetz hoặc ret không? Chúng tôi có thể trao đổi setnzđến setzvà trả lại 1cho một trận đấu nếu điều đó có ích. Hoặc thậm chí nói rằng giá trị trả lại của chúng tôi ZF. Tôi nên làm điều đó trong câu trả lời của tôi. (Nhưng tôi không nghĩ rằng chúng ta có thể biện minh cho yêu cầu người gọi để tạo ra hằng cho chúng ta, giống như ebx=0câu trả lời của tôi trên. Lời khuyên cho việc chơi golf trong x86 / x64 mã máy cho rằng sẽ được kéo dài gọi ước quá xa một tùy chỉnh.
Peter Cordes

BTW, tôi sử dụng cutđể xóa một số cột khỏi đầu ra danh sách NASM vì tất cả các hướng dẫn của tôi đều ngắn : nasm -felf foo.asm -l/dev/stdout | cut -b -34,$((34+6))-. Ngoài ra, tôi đã sử dụng Mov thay vì Movzx trong trình _startgọi của mình vì trạng thái thoát xuất phát từ byte thấp của arg tới sys_exit(). Nhân bỏ qua các byte cao hơn.
Peter Cordes

Tôi đoán điều đó sẽ làm việc. Đó là mất việc đếm ngược đến 43 byte và sau đó tôi chèn setnz alsau call in_subnettrong wrapper.
Daniel Schepler

Vâng Dễ hình dung trường hợp sử dụng thông thường cho chức năng này sẽ là call/ je, thay vì in hoặc chuyển tiếp theo kết quả. Giống như tôi đã chỉ ra trong "mẹo", một số quy ước gọi cuộc gọi hệ thống đã thực hiện điều này trong cuộc sống thực (thường là với CF = lỗi).
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;}

Đầu ra truecho sự thật và giả false.

Lưu ý: Điều này sử dụng longthay vì intcho sự thay đổi bên phải tiềm năng là 32.

Hãy thử trực tuyến!

Đã lưu 1 byte nhờ vào trần nhà

Đã lưu 10 byte nhờ Peter Cordes


Điều này không tạo ra "giá trị riêng biệt và nhất quán" cho falsey.
admBorkBork

Tôi lập luận rằng nó rõ ràng và nhất quán khác không nhưng nếu đó không phải là tinh thần của thử thách, tôi có thể thay đổi nó.
Chọc

Một 64-bit hỗ trợ số nguyên trái thay đổi bởi 32. Ngoài ra, bạn có thể ngay chuyển host ^ netđể chuyển ra các bit bạn muốn loại bỏ, thay vì thực sự tạo ra một mặt nạ. Nhưng tôi đoán Java cần một so sánh trong đó để tạo ra một boolean từ một số nguyên. Có thể là !vì nó không quan trọng bạn sản xuất đúng hay sai cho sản phẩm đầu ra nào. (Tôi đã hỏi OP để làm rõ về việc họ có ý định loại trừ 0 / khác không hay không và họ nói có, họ nhận thức được hậu quả của từ ngữ đó:
Peter Cordes

1
@PeterCordes Chuyển đổi mọi thứ để longlàm tôi mất một số byte nhưng tôi bù lại bằng cách có thể xóa ternary và thực hiện XOR như bạn đề xuất. Tôi đang kiểm tra những gì khác tôi có thể chơi golf trước khi đăng
Chọc

1

Than , 36 byte

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

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Lấy mạng con làm tham số đầu tiên và -chỉ xuất ra nếu địa chỉ nằm trong mạng con. Giải trình:

≔⪪S/θ

Tách mạng con trên /.

≔I⊟θζ

Tháo mặt nạ và đúc nó thành số nguyên.

⊞θS

Đẩy địa chỉ vào mảng.

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

Tách cả hai địa chỉ trên ., chuyển đổi chúng thành số nguyên, diễn giải thành cơ sở 256 và loại bỏ các bit bị che.

⁼⊟θ⊟θ

So sánh hai giá trị.


1

Japt , 26 byte

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

Thử nó

-3 byte nhờ @Shaggy!

Đầu vào là một mảng có 2 phần tử [address, subnet]. Transpiled JS bên dưới:

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


Thú vị - Tôi không nhận ra bạn có thể ép buộc một chuỗi với một số ++.
dana

Yup, giống như bạn có thể trong JS. Mặc dù vậy, nó không có tác dụng nếu bạn cần sử dụng lại giá trị ban đầu sau đó, nhưng đôi khi nó rất tiện dụng.
Xù xì

Sự cần thiết của dấu phẩy trong gphương thức làm tôi khó chịu; không thể tìm ra một cách xung quanh nó cả. Ít nhất không phải là một cái sẽ giúp bạn tiết kiệm một byte.
Xù xì


0

C # (Trình biên dịch tương tác 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

Hãy thử trực tuyến!

Câu lệnh LINQ lấy mảng chuỗi 2 phần tử làm đầu vào ở [address, subnet]định dạng.

Mỗi tứ giác chấm được chuyển đổi thành 32 bit dài bằng cách sử dụng thao tác bit. Các bit được dịch chuyển đúng bởi kích thước mạng con và các phần tử được so sánh cho bằng nhau.

Có một vài câu trả lời C # tại thời điểm câu trả lời này được đăng, nhưng không có câu trả lời nào sử dụng thao tác bit thuần túy.

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.