我在你的子网中,打高尔夫的代码


17

挑战

给定点address分四进制表示形式的IPv4 subnetCIDR表示形式的IPv4 ,请确定中是否address存在subnet。如果位于中subnet,则输出一个唯一且一致的值;如果不在中,则输出一个单独的唯一且一致的值subnet。输出值不一定需要使用您的语言为真/假。

CIDR子网符号简要入门

IPv4网络地址的长度为32位,分为四组,每组8位,以便于阅读。CIDR子网表示法是从最左边开始的指定位数的掩码。例如,对于/24子网,这意味着该子网中地址的最右边8位可用。因此,两个地址之间最多相隔一个255,并且具有相同的子网掩码,它们位于同一子网中。请注意,有效CIDR的所有主机位(右侧)均未设置(零)。

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

再举一个例子,/32子网指定所有位都是子网掩码,从本质上讲意味着每个子网仅允许一个主机/32

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

例子:

使用True“子网”和False“未子网”的输出:

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

规则和说明

  • 由于输入解析不是此挑战的重点,因此可以确保获得有效的IPv4地址和子网掩码。
  • 输入和输出可以通过任何方便的方法给出。
  • 您可以将结果打印到STDOUT或将其作为函数结果返回。请在您的提交中说明输出可以采用的值。
  • 完整的程序或功能都是可以接受的。
  • 禁止出现标准漏洞
  • 这是因此所有常见的高​​尔夫规则都适用,并且最短的代码(以字节为单位)获胜。

我们是否必须采用与测试用例相同的格式输入?
无知的体现,

1
@EmbodimentofIgnorance您不必像示例中那样将它们视为一行,但是您确实需要像示例中那样将它们作为点分四进制和点分子网。(例如,请参阅Arnauld的JavaScript答案)
AdmBorkBork,

可以用斜线将它们分隔开10.0.0.1/10.0.0.0”/16吗?
肯尼迪

1
@Poke我同意您是正确的,因为CIDR表示法描述了IP地址和子网大小。如中所示,1.255.1.1/8是一个有效的CIDR 表达式,用子网掩码表示1.255.1.1网络中的主机。但是,挑战要求使用CIDR表示法特别要求网络和子网,这不是有效的网络号和子网组合。1.0.0.0255.0.0.01.255.1.1/8
640KB

1
现在,我们还需要此挑战的IPv6版本
-Ferrybig,

Answers:


13

Python 3(62字节)

非常简单:

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

9
不错,但是python是否也具有内置的识别山羊的功能
本杰明·厄克特

3
当然,Mathematica内置了所有功能,甚至包括系外行星!没有什么比这更胜一筹
27

我想知道一个ip_adress对象和一个ip_network对象是否构成any convenient method,可能使Python获胜,除非基于python的高尔夫语言将其作为类型?
我的代词是monicareinstate,

在普通的Python中,您不会在20字节的范围内获得它。只有import和lambda已经比Stax答案更长。高尔夫语言
胜于

@someone:我用53字节的x86-64机器代码击败了Python 。:)不是传统的高尔夫语言,大多数代码大小都是手动解析string-> int。 (host^net)>>(32-mask)只有10个字节。但是对于不涉及列表列表或将函数映射到列表的任务来说,这只是中间的一半,因为许多标量运算可以使用2或3字节指令完成,并且循环可以围绕几个字节进行。
彼得·科德斯,

4

C#(Visual C#编译器),250 + 31 = 281字节

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

字节数包括 using System;using System.Linq;

在线尝试!

挑战发布后,我就用JS编写了此代码,但是Arnauld用更好的答案击败了我,所以这里是C#。

肯定有很多打高尔夫球的空间。

说明:

该函数由一个子函数组成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;
    }
);

此子功能将IP地址分割为.,将每个数字转换为二进制字符串,将每个字符串左移0为8位长,然后将字符串连接为一个32位二进制字符串。

立即使用a=h(a);给定的IP地址就地完成此操作。
然后,我们使用以下命令将子网掩码分为IP地址和掩码编号:c=b.Split('/');

IP地址组件也通过我们的子功能传递:b=h(c[0]);掩码号被解析为整数:var d=int.Parse(c[1]);

最后,我们将d两个二进制字符串的第一位(d掩码编号在此处)进行比较:return a.Substring(0,d)==b.Substring(0,d);


1
太累了,无法解决
过期数据

1
其实也忘记了PadLeft,也可以在线尝试!
过期的数据

很多优化。很高兴地通知您,您rPad是字符串的内置对象。pastebin链接到太长的TIO链接
我的代名词是monicareinstate

2
@someone小型仅供参考:与大多数其他网站不同,此SE中的注释中允许使用URL缩短程序,例如tinyurl.com。:)
凯文·克鲁伊森

1
188 - tinyurl.com/y6xfkbxt -漂亮的网址缩短提示@KevinCruijssen
达纳

4

Linux POSIX Shell(带有net-tools / iputils)(34个字节不终止,47个字节终止)

什么比网络实用程序本身最适合解析网络掩码和地址?:)

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

警告:该脚本可能会损害您的Internet连接,请谨慎运行。

输入:脚本将经过测试的IP地址作为第一个参数,并将经过测试的子网。作为第二个论点。

输出:如果脚本的第一个参数属于第二个参数指示的子网,则该脚本返回真实值(0)。否则,它将永远不会终止。

假设:脚本必须在干净的环境中以root用户身份运行(,管理员未设置其他黑洞路由,并且如果脚本的先前实例已运行,则其创建的黑洞路由也将被删除)。该脚本还假定“ Internet连接正常”(,存在有效的默认路由)。


说明:

我们创建到指定子网的黑洞路由。然后,我们使用ping测试与提供的IP地址的连接性。如果该地址不属于该子网(并且由于我们假设互联网连接设置正确),则ping将尝试将数据包发送到该地址。请注意,此地址是否实际响应并不重要,因为ping会一直尝试下去。相反,如果该地址确实属于该子网,则ping操作将失败并返回ENETUNREACH并返回2,并且由于我们否定了该命令,因此脚本将成功。


测试5.5.5.5是否属于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...]

sudo ip route del 8.8.8.0/24运行命令后用清理)。

测试5.5.5.5是否属于5.5.5.0/24:

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

sudo ip route del 5.5.5.0/24运行命令后用清理)。

测试8.8.8.8是否属于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...]

sudo ip route del 5.5.5.0/24运行命令后用清理)。


如果不允许非终止脚本,则为47字节版本

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

根据@Grimy的评论,这是始终终止的版本,如果地址在子网中,则返回0(真),否则返回1(伪)。我们用标记将ping终止,该-c1标记将发送的数据包的数量限制为1。如果地址响应,则ping将返回0,否则,ping将返回1。仅当地址属于黑洞子网时,ping才会返回2。因此,这就是我们在最后一条命令中要测试的内容。


3
虽然很聪明,但是如果地址不在子网中,则不能满足输出唯一且一致的值的要求(永远运行不会算作输出,也请参见this)。
Grimmy

1
@Grimy:但是它不会永远静默运行,因此仅适用第二个链接,而不适用第一个。同样,我认为ping如果SIGPIPE在将stdout + stderr通过管道传送到另一个程序中运行并且读者关闭管道的情况下会死掉。这是最可能的用例,因为退出状态可以通过两种方式都成功(如果我们-c1在ping中添加了一个选项来设置计数)var=$(/a.sh)。您需要一个决定后停下来的阅读器,而不是先阅读整个输出然后再看。
彼得·科德斯

@Grimy公平点(尽管出于争论的缘故,我可以说我们在这里有两个一致的值,因为ping在出现黑洞的情况下,终止时间少于一秒钟)。我添加了一个终止版本,额外增加了13个字节!:)
约安

3

JavaScript(ES6),82个字节

将输入作为(address)(subnet)。返回一个布尔值。

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

在线尝试!


3

PHP101 92 88字节

@gwaugh的-13个字节

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

在线尝试!


2
打高尔夫球有一些乐趣(Ty!):function($i,$r){return!((ip2long($i)^ip2long(strtok($r,'/')))>>32-strtok(_));}
Christoph

@Christoph非常好!我从没想过您可以在第二次致电中使用任何令牌strtok()。您的地址比下面我的类似答案短4个字节。道具!
640KB

@Christoph您应该将解决方案作为单独的答案发布,因为它比我的要好。
路易斯·费利佩·德·耶稣·穆诺兹

3

PowerPC / PPC64 C, 116 114字节

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

(在x86_64 Ubuntu 18.04上使用powerpc64-linux-gnu-gcc -static和qemu-user测试。)

程序在标准输入上使用两行,如果地址匹配,则返回1,否则返回0作为退出代码。(因此,这确实取决于规范,不需要匹配的真实值和不匹配的虚假值。)请注意,如果以交互方式运行,则需要^D在输入第二行后发出EOF()信号三遍。

这依赖于PowerPC是big-endian,并且还依赖于该平台返回0以将32位无符号值右移32。它将八位位组一个字节地读取为无符号值,以及另一个字节中的网络掩码长度。 ; 然后将两个无符号的32位地址进行异或运算,然后移出不相关的位。最后,它适用!于满足仅返回两个不同值的要求。

注意:可以替换u+3p并要求使用来删除两个字节-O0。不过,那比我所关心的要危险得多。

感谢Peter Cordes提供此解决方案的灵感。


更便携的C 186 171 167字节

在这里,我将保留一个运行167字节的更可移植的版本。

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

该程序在标准输入上使用两行,如果地址在子网中,则返回退出代码1,否则返回0。(因此,这确实依赖于规范,不需要匹配项为真值,不匹配项为假值。)

核心表达的细分:

  • a^eb^fc^gd^h计算地址的XOR和掩模逐字节。
  • (((a^e)<<8|b^f)<<8|c^g)<<8|d^h 然后通过类似Horner的方法将它们合并为一个无符号的32位值。
  • ...>>32-n然后移去与子网掩码无关的异或位(请记住,-C中的优先级比更高<<
  • 但是有一个陷阱:如果n = 0,~0U<<32则将给出未定义的行为,假设unsigned为32位(实际上在所有当前平台上都为32位),它将。另一方面,如果n = 0,则任何地址都将匹配,因此n&&...将给出正确的结果(利用的短路行为&&)。
  • 最后,为了满足输出只能是两个值之一的要求,我们应用 !输出0或1输出。

-15个字节,原因是ceilingcat和AdmBorkBork的评论

-4个字节,由Peter Cordes发表


1
使用退出代码返回值是默认的I / O方法之一,因此是允许的。
AdmBorkBork,

@ceilingcat当然,我多么想念这一点真是愚蠢。
丹尼尔·谢普勒

@AdmBorkBork好,谢谢,我将其更改为使用退出代码。
丹尼尔·谢普勒

想法:以小尾数或大尾数的C实现为目标(代码高尔夫球不需要可移植的代码),然后将输出指针键入pun的字节unsigned。例如使用char*p=&athen p++,p++,p++,...p--,...作为scanf args。格式字符串将是必需的"%hhu.%hhu...",因此在额外的大小与声明较少的vars和能够执行操作之间是一个重大的权衡(a^b)>>(32-count)
Peter Cordes,

1
@PeterCordes是的,右移可以工作,谢谢。
丹尼尔·谢普勒

2

Stax,22 个字节

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

运行并调试

它采用标准输入上以空格分隔的输入参数。

拆开包装,松开包装并进行评论,看起来像这样。

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

运行这个


2

x86-64机器码功能,53 48字节

更新日志:

  • jz移位时为-2 ,而不是使用64位移位来处理>>(32-0)特殊情况。
  • -3以ZF而不是AL返回,为节省了3个字节setnz al

(另请参见Daniel Schepler在此基础上的32位机器代码答案,然后演变为使用我们已有的其他一些想法。我在该答案的底部包括了该问题的最新版本。)


对于不在子网中的主机,返回ZF = 0;对于子网中的主机,返回ZF = 1;因此,您可以使用je host_matches_subnet

可以使用x86-64 System V调用约定进行调用,
bool not_in_subnet(int dummy_rdi, const char *input_rsi);就像添加一样setnz al

输入字符串包含主机和网络,并由1个非数字字符分隔。CIDR宽度结尾之后的内存必须在页面结​​尾之前至少包含3个非数字字节。(在大多数情况下,这不是问题,例如cmdline参数。)Daniel的32位版本没有此限制。

我们运行相同的点分四进制解析循环3次,获取两个IPv4地址,并/mask在dword的高字节中将其作为整数获取。(这就是为什么在后面必须有可读存储器的原因/mask,但是是否有ASCII数字并不重要。)

我们确实(host ^ subnet) >> (32-mask)移出了主机位(允许不匹配的位),仅保留了子网和主机之间的差异。为了解决/0特殊情况,我们需要移位32,我们跳过count = 0的移位。(neg cl设置ZF,我们可以在其上分支在不移位的情况下保留为返回值。)请注意32-mask mod 32 = -mask,和x86标量移位会将其计数掩盖为& 31& 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

(未更新为最新版本) 在线尝试!

包括_start调用它argv[1]并返回退出状态的。

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

如果您传递的命令行参数arg包含换行符而不是空格,则可以正常工作。但这必须是,不是。


x86 32位机器代码功能,38字节

执行9个整数-> uint8_t解析并将它们“推送”到堆栈中,在这里我们将它们作为dword弹出或使用仍在CL中的最后一个。完全避免读取超过字符串末尾的内容。

同样,dec在32位模式下只有1个字节。

    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

测试来电者

   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

我很好奇,如果不是cmp/jcc像您提到的那样执行32位asm字节计数,xor edx,edx;neg cl;cmovz eax,edx;shr eax,cl或者您已经有0值挂在某个地方。(然后您就不需要该sub cl,32指令了。)
Daniel Schepler

1
是的,看起来edi在循环退出时应该为0,所以xor eax,edx;neg cl;cmovz eax,edi;shr eax,cl应该可以工作。
丹尼尔·谢普勒

1
如果我没看错的话,cmove eax,edi有3个字节是被删除的字节,sub cl,32然后shr cl,eax保存一个字节,shr cl,rax而32位dec edi保存一个字节,超过64位dec edi。然后,我的程序集.byte 0x33以GNU binutils语法给出= 51 in_subnet.size
丹尼尔·谢普勒

好主意,谢谢。(在Intel语法中shr eax,cl,与shr %cl, %eaxAT&T语法相比,您的最后一条评论则是相反的。)更新机器代码答案(并移植_start调用方并重新描述32位模式的调用约定)有点麻烦。 。),因此我可能无法解决。今天觉得很懒。>。<
彼得·科德斯

1
我只是尝试实现您在回答中提出的关于摆脱双循环并存储到堆栈变量中的注释-即使使用额外的代码来初始化写入指针edi,写入输出等,最终也节省了2个字节在网。(至少一次我意识到push ecx;push ecx;push ecx比短sub esp,12;并且它似乎是一个洗涤我是否预先递减edi和使用std;stosb;cld或是否我只是使用存储dec edi;mov [edi],al
丹尼尔Schepler

1

果冻,23个字节

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

在线尝试!

Monadic链接,其地址和子网之间用斜杠分隔,并为true表示1,为false表示0。

感谢@gwaugh指出了原始文件中的一个缺陷-它无法确保二进制列表的长度为32。



1

05AB1E,21 字节

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

在地址之前获取子网。

在线尝试验证所有测试用例

说明:

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

一个功能-我在第一学期粘贴了“ .32”

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

只是为了好玩:

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

56字节


1

的PHP75 73,71字节

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

@Luis felipe De jesus Munoz的答案的一个分支,作为独立的从命令行参数中获取输入。输出'1'为Truthy, ''(空字符串)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

在线尝试!

-2个字节借用@Christoph的技巧strtok()。他的答案还短一些!


1

x86汇编功能, 49 43字节

这主要是为了满足Peter Cordes对我创建的修订版的要求而发布的。如果他将其纳入自己的答案中,它可能会消失一次。

该函数期望esi指向一个输入字符串,地址和子网部分用空格或换行符分隔,返回值在ZF标志中(根据定义,它只有两个可能的值)。

 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

和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

由于彼得·科德斯(Peter Cordes)的建议,返回-6字节的ZF值。


我想我可以通过删除最后一个字节xor edx,edx并替换cmovz eax,edx为来节省一个字节jz .nonzero; xor eax,eax; .nonzero:cmovz如果我们有通话约定的话,还是赢ebx=0
丹尼尔·谢普勒

我们可以jz超越shr塞茨或雷特吗?如果有帮助,我们可以将交换setnzsetz并返回1匹配项。甚至可以说,我们的返回值 ZF。我应该在回答中做到这一点。(但我不认为我们可以有理由要求主叫方为我们创造的常量,像ebx=0我上的答案。提示为在x86 / x64机器代码高尔夫球认为,将拉伸的自定义调用约定太远。
彼得·科德斯

顺便说一句,cut由于我的所有说明都很简短,因此我经常从NASM清单输出中删除一些列: nasm -felf foo.asm -l/dev/stdout | cut -b -34,$((34+6))-。另外,_start由于退出状态来自arg的低字节,因此我在调用方中使用了mov而不是movzx sys_exit()。内核会忽略较高的字节。
彼得·科德斯,

我想那行得通。这需要计数下降到43个字节,然后我插入setnz alcall in_subnet的包装。
丹尼尔·谢普勒

对。不难想象,此函数的正常用例是call/ je,而不是打印或进一步传递结果。就像我在“技巧”中指出的那样,一些系统调用调用约定已经在现实生活中做到了这一点(通常在CF = error的情况下)。
彼得·科德斯

1

Java 215211207202200199198190180180字节

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

true真实和输出false为假。

注意:这long代替int可能的右移32。

在线尝试!

多亏了ceilingcat,节省了1个字节

感谢Peter Cordes,节省了10个字节


这不会为错误输出“不同且一致的值”。
AdmBorkBork,

我认为它明显且始终非零,但是如果这不是挑战的精神,我可以进行更改。

一个64位的整数支撑左移位通过32此外,还可以向右移位host ^ net移出要删除的比特,而不是实际创建的掩模。但是我想Java需要在那里进行比较才能从整数创建布尔值。也许是!,因为对于哪个输出产生的是真还是假都没有关系。(我要求OP澄清他们是否打算排除0 /非零,以及他们说是的,他们知道该措辞的后果:
Peter Cordes

1
@PeterCordes将所有内容都转换为long确实会丢失一些字节,但是我可以通过删除三进制并按照您的建议进行XOR来弥补这一点。发布之前,我正在检查还能打些什么

1

木炭,36字节

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

在线尝试!链接是详细版本的代码。将子网作为第一个参数,并-仅在地址位于子网内时输出。说明:

≔⪪S/θ

在上分割子网/

≔I⊟θζ

取下面具,将其转换为整数。

⊞θS

将地址推送到阵列。

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

拆分两个地址 .将,将它们转换为整数,解释为基数256,并丢弃掩码的位。

⁼⊟θ⊟θ

比较两个值。


1

Japt,26个字节

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

尝试一下

-3个字节,感谢@Shaggy!

输入是一个包含2个元素的数组[address, subnet]。以下是转译的JS:

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

是的,就像在JS中一样。但是,如果以后需要重新使用原始值,则没有用,但是有时很方便。
毛茸茸的

g方法中对逗号的需要让我很烦;根本找不到解决方法。至少不会节省一个字节。
毛茸茸的


0

C#(Visual C#交互式编译器),134字节

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

在线尝试!

LINQ语句以2元素的字符串数组作为输入 [address, subnet]格式。

使用点操作将每个点分四边形转换为32位长的数字。这些位右移子网大小,并比较元素是否相等。

发布此答案时有几个C#答案,但没有一个使用纯位操作。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.