Я в ваших подсетях, играю в гольф ваш код

17

Вызов

Учитывая IPv4 addressв нотации с точечным квадратом и IPv4 subnetв нотации CIDR , определите, есть ли 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 или вернуть его как результат функции. Пожалуйста, укажите в своем представлении, какие значения могут принимать результаты.
  • Либо полная программа или функция приемлемы.
  • Стандартные лазейки запрещены.
  • Это поэтому применяются все обычные правила игры в гольф, и выигрывает самый короткий код (в байтах).
AdmBorkBork
источник
Нужно ли вводить данные в том же формате, что и ваши тесты?
Воплощение Неведения
1
@EmbodimentofIgnorance Вам не нужно принимать их как один за строку, как в примерах, но вам нужно принимать их как пунктирную четверку и пунктирную подсеть, как в примерах. (например, см. ответ JavaScript от
Арнаулда
Можно ли, например, разделять их косой чертой 10.0.0.1/10.0.0.0”/16?
Ник Кеннеди
1
@Poke Я согласен, что вы правы в том, что нотация CIDR описывает IP-адрес и размер подсети. Например, 1.255.1.1/8допустимое выражение CIDR , представляющее хост 1.255.1.1в сети 1.0.0.0с маской подсети 255.0.0.0. Тем не менее, запрос запрашивает номер сети и подсети, в частности, в нотации CIDR, которая 1.255.1.1/8не является допустимой комбинацией номера сети и подсети.
640KB
1
Теперь нам также нужна версия этого вызова для IPv6
Ferrybig

Ответы:

13

Python 3 (62 байта)

Очень просто:

from ipaddress import*
lambda i,m:ip_address(i)in ip_network(m)
agtoever
источник
9
Хорошо, но есть ли в Python встроенная функция распознавания коз ?
Бенджамин Уркхарт
3
Конечно, у Mathematica есть встроенная программа для всего - даже для экзопланет ! Ничто не может победить это ... Но, как вы могли видеть, Python соответствует козловому
составу
Интересно, составляют ли ip_adressобъект и ip_networkобъект any convenient method, возможно, позволить Python победить, если только язык игры в гольф на основе Python не имеет их в качестве своих типов?
мое местоимение monicareinstate
Вы не получите его в диапазоне 20 байт в обычном Python. Только импорт и лямбда уже длиннее ответа Stax. Это не удивительно , что языки гольф выиграть от «нормальных» языков ... :-(
agtoever
@ Someone: я победил Python с 53 байтами машинного кода x86-64 . :) Не традиционный язык игры в гольф, и большая часть размера кода обрабатывает 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);};

Bytecount включает в себя using System;using System.Linq;

Попробуйте онлайн!

Я написал это в JS, как только задание было опубликовано, но Арно обошел меня с ударом с гораздо лучшим ответом, так что вместо этого он находится в 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);

Skidsdev
источник
1
Слишком устал, чтобы разобраться с этим, так что я просто сделал ваш гольф для вас
Просроченные данные
1
На самом деле забыл про PadLeft в этом тоже Попробуйте онлайн!
Просроченные данные
Много оптимизаций. Я рад сообщить вам, что вы rPadвстроены в строки. вставьте ссылку на ссылку
TIO,
2
@ Someone Small FYI: в отличие от большинства, в комментариях к этой SE разрешены сокращения URL-адресов, такие как tinyurl.com . :)
Кевин Круйссен
1
188 - tinyurl.com/y6xfkbxt - хорошие советы URL укорочение @KevinCruijssen
Dana
4

Оболочка Linux POSIX (с net-tools / iputils) (34 байта не завершаются, 47 байтов заканчиваются)

Что лучше всего подходит для разбора сетевых масок и адресов, чем сами сетевые утилиты? :)

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

Предупреждение: скрипт может повредить подключение к Интернету, пожалуйста, запустите его с осторожностью.

Входные данные: сценарий принимает в качестве первого аргумента проверенный IP-адрес и проверенную подсеть. в качестве второго аргумента.

Вывод: скрипт возвращает истинное значение (0), если первый аргумент скрипта принадлежит подсети, указанной во втором аргументе. Иначе оно никогда не прекратится.

Допущения: сценарий должен запускаться от имени пользователя root в чистой среде ( т. Е. Администратор не установил другой маршрут черной дыры, и если предыдущий экземпляр сценария был запущен, созданный им маршрут черной дыры был удален ). Сценарий также предполагает «работающее подключение к Интернету» ( т. Е. Присутствует действующий маршрут по умолчанию).


Объяснение:

Мы создаем маршрут черной дыры к указанной подсети. Затем мы проверяем подключение к указанному IP-адресу с помощью ping . Если адрес не принадлежит подсети (и поскольку мы предполагаем, что интернет-соединение установлено правильно), 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
Хотя это и умно, это не соответствует требованию для вывода отличного и непротиворечивого значения, если адрес не находится в подсети ( работа навсегда не считается выходом , см. Также это ).
Grimmy
1
@Grimy: Но он не работает бесшумно вечно, поэтому применима только ваша вторая ссылка, а не первая. Также я думаю, pingчто умрет от SIGPIPE, если он работает с stdout + stderr, переданным в другую программу, и ридер закрыл канал. И это наиболее вероятный вариант использования, потому что состояние выхода может быть успешным в любом случае (если мы добавили -c1опцию ping для установки счетчика). Но, конечно, чтение его вывода с помощью var=$(/a.sh)завершится неудачей; вам нужен читатель, который остановился после принятия решения, вместо того, чтобы прочитать весь вывод и затем посмотреть на него.
Питер Кордес
@ Справедливое замечание (хотя в качестве аргумента я мог бы сказать, что у нас здесь есть два последовательных значения, так как 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))

Попробуйте онлайн!

Arnauld
источник
3

PHP , 101 92 88 байт

-13 байтов от @gwaugh

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

Попробуйте онлайн!

Луис Фелипе Де Иисус Муньос
источник
2
function($i,$r){return!((ip2long($i)^ip2long(strtok($r,'/')))>>32-strtok(_));}
Кристоф
@ Кристоф очень милый! Мне никогда не приходило в голову, что вы можете просто использовать любой токен для второго звонка 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 является байтовым порядком байтов, а также на этой платформе, возвращающей 0 для сдвига вправо 32-битного значения без знака на 32. Он считывает октеты в значения без знака один за другим вместе с длиной маски маски в другом байте. ; затем он принимает xor двух беззнаковых 32-битных адресов и удаляет ненужные биты. Наконец, это относится !к требованию возврата только двух различных значений.

Примечание. Можно было бы сократить два байта, заменив их u+3на pи требуя компиляции с помощью -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^e, b^f, c^g, d^hВычисляет исключающий адрес и маску байт за байтом.
  • (((a^e)<<8|b^f)<<8|c^g)<<8|d^h затем объединяет их в одно 32-разрядное значение без знака методом Хорнера.
  • ...>>32-nзатем сдвигает биты разности xor, которые не имеют отношения к маске подсети (имея в виду, что -имеет более высокий приоритет в C, чем <<)
  • Однако есть одна ошибка: если n = 0, то ~0U<<32поведение будет неопределенным при условии, unsignedчто оно равно 32 битам (это практически на всех современных платформах). С другой стороны, если n = 0, то любой адрес будет совпадать, поэтому n&&...даст правильный результат (используя преимущества короткого замыкания &&).
  • Наконец, чтобы удовлетворить требованию, что выходные данные могут быть только одним из двух значений, мы применяем !к выходным данным 0 или 1.

-15 байт из-за комментариев потолочного кота и AdmBorkBork

-4 байта из-за комментария Питера Кордеса

Даниэль Шеплер
источник
1
Использование кодов выхода для возврата значений является одним из методов ввода-вывода по умолчанию и, таким образом, разрешено.
AdmBorkBork
@ceilingcat Конечно, как глупо с моей стороны пропустить это.
Даниэль Шеплер
@AdmBorkBork Хорошо, спасибо, я изменил его, чтобы использовать код выхода.
Даниэль Шеплер
Идея: нацелить реализацию C с прямым порядком байтов или с прямым порядком байтов (код-гольф не требует переносимого кода) и выводить указатели типа «каламбур» на байты объекта unsigned. например, с помощью char*p=&athen p++,p++,p++,...или p--,...as scanf. "%hhu.%hhu..."Хотя форматная строка должна быть такой, так что это значительный компромисс между этим дополнительным размером и объявлением меньшего числа переменных и возможностью сделать это(a^b)>>(32-count)
Питер Кордес
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 байт

Список изменений:

  • -2 jzза смену вместо использования 64-битного сдвига для обработки >>(32-0)особого случая.
  • -3 вернуть в ZF вместо AL, сохранив 3 байта для a setnz al.

(См. Также ответ 32-битного машинного кода Даниэля Шеплера, основанный на этом, который затем развился, чтобы использовать некоторые другие идеи, которые у нас были. Я включил мою последнюю версию этого в нижней части этого ответа.)


Возвращает ZF = 0 для хоста, не входящего в подсеть, ZF = 1 для подсети, поэтому вы можете перейти к результату с помощьюje host_matches_subnet

Может вызываться соглашением о вызовах System V в x86-64 как
bool not_in_subnet(int dummy_rdi, const char *input_rsi); будто вы добавляете setnz al.

Входная строка содержит хост и сеть, разделенные ровно 1 нецифровым символом. Память после конца ширины CIDR должна содержать как минимум 3 байта без цифр перед концом страницы. (В большинстве случаев не должно быть проблемой, например, для аргумента cmdline.) 32-разрядная версия Daniel не имеет этого ограничения.

Мы запускаем один и тот же цикл синтаксического разброса в точках 3 раза, получая два IPv4-адреса и получая /maskкак целое число в старшем байте слова. (Вот почему должна быть читаемая память после/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

Это работает нормально, если вы передаете аргумент командной строки, содержащий новую строку вместо пробела. Но это должно быть, а не так хорошо.


32-битная функция машинного кода x86, 38 байт

Выполните 9 целочисленных -> uint8_t синтаксических разборов и «вытолкните» их в стек, где мы вытолкнем их как dwords или используем последний, еще оставшийся в CL. Избегает чтения за концом строки вообще.

Кроме того, decтолько 32 байта в 32-битном режиме.

    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
Питер Кордес
источник
Мне любопытно, как будет работать счетчик 32-битных asm-байтов, если вместо того, cmp/jccчто вы упомянули, вы сделали что-то вроде xor edx,edx;neg cl;cmovz eax,edx;shr eax,cl- или, может быть, у вас уже есть значение 0, которое где-то висит. (И тогда вам не понадобится sub cl,32инструкция.)
Даниэль Шеплер
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, %eaxс синтаксисом AT & T, ваш последний комментарий полностью изменил это.) Это немного хлопотно, чтобы обновить ответы машинного кода (и перенести _startвызывающую программу и заново описать соглашение о вызовах для 32-битного режима.) ., так что я не могу обойтись. Чувствую себя ленивым сегодня. >. <
Питер Кордес
1
Я просто попытался реализовать комментарий, который вы добавили к моему ответу о том, как избавиться от двойного цикла и вместо этого сохранить в переменные стека - и даже с дополнительным кодом для инициализации указателя ediзаписи, записи вывода и т. Д. В итоге удалось сэкономить 2 байта в сети (По крайней мере, однажды я понял, что push ecx;push ecx;push ecxон короче sub esp,12; и, казалось, это была стирка, независимо от того, был ли я предварительно прокомментирован ediи использовался, std;stosb;cldили я просто хранил с помощью dec edi;mov [edi],al.
Даниэль Шеплер,
1

Желе , 23 байта

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

Попробуйте онлайн!

Монадическая ссылка, которая принимает адрес и подсеть, разделенные косой чертой, и возвращает 1 для true и 0 для false.

Спасибо @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

PHP ,75 7371 байт

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

Вилка из @Luis Филипе де Хесус Муньос ответа «s, как автономные принимает входные данные из командной строки арг. Выходы '1'для Истины, ''(пустая строка) для Фасли.

$ 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(). Хотя его ответ еще короче!

640 КБ
источник
1

функция сборки x86, 49 43 байта

Это главным образом отправлено, чтобы удовлетворить запрос Питера Кордеса о пересмотренной версии, которую я создал. Вероятно, он может исчезнуть один раз / если он включит его в свой ответ.

Предполагается, что эта функция 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

-6 байт из-за предложения Питера Кордеса вернуть значение в ZF.

Даниэль Шеплер
источник
Я думаю, я мог бы сохранить один байт, удалив последний xor edx,edxи заменив cmovz eax,edxна jz .nonzero; xor eax,eax; .nonzero:. cmovzвсе еще выигрывает, если у нас есть соглашение о вызовах ebx=0.
Даниэль Шеплер
Можем ли мы просто jzнадshr сетц или рет? Мы можем поменять местами , setnzчтобы setzи вернуться 1к матчу , если это помогает. Или даже сказать , что наше возвращаемое значение является ZF. Я должен был сделать это в своем ответе. (Но я не думаю, что мы можем оправдать требование вызывающей стороны создавать константы для нас, например ebx=0. Мой ответ на Советы по игре в гольф в машинном коде x86 / x64 утверждает, что это слишком сильно
растянет
Кстати, я использую cut , чтобы удалить некоторые столбцы из листинга вывода NASM , потому что все мои инструкции коротки: nasm -felf foo.asm -l/dev/stdout | cut -b -34,$((34+6))-. Кроме того, я использовал mov вместо movzx в моем _startзвонящем, потому что состояние выхода исходит из младшего байта аргумента to sys_exit(). Ядро игнорирует старшие байты.
Питер Кордес
Я думаю, это сработало бы. Это уменьшает счет до 43 байтов, а затем я вставляю setnz alпосле call in_subnetв обертку.
Даниэль Шеплер
Ага. Легко представить, что нормальным вариантом использования этой функции будет call/ je, а не печать или дальнейшая передача результата. Как я указал в «советах», некоторые соглашения о вызовах системных вызовов уже делают это в реальной жизни (обычно с CF = error).
Питер Кордес
1

Java 215 211 207 202 200 199 198 190 180 байтов

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.

Попробуйте онлайн!

Сохранено 1 байт благодаря floorcat

Сохранено 10 байтов благодаря Питеру Кордесу

совать
источник
Это не выводит «отчетливое и непротиворечивое значение» для Falsey.
AdmBorkBork
Я бы сказал, что это отчетливо и последовательно ненулевой, но если это не дух задачи, я могу изменить его.
Poke
64-разрядное целое число поддерживает сдвиг влево на 32. Также вы можете сдвиг вправо,host ^ net чтобы сместить биты, которые вы хотите удалить, вместо того, чтобы фактически создавать маску. Но я предполагаю, что Java нуждается в сравнении, чтобы создать логическое значение из целого числа. Может быть !, потому что не имеет значения, какое из истинных или ложных вы производите для какого выхода. (Я попросил у ОП уточнения относительно того, намеревались ли они исключить 0 / ненулевое значение, и они сказали « да», они знали о последствиях этой формулировки:
Питер Кордес
1
@PeterCordes Преобразование всего в longменя теряет несколько байтов, но я восполняю это тем, что могу удалить троицу и выполнить XOR, как вы предлагаете. Я проверяю что еще я могу гольф , прежде чем отправлять
Poke
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
источник
26 байт
Shaggy
Интересно - я не осознавал, что ты можешь привести строку к числу ++.
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, который принимает двухэлементный массив строк в качестве входных данных в [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
Dana
источник