Подтема 5 из 6
Адреса с условием на двоичную запись
Как считать адреса с условием на двоичную запись: число единиц, чётность, часть адреса.
Фиксированные биты
Сколько адресов сети задачи темы содержат в двоичной записи ровно 12 единиц?
Сетевые биты одинаковы у всех адресов сети: их единицы считают один раз, а меняются только свободные биты. В сетевой части нашей сети 172 = 10101100 — 4 единицы, 20 = 00010100 — 2, сетевые биты третьего октета 010011 — 3. Всего 9 единиц у каждого адреса.
Значит, для 12 единиц в десяти свободных битах нужно ровно 3 единицы. Посчитать такие адреса проще всего перебором сети: цикл for address in net выдаёт все её адреса по порядку, включая оба края, а count('1') () считает единицы:
from ipaddress import ip_networknet = ip_network('172.20.77.140/22', strict=False)count = 0for address in net: if f'{address:b}'.count('1') == 12: count += 1print(count)Число 120 — это число способов выбрать 3 позиции из 10; как его посчитать без перебора, разбирает дополнительный урок. Важно: 22 сетевых бита не значат 22 единицы — среди фиксированных битов есть и нули.
Чётность и кратность
Если считают только адреса компьютеров, каждый из двух специальных адресов проверяют по условию — вычитать два автоматически нельзя. В нашей сети адрес сети содержит 9 единиц — число, кратное 3, а широковещательный — 9 + 10 = 19, не кратное. Адресов с числом единиц, кратным 3, всего 341; среди адресов компьютеров — на один меньше, а не на два. Перебор только адресов компьютеров даёт net.hosts():
from ipaddress import ip_networknet = ip_network('172.20.77.140/22', strict=False)every = [a for a in net if f'{a:b}'.count('1') % 3 == 0]hosts = [a for a in net.hosts() if f'{a:b}'.count('1') % 3 == 0]print(len(every), len(hosts))print(f'{net.network_address:b}'.count('1'))Кратность проверяют остатком (): «кратно 3» — % 3 == 0, «чётно» — % 2 == 0. Для чётности есть короткое рассуждение: при хотя бы одном свободном бите ровно половина адресов имеет чётное число единиц — в нашей сети 512 из 1024.
Обоснование · необязательноПочему ровно половина
Разобьём варианты свободных битов на пары, отличающиеся только последним битом: в паре число единиц k и k + 1, одно чётное, другое нет. На маленькой сети с четырьмя свободными битами и семью единицами в сетевой части:
Не путай чётность адреса и чётность числа единиц: 3 = 11₂ — число нечётное, а единиц в нём две.
Часть адреса
Условие на часть адреса проверяют на части строки из 32 битов — срезе. bits[:16] — первые два октета, bits[16:] — последние два, bits[16:24] — третий октет. Выбери условие, чтобы увидеть проверку:
- ровно 12 единиц
bits.count('1') == 12- число единиц кратно 3
bits.count('1') % 3 == 0- нулей больше, чем единиц
bits.count('0') > bits.count('1')- две последние цифры 11
bits[-2:] == '11'- в третьем октете единиц столько же, сколько нулей
bits[16:24].count('1') == bits[16:24].count('0')
Например, в скольких адресах нашей сети в первых двух октетах единиц больше, чем в последних двух?
from ipaddress import ip_networknet = ip_network('172.20.77.140/22', strict=False)count = 0for address in net: bits = f'{address:b}' if bits[:16].count('1') > bits[16:].count('1'): count += 1print(count)Проверка рассуждением: слева у всех 6 единиц, справа 3 фиксированные плюс s свободных. Нужно 3 + s < 6, то есть в десяти свободных битах не больше двух единиц: 1 + 10 + 45 = 56.
Наименьший и наибольший
Наименьший подходящий адрес — первый, который встретится при переборе по порядку: на нём цикл и останавливают. Наибольшее значение ищут перебором до конца, каждый раз запоминая лучшее. Найдём наименьший адрес компьютера нашей сети с 12 единицами:
from ipaddress import ip_network net = ip_network('172.20.76.0/22')for address in net.hosts(): if f'{address:b}'.count('1') == 12: breakprint(address)Наибольшая сумма октетов среди таких адресов ищется до конца сети ():
from ipaddress import ip_networknet = ip_network('172.20.77.140/22', strict=False)best = 0for address in net.hosts(): if f'{address:b}'.count('1') == 12: octets = str(address).split('.') best = max(best, sum(int(x) for x in octets))print(best)Это 172.20.76.224, а не адрес из конца сети: у 79 в третьем октете уже 5 единиц, и на последний октет остаётся одна. Самый большой адрес и самая большая сумма октетов — разные вопросы.
Тонкости:размер перебора и неизвестная маска
Перебор сети /22 — 1024 адреса, /16 — 65 536, /12 — около миллиона: это ещё секунды. Сеть /8 — 16 миллионов адресов, её считают формулой (дополнительный урок).
Если маска не дана, сначала выбирают крайнюю допустимую маску (подтема 4). Наименьшее количество подходящих адресов — в самой маленькой сети (наибольшее p), наибольшее — в самой большой (наименьшее p): меньшая сеть целиком лежит внутри большей.
Итого
- Фиксированныеединицы сетевой части — у всех адресов одни
- Перебор
for address in net,f'{address:b}'.count('1') - Компьютеры
net.hosts(); края проверить, а не вычесть два - Часть адресасрезы bits[:16], bits[16:24]
- Крайний адреснаименьший — break, наибольший — max до конца
Проверьте себя
Ответь сначала сам, потом открой ответ.
ОтветСкрыть ответ
ОтветСкрыть ответ
ОтветСкрыть ответ
ОтветСкрыть ответ
bits из 32 битов адреса берёт срез bits[16:24]?ОтветСкрыть ответ
Практика
Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.
Ровно восемь единиц в /29
В сети 192.168.1.0/29 сколько адресов содержат ровно восемь единиц в полной двоичной записи?
Введите число.
Подсказка
Сначала сосчитай единицы сетевой части — они есть у каждого адреса.
Решение
Фиксированная часть: 192 — две единицы, 168 — три, 1 — одна, сетевые биты последнего октета нулевые — всего шесть. Свободных битов три, нужны две единицы: 011, 101, 110 — три адреса.
Решение программой
from ipaddress import ip_address, ip_network def ones(address): return bin(int(address)).count('1') net = ip_network('192.168.1.0/29')print(sum(1 for x in net if ones(x) == 8))Ответ: 3
Три единицы в /28
Сколько адресов сети 10.0.0.0/28 содержат ровно три единицы в двоичной записи?
Введите число.
Подсказка
Сколько единиц уже дают сетевые биты?
Решение
У 10 = 00001010 две единицы, остальные сетевые биты нулевые. В четырёх свободных битах нужна одна единица — четыре варианта её места.
Решение программой
from ipaddress import ip_address, ip_network def ones(address): return bin(int(address)).count('1') print(sum(1 for x in ip_network('10.0.0.0/28') if ones(x) == 3))Ответ: 4
Наибольшее число единиц у компьютера
Какое наибольшее количество единиц может быть в двоичной записи адреса компьютера сети 192.168.0.0/24?
Введите число.
Подсказка
Широковещательный адрес компьютеру не назначают.
Решение
Сетевая часть даёт 2 + 3 = 5 единиц, свободных битов 8. Все восемь единиц — у широковещательного адреса, он компьютеру не достаётся, поэтому наибольшее 5 + 8 − 1 = 12.
Решение программой
from ipaddress import ip_address, ip_network def ones(address): return bin(int(address)).count('1') net = ip_network('192.168.0.0/24')print(max(ones(x) for x in net.hosts()))Ответ: 12
Чётное число единиц у компьютеров
В сети 192.168.1.0/29 сколько адресов, которые можно назначить компьютерам, содержат чётное число единиц в двоичной записи?
Введите число.
Подсказка
Проверь каждый специальный адрес по условию, а не вычитай два.
Решение
В сетевой части шесть единиц. Чётное число всего — ноль или две единицы в трёх свободных битах: 1 + 3 = 4 адреса. Среди них адрес сети (шесть единиц) — его исключают; широковещательный (девять единиц) в четвёрку не входил. Остаётся 3.
Решение программой
from ipaddress import ip_address, ip_network net = ip_network('192.168.1.0/29')count = 0for address in net.hosts(): if f'{address:b}'.count('1') % 2 == 0: count += 1print(count)Ответ: 3
Количество единиц кратно 3
Сколько адресов сети 172.16.5.64/26 имеют количество единиц, кратное 3?
Введите число.
Подсказка
Сосчитай единицы сетевой части и реши, сколько нужно в свободных битах.
Решение
Фиксированная часть 172.16.5 и два сетевых бита 01 дают 4 + 1 + 2 + 1 = 8 единиц. Кратно 3 — 9 или 12 единиц всего, то есть 1 или 4 в шести свободных битах: 6 + 15 = 21.
Решение программой
from ipaddress import ip_address, ip_network def ones(address): return bin(int(address)).count('1') print(sum(1 for x in ip_network('172.16.5.64/26') if ones(x) % 3 == 0))Ответ: 21
Число единиц не кратно 3
Сеть задана IP-адресом 201.33.148.0 и маской сети 255.255.255.240. Сколько в этой сети IP-адресов, для которых количество единиц в двоичной записи не кратно 3? В ответе укажи только число.
Введите число.
Подсказка
Из 16 адресов посчитай те, где условие не выполняется.
Решение
Перебор 16 адресов сети: у пяти число единиц кратно 3, у остальных 11 — нет.
Решение программой
from ipaddress import ip_address, ip_network def ones(address): return bin(int(address)).count('1') print(sum(1 for x in ip_network('201.33.148.0/28') if ones(x) % 3 != 0))Ответ: 11
Третий байт: нулей столько же, сколько единиц
Сколько адресов сети 10.20.0.0/18 содержат в третьем байте одинаковое количество нулей и единиц?
Введите число.
Подсказка
Условие проверяют только на третьем байте — срезом.
Решение
При маске /18 третий байт — 00xxxxxx: два сетевых нуля и шесть свободных битов. Поровну нулей и единиц — четыре единицы в шести битах, 15 вариантов; четвёртый байт любой: 15 · 256 = 3840.
Решение программой
from ipaddress import ip_address, ip_network count = 0for x in ip_network('10.20.0.0/18'): third = f'{x.packed[2]:08b}' if third.count('1') == third.count('0'): count += 1print(count)Ответ: 3840
Наименьший адрес с кратным 4 числом единиц
Сеть задана IP-адресом одного из входящих в неё узлов 180.45.101.7 и сетевой маской 255.255.224.0. Найди наименьший IP-адрес этой сети, который может быть назначен компьютеру и содержит в двоичной записи кратное 4 количество единиц. В ответе укажи адрес без разделителей.
Введите адрес без точек.
Подсказка
Перебирай адреса компьютеров по порядку и остановись на первом подходящем.
Решение
Сеть 180.45.96.0/19. Перебираем адреса компьютеров по порядку: первый с числом единиц, кратным 4, — 180.45.96.3 (4 + 4 + 2 + 2 = 12 единиц). Без точек — 18045963.
Решение программой
from ipaddress import ip_address, ip_network def ones(address): return bin(int(address)).count('1') net = ip_network('180.45.101.7/255.255.224.0', strict=False)for x in net.hosts(): if ones(x) % 4 == 0: print(str(x).replace('.', '')) breakОтвет: 18045963
Наибольшая сумма октетов
Сеть задана IP-адресом 115.180.0.0 и сетевой маской 255.252.0.0. Определи наибольшую сумму октетов IP-адреса компьютера из этой сети, у которого количество единиц и количество нулей в двоичной записи одинаково.
Введите число.
Подсказка
Наибольшую сумму ищи перебором до конца сети, обновляя лучший результат.
Решение
Сеть 115.180.0.0/14: в сетевой части 9 единиц, в 18 свободных битах нужно ещё 7. Перебор адресов компьютеров с обновлением наибольшей суммы даёт 759 — например, у 115.180.240.224.
Решение программой
from ipaddress import ip_address, ip_network def ones(address): return bin(int(address)).count('1') best = 0for x in ip_network('115.180.0.0/14').hosts(): if ones(x) == 16: best = max(best, sum(x.packed))print(best)Ответ: 759
Наименьшее количество адресов с 15 единицами
Узлы с IP-адресами 52.118.40.17 и 52.118.45.200 принадлежат одной сети. Какое наименьшее количество IP-адресов, в двоичной записи которых ровно 15 единиц, может содержаться в этой сети?
Введите число.
Подсказка
Наименьшее количество — в самой маленькой допустимой сети.
Решение
Самая длинная общая маска — /21 (40 = 00101000, 45 = 00101101): в самой маленькой общей сети 52.118.40.0/21 меньше всего адресов. Ровно 15 единиц у 462 из них.
Решение программой
from ipaddress import ip_address, ip_network def net(node, p): return ip_network(f'{node}/{p}', strict=False) def ordinary(node, p): n = net(node, p) address = ip_address(node) return address not in (n.network_address, n.broadcast_address) a, b = '52.118.40.17', '52.118.45.200'same = [p for p in range(33) if net(a, p) == net(b, p)]def ones(address): return bin(int(address)).count('1') p = max(p for p in same if ordinary(a, p) and ordinary(b, p))print(sum(1 for x in net(a, p) if ones(x) == 15))Ответ: 462