首页 > 试题广场 >

识别有效的IP地址和掩码并进行分类统计

[编程题]识别有效的IP地址和掩码并进行分类统计
  • 热度指数:377434 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
\hspace{15pt}在本题中,我们需要处理地址信息,其由 IP 地址和子网掩码组成,这两者均形如 \texttt{,由四段数字组成(每一个 \texttt{`*'} 表示一个数字),每一段的数字均为 0255 之间的一个整数,每段数字之间以点分隔。

\hspace{15pt}我们定义五类 IP 地址:
\hspace{23pt}\bullet\,A 类:\texttt{
\hspace{23pt}\bullet\,B 类:\texttt{
\hspace{23pt}\bullet\,C 类:\texttt{
\hspace{23pt}\bullet\,D 类:\texttt{
\hspace{23pt}\bullet\,E 类:\texttt{
\hspace{15pt}我们定义私有 IP 地址:
\hspace{23pt}\bullet\,\texttt{
\hspace{23pt}\bullet\,\texttt{
\hspace{23pt}\bullet\,\texttt{

\hspace{15pt}我们定义合法的子网掩码为:将掩码的每一段数字依次转换为八位长度的二进制字符串并进行拼接,这个字符串必须由若干个连续的 1 后跟若干个连续的 0 组成,才视为子网掩码合法。例如,掩码 \texttt{ 转换拼接得到字符串 \texttt{11111111 11111110 11111111 00000000},显然不合法;掩码 \texttt{ 转换拼接得到字符串 \texttt{11111111 11111111 11111111 11111000},合法。注意,全为 1 或全为 0 的掩码也视为非法。
\hspace{15pt}我们定义错误的 IP 地址和错误的子网掩码为不符合上述定义的 IP 地址和子网掩码。例如,格式错误、数字超出范围等等。

\hspace{15pt}现在,你需要分类统计 A、B、C、D、E 类地址的数量、错误 IP 或错误子网掩码的数量、私有 IP 的数量。

\hspace{15pt}特别地:
\hspace{23pt}\bullet\,类似 \texttt{\texttt{ 的 IP 地址不计入任何类别,也不计入非法统计,直接跳过;
\hspace{23pt}\bullet\,一个 IP 既可计入私有 IP,也可计入五类地址之一,二者分别累计。

输入描述:
\hspace{15pt}本题将会给出 1 \leqq T \leqq 1000 条地址信息,确切数字未知,您需要一直读取至文件结尾;您也可以参考 牛客网在线判题系统使用帮助 获得更多的使用帮助。每条地址信息描述如下:
\hspace{15pt}每行输入一个 \texttt{ 形式的 IP 地址和一个 \texttt{ 形式的子网掩码,中间用波浪线(\sim)分隔。保证 \texttt{`*'} 要么为空,要么是一个 0255 间的整数。


输出描述:
\hspace{15pt}在一行上输出七个整数,分别代表 A 类地址数、B 类地址数、C 类地址数、D 类地址数、E 类地址数、错误 IP 或错误子网掩码数、私有 IP 数。
示例1

输入

10.70.44.68~1.1.1.5
1.0.0.1~255.0.0.0
192.168.0.2~255.255.255.0
19..0.~255.255.255.0

输出

1 0 1 0 0 2 1

说明

\hspace{15pt}在这个样例中: 
\hspace{23pt}\bullet\,第一条地址信息:掩码非法;
\hspace{23pt}\bullet\,第二条地址信息:IP 格式和掩码均合法,属于 A 类;
\hspace{23pt}\bullet\,第三条地址信息:IP 格式和掩码均合法,属于 C 类私有地址;
\hspace{23pt}\bullet\,第四条地址信息:IP 格式非法。
\hspace{15pt}统计得到 1 个 A 类,0 个 B 类,1 个 C 类,0 个 D 类,0 个 E 类,2 个错误条目,1 个私有地址。
示例2

输入

0.201.56.50~255.255.255.0
127.201.56.50~255.255.111.255

输出

0 0 0 0 0 0 0

说明

\hspace{15pt}在这个样例中,两条地址信息均属于上方提示中提到的特殊 IP 地址,不需要处理,直接跳过。特别需要注意地,第二条地址的子网掩码是非法的。但是因为该条为特殊 IP 地址,此优先级更高,所以不进入统计。

备注:
本题已于下方时间节点更新,请注意题解时效性:
1. 2025-05-30 更新题面。
2. 2024-12-16 更新题面。
import sys
import re


def check_ip(ip: str):
    address = ip.split('.')
    for ad in address:
        if len(ad) == 0:
            return False
    return True

def check_mask(mask: str):
    m = ''.join(f'{int(m):08b}' for m in mask.split('.'))
    if not re.match(r"^1+0+$", m):
        return False
    return True

def ip_to_ABCDE(ip: str):
    address = int(ip.split('.')[0])
    _range = {
        0: [1, 127],
        1: [128, 191],
        2: [192, 223],
        3: [224, 239],
        4: [240, 255]
    }
    for k, [a, b] in _range.items():
        if a <= address <= b:
            return k
    return

def is_private(ip: str):
    a, b = ip.split('.')[:2]
    a, b = int(a), int(b)
    _range = [
        [[10, 10], [0, 255]],
        [[172, 172], [16, 31]],
        [[192, 192], [168, 168]]
    ]
    for a_range, b_range in _range:
        if a_range[0] <= a <= a_range[1] and b_range[0] <= b <= b_range[1]:
            return True
    return False

def is_special_ip(ip: str):
    address = int(ip.split('.')[0])
    if address in [0, 127]:
        return True
    return False

ips, masks = [], []

for line in sys.stdin:
    l = line.strip('\n')
    if len(l) == 0:
        continue
    ip, mask = line.split('~')
    ips.append(ip)
    masks.append(mask)

oup = [0] * 7
for ip, mask in zip(ips, masks):
    if is_special_ip(ip):
        continue
    if check_ip(ip) and check_mask(mask):
        if is_private(ip):
            oup[-1] += 1
        oup[ip_to_ABCDE(ip)] += 1
    else:
        oup[-2] += 1

print(' '.join(map(str, oup)))





发表于 2025-07-01 17:02:29 回复(0)
import sys

MAP={
    'A_ip': 0,
    'B_ip': 0,
    'C_ip': 0,
    'D_ip': 0,
    'E_ip': 0,
    'private': 0,
    'error_ip_mark': 0
}

def check_ip(ip: str):
    ip_list = ip.split('.')
    # 特殊 ip
    if ip_list[0] in ['0', '127']:
        return None
    
    # 错误 ip
    if '' in ip_list:
        return 'error_ip_mark'
    
    ip_num_list = list(map(int, ip_list))
    for num in ip_num_list:
        if not 0 <= num <= 255:
            return 'error_ip_mark'
    
    # A 
    if 1 <= ip_num_list[0] <= 127:
        # 第一类私有 ip
        if ip_num_list[0] == 10:
            return 'A_ip', 'private'
        return 'A_ip'
    # B 
    elif 128 <= ip_num_list[0] <= 191:
        # 第二类私有 ip
        if ip_num_list[0] == 172 and 16 <= ip_num_list[1] <= 31:
            return 'B_ip', 'private'
        return 'B_ip'
    # C 
    elif 192 <= ip_num_list[0] <= 223:
        # 第三类私有 ip
        if ip_num_list[0] == 192 and ip_num_list[1] == 168:
            return 'C_ip', 'private'
        return 'C_ip'
    # D 
    elif 224 <= ip_num_list[0] <= 239:
        return 'D_ip'
    # E
    elif 240 <= ip_num_list[0] <= 255:
        return 'E_ip'

def check_mark(mark: str):
    mark_list = mark.split('.')
    # 1. 有空缺或以 ‘0’ 开头都错误
    if '' in mark_list&nbs***bsp;mark_list[0] == '0':
        return False
    # 2. 超出范围错误
    mark_num_list = list(map(int, mark_list))
    for num in mark_num_list:
        if not 0 <= num <= 255:
            return False
    # 构建掩码二进制字符串
    mark_str = ''
    for mark_i in mark_num_list:
        mark_str += f'{mark_i:08b}'
    # 3. 从左到右第一个‘0’(包含该‘0’)后面的片段中含‘1’错误
    for i in range(len(mark_str)):
        if mark_str[i] == '0':
            if '1' in mark_str[i:]:
                return False
        else: # 全为 ‘1’错误
            if i+1 == len(mark_str):
                return False

    return True

def main():
    global MAP
    # 处理每一行输入
    for line in sys.stdin:
        ip, mask = line.strip().split('~')
        class_ip = check_ip(ip)
        is_mask = check_mark(mask)
        if class_ip is None:
            continue
        if is_mask:
            if isinstance(class_ip ,tuple):
                MAP[class_ip[0]]+=1
                MAP[class_ip[1]]+=1
            else:
                MAP[str(class_ip)]+=1
        else:
            MAP['error_ip_mark']+=1

    print(f'{MAP["A_ip"]} {MAP["B_ip"]} {MAP["C_ip"]} {MAP["D_ip"]} {MAP["E_ip"]} {MAP["error_ip_mark"]} {MAP["private"]}')

main()

发表于 2025-06-20 20:00:37 回复(0)
提醒本题合法的子网掩码的判断中,“将IP地址转换为二进制后,必须由若干个连续的1后跟若干个连续的0组成”,指的是每一段补0的二进制,例如1.1.1.1也是非法的,而不是合法的, 因为转成二进制是00000001000000010000000100000001。样例的1.1.1.5的非法的描述很有迷惑性,好像转成二进制变成1.1.1.101然后说非法是因为111101非法……当然,如果你了解ip地址这些自然不是问题……
发表于 2025-05-21 13:34:00 回复(0)
import sys

def solve():
    counts = {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'E': 0, 'Error': 0, 'Private': 0}

    def parse_and_validate_octets(addr_str):
        parts = addr_str.split('.')
        if len(parts) != 4:
            return None
       
        octets = []
        for part in parts:
            if not part.isdigit(): # Handles empty parts like "19..0." and non-digits
                return None
            if len(part) > 1 and part.startswith('0'): # "01" is often invalid in contexts, but here 0-255 is the rule for values
                pass # Let the int conversion and range check handle it. "00" will be 0.
           
            try:
                val = int(part)
                if not (0 <= val <= 255):
                    return None
                octets.append(val)
            except ValueError:
                return None # Should be caught by isdigit already but good for safety
        return octets

    def is_valid_mask_logic(mask_octets):
        if mask_octets is None: # Should not happen if called after parse_and_validate_octets
            return False

        binary_mask_str = ""
        for octet in mask_octets:
            binary_mask_str += format(octet, '08b')
       
        if binary_mask_str == '0' * 32 or binary_mask_str == '1' * 32:
            return False

        # Must be a sequence of 1s followed by a sequence of 0s
        # Find first '0', then check if any '1' appears after it
        try:
            first_zero_idx = binary_mask_str.index('0')
            # Check if there's any '1' in the rest of the string
            if '1' in binary_mask_str[first_zero_idx:]:
                return False
        except ValueError: # No '0' found, means all '1's, already handled.
            pass
           
        return True

    def get_ip_class(ip_octets):
        first_octet = ip_octets[0]
        if 1 <= first_octet <= 126:
            return 'A'
        elif 128 <= first_octet <= 191:
            return 'B'
        elif 192 <= first_octet <= 223:
            return 'C'
        elif 224 <= first_octet <= 239:
            return 'D'
        elif 240 <= first_octet <= 254: # As per problem, 255.255.255.255 is usually broadcast, E class typically up to 255.255.255.254 or .255
                                      # The problem statement says "240.0.0.0"-"255.255.255.255" for E.
            return 'E'
        return None # Should not happen if called after special IP check

    def is_private_ip(ip_octets):
        # 10.0.0.0 - 10.255.255.255
        if ip_octets[0] == 10:
            return True
        # 172.16.0.0 - 172.31.255.255
        if ip_octets[0] == 172 and (16 <= ip_octets[1] <= 31):
            return True
        # 192.168.0.0 - 192.168.255.255
        if ip_octets[0] == 192 and ip_octets[1] == 168:
            return True
        return False

    for line in sys.stdin:
        line = line.strip()
        if not line:
            continue

        try:
            ip_str, mask_str = line.split('~')
        except ValueError: # Line doesn't contain '~'
            counts['Error'] += 1 # Or handle as per contest rules for malformed lines
            continue
           
        current_ip_octets = parse_and_validate_octets(ip_str)
        current_mask_octets = parse_and_validate_octets(mask_str)

        # Check for invalid IP format first
        if current_ip_octets is None:
            counts['Error'] += 1
            continue
           
        # Special IP check (0.*.*.* or 127.*.*.*) - highest priority, just skip, no counts
        if current_ip_octets[0] == 0 or current_ip_octets[0] == 127:
            continue

        # Now check mask format and logic
        if current_mask_octets is None or not is_valid_mask_logic(current_mask_octets):
            counts['Error'] += 1
            continue
       
        # If we reach here, IP format is valid (and not special), and Mask format & logic are valid.
       
        ip_class = get_ip_class(current_ip_octets)
        if ip_class: # Should always be true if not 0 or 127 and first octet is in valid general IP range
            counts[ip_class] += 1

        if is_private_ip(current_ip_octets):
            counts['Private'] += 1
           
    print(counts['A'], counts['B'], counts['C'], counts['D'], counts['E'], counts['Error'], counts['Private'])

if __name__ == "__main__":
    solve()
发表于 2025-05-09 23:03:23 回复(0)
由于合法子网掩码从左到右第一个非255的值只有可能为254, 252, 248, 240, 224, 192, 128, 0之一,所以完全不用转为二进制
import sys
avl_mask = (254, 252, 248, 240, 224, 192, 128, 0)   # 子网掩码第一个非255的段只有是这些值时才合法

def check_mask(mask: str) -> bool:   # 检查子网掩码是否合法,合法则返回Ture
    listed_mask = list(map(int, mask.split('.')))
    if listed_mask == [255, 255, 255, 255]&nbs***bsp;listed_mask == [0, 0, 0, 0]: return False   # 全0全1
    listed_mask.append(0)   # 加个0为了下面这步不越界
    for i in range(4):
        if listed_mask[i] != 255:   # 当第一次遇到非255段时,若该段不在avl_mask中则非法
            if listed_mask[i] not in avl_mask: return False
            elif listed_mask[i+1] != 0: return False   # 后面段非0则不合法
    return True

def check_ip(ip: list) -> bool:   # 检查IP是否合法
    if len(ip) != 4: return False   # 非4段不合法
    for num in ip:
        if not 0 <= num <= 255: return False   # 值非0~255不合法
    return True

A, B, C, D, E, wrong, private = 0, 0, 0, 0, 0 ,0 ,0
for line in sys.stdin:
    addr = line[:len(line)-1].split('~')
    ip = [int(item) for item in addr[0].split('.') if item != '']
    if ip[0] == 0&nbs***bsp;ip[0] == 127: continue   # 0和127开头的跳过
    if not check_ip(ip)&nbs***bsp;not check_mask(addr[1]):   # 若IP或子网掩码有误则计数后跳过
        wrong += 1
        continue
    if 1 <= ip[0] <= 126: A += 1   # IP和掩码都合法才会进入这一步,统计各类地址
    elif 128 <= ip[0] <= 191: B += 1
    elif 192 <= ip[0] <= 223: C += 1
    elif 224 <= ip[0] <= 239: D += 1
    elif 240 <= ip[0] <= 255: E += 1
    if ip[0] == 10&nbs***bsp;(ip[0] == 192 and ip[1] == 168)&nbs***bsp;(ip[0] == 172 and 16 <= ip[1] <= 31): 
        private += 1   # 统计私有地址
print(A, B, C, D, E, wrong, private)

发表于 2025-04-25 21:15:11 回复(0)
一定要记得转二进制时候补齐八位啊😭
发表于 2025-04-19 19:21:15 回复(0)

这道题主要是题目要求没讲清楚:掩码没问题后判断ip类别,ip类别的判断是根据第一项的范围来的,起初还以为是单个值,其次是私有ip的定义更是一坨,第一个是根据ip的第一个字段,第二个和第三个需要看前两个字段,并且第一个字段是固定值第二个字段是个范围,这个范围也没讲清楚。

# 识别有效的ip和掩码进行分类统计
import sys
ip_list = []
mask_list = []
total_num = {'A':0,'B':0,'C':0,'D':0,'E':0,'error':0,'pri':0}
for line in sys.stdin:
    a = line.split('~')
    head  = a[0].split('.')[0]
    # 剔除特殊ip
    if head != '0' and head != '127':
        ip_list.append(a[0])
        mask_list.append(a[1])
ip_correct = []  # 初始化正确的ip位置列表
ip_error = []
mask_correct = []
mask_error = []
for i in range(len(ip_list)):
    # ip判别
    empty_flage = False
    ip_errror_flage = False
    ip = ip_list[i]
    ip_temp = ip.split('.')
    for part in ip_temp:
        if len(part)<1:
            empty_flage = True
    if empty_flage:
        ip_error.append(i)
        continue
    ip_correct.append((i,int(ip_temp[0])))         # 保存争取的索引以及正确ip的类别
for j in range(len(mask_list)):
    # mask判别
    cat_=''
    cat_bin=''
    illage_num=0
    mask_error_flage = False
    mask_empty_flage = False
    mask = mask_list[j]
    mask_temp = mask.split('.')
    for part in mask_temp:
        if len(part)<1:
            mask_empty_flage = True
    if mask_empty_flage:
        mask_error.append(j)
        continue
    for i in range(len(mask_temp)):
        cat_ += bin(int(mask_temp[i]))[2:].zfill(8)
    if cat_.count('1') == len(cat_):
        mask_error.append(j)
        continue
    elif cat_.count('0') == len(cat_):
        mask_error.append(j)
        continue
    bin_mask = []
    for k in range(len(mask_temp)):
        bin_mask.append(bin(int(mask_temp[k]))) # 二进制mask
    for item in bin_mask:
        cat_bin += item[2:].zfill(8)
    # print(cat_bin)
    illage_num+=cat_bin.count('01')
    illage_num+=cat_bin.count('10')
    if illage_num >=2:
        mask_error_flage = True
        mask_error.append(j)
    if mask_empty_flage or mask_error_flage:
        continue
    mask_correct.append(j)          # 仅保存正确掩码的索引
# 计算类别正确类别
for item in ip_correct:
    index,type_ = item
    if index in mask_correct:
        if type_ <128 :
            if type_ == 10 :
                total_num['A'] += 1
                total_num['pri'] += 1
            else:
                total_num['A'] += 1
        elif type_ <192 :
            if type_ == 172 and 15<int(ip_list[index].split('.')[1]) <32:
                total_num['B'] += 1
                total_num['pri'] += 1
            else:
                total_num['B'] += 1
        elif type_ <224 :
            if type_ == 192 and ip_list[index].split('.')[1] == '168':
                total_num['C'] += 1
                total_num['pri'] += 1
            else:
                total_num['C'] += 1
        elif type_ < 240:
            total_num['D'] += 1
        elif type_ <255:
            total_num['E'] += 1
ip_error = list(set(ip_error))
mask_error = list(set(mask_error))
for ip_error_index in ip_error:
    if ip_error_index in mask_error:
        mask_error.remove(ip_error_index)
error_list = ip_error + mask_error
total_num['error'] = len(error_list)
print(total_num['A'],total_num['B'],total_num['C'],total_num['D'],total_num['E'],total_num['error'],total_num['pri'])
发表于 2025-04-03 12:16:10 回复(0)
import sys
#设置变量
num=[0]*7
ips=[]
masks=[]
#存储输入IP地址
for line in sys.stdin:
    address=line.strip().split('~')
    ips.append(address[0])
    masks.append(address[1])

#判断子网掩码是否合法
def ifmask(ipmask):
    if  not ifip(ipmask):
        return False
    bitmask=''.join(bin(int(num))[2:].rjust(8,'0') for num in ipmask)
    if bitmask in ('0'*32,'1'*32):
        return False
    if '1' in bitmask.lstrip('1'):
        return False
    return True

#判断IP地址是否合法
def ifip(ip):
    if len(ip)!=4:
        return False
    for i in ip:
        if not i:
            return False
        if int(i) not in range(0,256):
            return False
    return True

i=0
for a in masks:
    mask=a.split('.')
    ip=ips[i].split('.')
    if int(ip[0])!=(0 or 127):
        if ifmask(mask):
            if ifip(ip):
                if int(ip[0]) in range(1,127):
                    num[0]+=1
                    if int(ip[0])==10:
                        num[6]+=1
                elif int(ip[0]) in range(128,192):
                    num[1]+=1
                    if int(ip[0])==172 and int(ip[1]) in range(16,32):
                        num[6]+=1
                elif int(ip[0]) in range(192,224):
                    num[2]+=1
                    if int(ip[0])==192 and int(ip[1])==168:
                        num[6]+=1
                elif int(ip[0]) in range(224,240):
                    num[3]+=1
                elif int(ip[0]) in range(240,256):
                    num[4]+=1
            else:
                num[5]+=1
        else:
            num[5]+=1
    i+=1

for i in num:
    print(i,end=' ')
发表于 2025-03-27 18:42:24 回复(0)
def is_valid_ip(ip_str):
    parts = ip_str.split(".")
    if len(parts) != 4:
        return False
    for part in parts:
        if not part.isdigit():
            return False
        num = int(part)
        if num < 0 or num > 255:
            return False
    return True

def is_valid_mask(mask_str):
    if not is_valid_ip(mask_str):
        return False
    parts = list(map(int, mask_str.split(".")))
    binary_str = "".join(f"{p:08b}" for p in parts)
    if all(c == "0" for c in binary_str) or all(c == "1" for c in binary_str):
        return False
    first_zero = binary_str.find("0")
    if first_zero == -1:
        return False
    if "1" in binary_str[first_zero:]:
        return False
    return True

error = 0
private = 0
a = 0
b = 0
c = 0
d = 0
e = 0

inf = []
while True:
    try:
        line = input().strip()
        if not line:
            break
        inf.append(line)
    except EOFError:
        break

for line in inf:
    try:
        if "~" not in line:
            error += 1
            continue
        ip_str, mask_str = line.split("~", 1)
        valid_ip = is_valid_ip(ip_str)
        valid_mask = is_valid_mask(mask_str)
        if not (valid_ip and valid_mask):
            error += 1
            continue
        ip_parts = list(map(int, ip_str.split(".")))
        first = ip_parts[0]
        # Check private IP
        is_private = False
        if ip_parts[0] == 10:
            is_private = True
        elif ip_parts[0] == 172 and 16 <= ip_parts[1] <= 31:
            is_private = True
        elif ip_parts[0] == 192 and ip_parts[1] == 168:
            is_private = True
        if is_private:
            private += 1
        # Skip 0.x.x.x and 127.x.x.x
        if first == 0 or first == 127:
            continue
        # Classify
        if 1 <= first <= 126:
            a += 1
        elif 128 <= first <= 191:
            b += 1
        elif 192 <= first <= 223:
            c += 1
        elif 224 <= first <= 239:
            d += 1
        elif 240 <= first <= 255:
            e += 1
    except Exception as ex:  # 修改变量名为ex避免冲突
        error += 1
        # print(f"处理行 {line} 时出错: {ex}")  # 可选的错误打印
print(f"{a} {b} {c} {d} {e} {error} {private}")
发表于 2025-03-19 21:34:01 回复(1)
import sys
li=[0,0,0,0,0,0,0]
def ip5(ips):
    if 1<=ips[0]<=126:
        li[0]+=1
    elif 128<=ips[0]<=191:
        li[1]+=1
    elif 192<=ips[0]<=223:
        li[2]+=1
    elif 224<=ips[0]<=239:
        li[3]+=1
    elif 240<=ips[0]<=255:
        li[4]+=1
    return
def ipsy(ips):
    if ips[0]==10 or ips[0]==172 and 16<=ips[1]<=31 or ips[0]==192 and ips[1]==168:
        li[6]+=1
    return
def ymhf(yms):
    binyms=''
    for i in yms:
        binyms+=bin(i)[2:].rjust(8,'0')
    pos0=binyms.find('0')
    pos1=binyms.rfind('1')
    if pos0!=-1 and pos1!=-1 and pos0-pos1==1:
        return True
    else:
        return False
def judge(line):
    ip,ym=line.split('~')
    ips=[int(i) for i in filter(None,ip.split('.'))]
    yms=[int(i) for i in filter(None,ym.split('.'))]
    if ips[0]==0 or ips[0]==127:
        return
    if len(ips) < 4 or len(yms) < 4:
        li[5] += 1
        return
    if ymhf(yms):
        ip5(ips)
        ipsy(ips)
        return
    else:
        li[5]+=1
        return
for line in sys.stdin:
    judge(line)
for i in li:
    print(i,end=' ')
发表于 2025-03-06 19:13:00 回复(0)
说实话这题目的需求都没有讲清, 写不出来很正常, 需求都是对着不通过的测试集才理清的
import sys


def judge_ip(ip_address: str):
    try:
        num_list = [int(item) for item in ip_address.split(".")]
    except:
        return ['invalid', ' ', ' ']
    num1 = num_list[0]
    num2 = num_list[1]
    num3 = num_list[2]
    num4 = num_list[3]
    if  1<= num1 <= 126:
        if  num1 == 10:
            return ['valid', 'A', 'P']
        else:
            return ['valid', 'A', ' ']
    elif 128<= num1 <= 191:
        if num1 == 172 and 16 <= num2 <= 31:
            return ['valid', 'B', 'P']
        else:
            return ['valid', 'B', ' ']
    elif 192<= num1 <= 223:
        if num1 == 192 and num2 == 168:
            return ['valid', 'C', 'P']
        else:
            return ['valid', 'C', ' ']
    elif 224<= num1 <= 239:
        return ['valid', 'D', ' ']
    elif 240<= num1 <= 255:
        return ['valid', 'E', ' ']
    else:
        return ['pass', ' ', ' ']


def judge_mark(ip_address: str):
    num_list = [bin(int(item))[2:] for item in ip_address.split(".")]
    for i in range(0,4):
        if len(num_list[i]) <8:
            num_list[i] = '0'*(8-len(num_list[i])) + num_list[i]
            
    num_str = ''.join(num_list)
    if num_str.lower() == '1'*32:
        return 'invalid'
    if num_str.lower() == '0'*32:
        return 'invalid'
    for i in range(0, len(num_str)):
        if not num_str[i] == '1':
            for j in range(i, len(num_str)):
                if num_str[j] != '0':
                    return 'invalid'
    return 'valid'

res_dict = {'A':0, 'B':0, 'C':0, 'D':0, 'E':0, 'invalid':0,'P':0}
for item in sys.stdin.readlines():
        if item == '\n':
            continue
        item = item.rstrip('\n')
        slist = item.split('~')
        temp = judge_ip(slist[0])
        temp_mark = judge_mark(slist[1])
        if temp[0] == 'pass':
            continue
        if temp[0] == 'invalid'&nbs***bsp;temp_mark == 'invalid':
            res_dict['invalid'] += 1
            continue
        if temp[1] in res_dict.keys():
            res_dict[temp[1]] += 1
        if temp[2] in res_dict.keys():
            res_dict[temp[2]] += 1
        
        

print(f"{res_dict['A']} {res_dict['B']} {res_dict['C']} {res_dict['D']} {res_dict['E']} {res_dict['invalid'] } {res_dict['P']}")

发表于 2025-02-27 01:20:25 回复(0)
a = b = c = d = e = error = private = 0
try:
    while True:
        user_input = input("")
        if user_input == "":
            break

        parts = user_input.split("~")
        if len(parts) != 2:
            error += 1
            continue

        ip_str, mask_str = parts[0], parts[1]

        # Check IP validity
        ip_valid = True
        ip_parts = ip_str.split(".")
        if len(ip_parts) != 4:
            ip_valid = False
        else:
            for p in ip_parts:
                if not p.isdigit():
                    ip_valid = False
                    break
                num = int(p)
                if num < 0&nbs***bsp;num > 255:
                    ip_valid = False
                    break

        # Check Mask validity
        mask_valid = True
        mask_parts = mask_str.split(".")
        if len(mask_parts) != 4:
            mask_valid = False
        else:
            for p in mask_parts:
                if not p.isdigit():
                    mask_valid = False
                    break
                num = int(p)
                if num < 0&nbs***bsp;num > 255:
                    mask_valid = False
                    break

        if mask_valid:
            mask_nums = [int(p) for p in mask_parts]
            binary_str = "".join([format(num, "08b") for num in mask_nums])
            all_zero = all(c == "0" for c in binary_str)
            all_one = all(c == "1" for c in binary_str)
            if all_zero&nbs***bsp;all_one:
                mask_valid = False
            else:
                first_zero = binary_str.find("0")
                if first_zero == -1:
                    mask_valid = False
                else:
                    if "1" in binary_str[first_zero:]:
                        mask_valid = False

        if not (ip_valid and mask_valid):
            error += 1
        else:
            ip_parts = [int(p) for p in ip_parts]
            # Check private IP
            if (
                (ip_parts[0] == 10)
               &nbs***bsp;(ip_parts[0] == 172 and 16 <= ip_parts[1] <= 31)
               &nbs***bsp;(ip_parts[0] == 192 and ip_parts[1] == 168)
            ):
                private += 1
            # Check IP class
            if ip_parts[0] not in (0, 127):
                first_byte = ip_parts[0]
                if 1 <= first_byte <= 126:
                    a += 1
                elif 128 <= first_byte <= 191:
                    b += 1
                elif 192 <= first_byte <= 223:
                    c += 1
                elif 224 <= first_byte <= 239:
                    d += 1
                elif 240 <= first_byte <= 255:
                    e += 1

except EOFError:
    pass
finally:
    print(f"{a} {b} {c} {d} {e} {error} {private}")
通过8/11,没通过的预期输出和实际输出只差了一个数,求大佬看看怎么回事QAQ
发表于 2025-02-15 11:40:53 回复(0)
没研究出来哪个地方有问题
import sys
a = b = c = d = e = count_error = count_pri = 0
# 十进制转二进制
def trans(number):
    result = ""
    if number == 0:
        return 0
    dic = []
    while number > 0:
        result = str(number % 2) + result
        number = number // 2
    return result
# 判断IP是否错误
def isIp(ip):
    dic = ip.split(".")
    if len(dic) != 4:
        return False
    for i in dic:
        if i.isdigit() != True:
            return False
        if int(i) > 255&nbs***bsp;int(i) < 0:
            return False
    return True
# 判断子网掩码是否错误
def isMask(mask):
    if isIp(mask) == False&nbs***bsp;mask == "1.1.1.1"&nbs***bsp;mask == "0.0.0.0":
        return False
    n1, n2, n3, n4 = mask.split(".")
    for n in [n1, n2, n3, n4]:
        if "01" in trans(int(n)):
            return False
    return True
# 判断IP类型
def type(ip, a, b, c, d, e, count_pri):
    n1, n2, n3, n4 = ip.split(".")
    n1 = int(n1)
    n2 = int(n2)
    if n1 >= 1 and n1 < 127:
        a += 1
    elif n1 >= 128 and n1 < 192:
        b += 1
    elif n1 >= 192 and n1 < 224:
        c += 1
    elif n1 >= 224 and n1 < 240:
        d += 1
    elif n1 >= 240 and n1 < 260:
        e += 1
    if n1 == 10:
        count_pri += 1
    if n1 == 172 and (n2 >= 16 and n2 <= 31):
        count_pri += 1
    if n1 == 192 and n2 == 168:
        count_pri += 1
    return a, b, c, d, e, count_pri
for line in sys.stdin:
    ip, mask = line.split("~")
    dic = ip.split(".")
    if int(dic[0]) != 0 and int(dic[0]) != 127:
        if isIp(ip) == False:
            count_error += 1
        else:
            a, b, c, d, e, count_pri = type(ip, a, b, c, d, e, count_pri)
        if isMask(mask) == False:
            count_error += 1
print(f"{a} {b} {c} {d} {e} {count_error} {count_pri}")

发表于 2025-01-06 15:30:03 回复(0)
通过了7/11, 错误用例又复制不了不能定位,是由3个错误ip地址被识别成了A类和E类:
预期输出:71 41 21 12 10 68 1
实际输出:73 41 21 13 10 65 1 

al = [1, 0, 0, 0, 126, 255, 255, 255, "a"]
bl = [128, 0, 0, 0, 191, 255, 255, 255, "b"]
cl = [192, 0, 0, 0, 223, 255, 255, 255, "c"]
dl = [224, 0, 0, 0, 239, 255, 255, 255, "d"]
el = [240, 0, 0, 0, 255, 255, 255, 255, "e"]

sl1 = [10, 0, 0, 0, 10, 255, 255, 255, "s"]
sl2 = [172, 16, 0, 0, 172, 31, 255, 255, "s"]
sl3 = [192, 168, 0, 0, 192, 168, 255, 255, "s"]

allm = [al, bl, cl, dl, el, sl1, sl2, sl3]

# ABCDE类地址的数量、错误IP、私有IP
ar = {"a": 0, "b": 0, "c": 0, "d": 0, "e": 0, "er": 0, "s": 0}

def d2b(a):
    s = []
    length = 0
    while int(a) > 0:
        s.append(int(a % 2))
        a = int(a / 2)
        length += 1
    s = s[::-1]
    if len(s) == 0:
        s = [0]
    return s

def iscorrect(s):
    isCorrect = True
    s2 = s[::-1]
    i0 = -1
    i1 = -1
    if len(s) == 1 and s[0] == 0:
        isCorrect = True
    else:
        if 0 in s:
            i0 = s.index(0)
        else:
            isCorrect = True
    if 1 in s:
        i1 = len(s) - s2.index(1) - 1
    if i0 > -1 and i0 < i1:
        isCorrect = False
    return isCorrect

while True:
    try:
        ip = input().strip()

    except:
        break
    if "~" in ip:
        ip = ip.replace("~", ".")
    x1, x2, x3, x4, x5, x6, x7, x8 = ip.split(".")
    if (
        len(x1) == 0
        or len(x2) == 0
        or len(x3) == 0
        or len(x4) == 0
        or len(x5) == 0
        or len(x6) == 0
        or len(x7) == 0
        or len(x8) == 0
    ):
        ar["er"] += 1
        continue

    x1 = int(x1)
    x2 = int(x2)
    x3 = int(x3)
    x4 = int(x4)
    x5 = int(x5)
    x6 = int(x6)
    x7 = int(x7)
    x8 = int(x8)

    if x1 == 0 or x1 == 127:
        continue
    # if(len(x1)<=0): continue
    # print(1,iscorrect(d2b(x5)))
    if (
        (not iscorrect(d2b(x5)))
        or (not iscorrect(d2b(x6)))
        or (not iscorrect(d2b(x7)))
        or (not iscorrect(d2b(x8)))
        or (not iscorrect(d2b(x5) + d2b(x6)))
        or (not iscorrect(d2b(x5) + d2b(x6) + d2b(x7)))
        or (not iscorrect(d2b(x5) + d2b(x6) + d2b(x7) + d2b(x8)))
        or (x5 == 255 and x6 == 255 and x7 == 255 and x8 == 255)
    ):

        ar["er"] += 1
        continue

    cr = [x1, x2, x3, x4]
    # print(cr)

    for r in allm:
        if r[0] <= x1 and r[4] >= x1 and r[1] <= x2 and r[5] >= x2:
            # print("label ",r[8],r[0],x1 , r[5] , x1)
            ar[r[8]] = ar[r[8]] + 1

for key, value in ar.items():
    print(value, end=" ")


发表于 2025-01-01 22:04:53 回复(2)
该题的问法很有问题:
1、私有ip不冲突,这个歧义就很严重。是不是要两个计入
2、如果子网掩码错误,那及时ip正确也不计入分组(这个看不出来)
3、如果ip 和子网掩码都错误,那是不是两个都计入?我也没看出来


发表于 2024-11-11 16:34:40 回复(0)
import sys, re
class IsValidIp():
    def __init__(self,ip):
        self.ip1 = ip.split('~')[0].split('.')
        self.ip2 = ip.split('~')[1].split('.')
    def isRight(self):
        if len(self.ip1)<4&nbs***bsp;len(self.ip2)<4:
            return 'err'
        for i in self.ip1:
            if not i.isdigit():
                return 'err'
            else:
                if int(i)<0&nbs***bsp;int(i)>255:
                    return 'err'
        s = ''
        pattern = r'^1+0+$'
        for i in self.ip2:
            if not i.isdigit():
                return 'err'
            else:
                if int(i)<0&nbs***bsp;int(i)>255:
                    return 'err'
                else:
                    s = s + bin(int(i))[2:].rjust(8, '0')
        if not re.fullmatch(pattern, s):
            return 'err'
    def Not_count(self):
        if self.ip1[0] == '0'&nbs***bsp;self.ip1[0]== '127':
            return 'not_count'
    def ABCDEF(self):
        if 0<int(self.ip1[0])<127:
            if int(self.ip1[0]) == 10:
                return 'a+pa'
            else:
                return 'a'
        elif 128<=int(self.ip1[0])<192:
            if int(self.ip1[0]) == 172 and 16<int(self.ip1[0])<32:
                return 'b+pa'
            else:
                return 'b'
        elif 192 <= int(self.ip1[0])<224:
            if int(self.ip1[0]) == 192 and int(self.ip1[1])==168:
                return 'c+pa'
            else:
                return 'c'
        elif 224<= int(self.ip1[0])<240:
            return 'd'
        else:
            return 'e'
nums = [0]*7
for line in sys.stdin:
    a = line.strip()
    b = IsValidIp(a)
    if b.Not_count() == 'not_count':
       continue
    if b.isRight() == 'err':
        nums[5]=nums[5]+1
        continue
    else:
        c= b.ABCDEF()
        if c == 'a+pa':
            nums[0]=1+nums[0]
            nums[6]=1+nums[6]
        if c =='a':
            nums[0]=1+nums[0]
        if c=='b':
            nums[1]+=1
        if c == 'b=pa':
            nums[1]+=1
            nums[6]+=1
        if c=='c':
            nums[2]+=1
        if c =='c+pa':
            nums[2]+=1
            nums[6]+=1
        if c == 'd':
            nums[3]+=1
        if c == 'e':
            nums[4]+=1
print(' '.join(map(str,nums)))

发表于 2024-11-06 12:50:04 回复(0)
感觉这题的测试案例确实存在问题,卡在(3/10),用例总共40组数据,我的输出是:16 6 3 1 0 14 0 ,预期输出是:16 6 3 1 0 13 0,少了一组数据
import sys

def ip_true(ip):
    k = 0
    x = ip.split('.')
    if x.count('')==0:
        for i in x:
            if int(i)<256 and str(int(i)) == i:
               k+=1 
    return True if k==4 else False 
def mac_true(mac):
    x = mac.split('.')
    k = ''
    for i in x:
        if int(i)<256:
            y=bin(int(i))[2:].zfill(8)
            k+=y
    if 0<k.count('1')< 32 and k[0:k.count('1')]=='1'*k.count('1'):
        return True
    else:
        return False

res = [0,0,0,0,0,0,0]
for line in sys.stdin:
    x = line.split('~')
    if ip_true(x[0])==False&nbs***bsp;mac_true(x[1])==False:
        res[5]+=1
    else:
        a = x[0].split('.')
        if 1<=int(a[0])<=126:
            res[0]+=1
            if int(a[0])==10:
                res[6]+=1
        elif 128<=int(a[0])<=191:
            res[1]+=1
            if int(a[0])==172 and 16<=int(a[1])<=31:
                res[6]+=1   
        elif 192<=int(a[0])<=223:
            res[2]+=1
            if int(a[0])==192 and int(a[1])==168:
                res[6]+=1 
        elif 224<=int(a[0])<=239:
            res[3]+=1
        else:
            res[4]+=1
for i in res:
    print(i,end=' ')


发表于 2024-09-28 17:29:54 回复(4)
Python3版本,通过建立类组织代码,ip地址采用32位数值存储,ip地址及子网掩码错误可能会出现在不同的步骤中,用了抛出异常的方案,在主程序中捕捉异常计数,避免多次计数。
import sys

class IpAddress:
    # 定义类属性,用于计数
    A = 0
    B = 0
    C = 0
    D = 0
    E = 0
    PA = 0
    Err = 0

    # 将文本型ip地址转换为二进制,采用int保存
    @staticmethod
    def address_to_num(address):
        num = 0
        add_split = address.split(".")
        # ip地址或子网掩码错误的校验,会在解析ip和子网掩码的多个不同步骤中出现,但计数只能记1次。因此,采用asserterror形式抛出异常,在主程序里面用异常捕获单独计数。以下类似
        assert len(add_split) == 4
        for x in add_split:
            num <<= 8
            try:
                a = int(x)
            except:
                raise AssertionError
            assert a<= 255
            num += int(x)
        return num

    # 创建实例,保存ip和子网掩码
    def __init__(self, address, code) -> None:
        self.address =self.address_to_num(address)
        self.code = self.address_to_num(code)

    # IP地址的类型,属于A~E中的哪一类
    def IpKind(self):
        # 0x01000000为1.0.0.0的16进制写法,0x7effffff为126.255.255.255的16进制写法,以下类似。
        if self.address >= 0x01000000 and self.address <= 0x7EFFFFFF:
            IpAddress.A += 1
            return "A"
        elif self.address >= 0x80000000 and self.address <= 0xbfFFFFFF:
            IpAddress.B += 1
            return "B"
        elif self.address >= 0xc0000000 and self.address <= 0xdfffffff:
            IpAddress.C += 1
            return "C"
        elif self.address >= 0xe0000000 and self.address <= 0xefffffff:
            IpAddress.D += 1
            return "D"
        elif self.address >= 0xf0000000 and self.address <= 0xffffffff:
            IpAddress.E += 1
            return "E"
    # 检查是否为私有IP
    def Private(self):
        if self.address >= 0x0a000000 and self.address <=0x0affffff:
            IpAddress.PA += 1
            return True
        elif self.address >=0xac100000 and self.address <= 0xac1f0000:
            IpAddress.PA += 1
            return True
        elif self.address >= 0xc0a80000 and self.address <= 0xc0a8ffff:
            IpAddress.PA += 1
            return True
        else:
            return False
    
    # 检查子网掩码是否为非法子网掩码
    def LegalCode(self):
        # 0.*.*.*及127.*.*.*这些特殊IP排除
        if self.address <=0xffffff&nbs***bsp;(self.address >= 0x7f000000 and self.address <= 0x7fffffff):
            return True
        # 特殊子网掩码校验
        assert self.code != 0xffffffff
        assert self.code != 0
        # 一般子网掩码校验,采用位运算方案
        # 方案是:将子网掩码与32位全为1的数进行异或运算,然后加1,最后与原来的子网掩码按位或,若相等,则为前面全为1,后面全为0的子网掩码。
        # 例如:一个合法的子网掩码类似于0b11110000,用8位方便展示,计算过程也适用于32位,将其与0b11111111进行按位异或后,得到0b00001111。这样的数前面全部为0,后面全部为1。加1后,得到0b00010000,只有1位为1,剩余位全为0,且为1的为正好在子网掩码的最后一位1出现的位置。因此,与子网掩码按位与后,原子网掩码数值不变。
        # 而一个非法的子网掩码,例如0b00100010,将其与0b11111111按位异或后,得到0b11011101。这样的数加1后,得到0b11011110,与原来的子网掩码,会在原来为0的多个位置出现1。与子网掩码按位或后,子网掩码数值改变。
        assert self.code == self.code | ( (self.code ^ 0xffffffff) + 1 )

for line in sys.stdin:
    if line == '\n':
        break
    line = line.strip('\n')    
    address, code = line.split('~')
    try:
        a = IpAddress(address,code)
        a.LegalCode()
        a.IpKind()
        a.Private()
    except AssertionError:
        IpAddress.Err += 1
        
print(f'{IpAddress.A} {IpAddress.B} {IpAddress.C} {IpAddress.D} {IpAddress.E} {IpAddress.Err} {IpAddress.PA}')


发表于 2024-09-23 11:54:46 回复(0)
import sys

a,b,c,d,e,error,prv = [0]*7
for line in sys.stdin:
    p = line.split()
    ip, mask = p[0].split('~')
    ip_list = ip.split('.')
    mask_list = mask.split('.')
    mask_list_bin = [bin(int(m))[2:].rjust(8, '0') for m in mask_list]
    # 忽略 0* / 127*
    if(ip_list[0] in ['0', '127']):
        continue

    # 子网掩码 单独计算
    mask_str = ''.join(mask_list_bin)
    if '01' in mask_str&nbs***bsp;len(set(mask_list_bin)) == 1:
        error += 1
        continue
    
    # ip 识别
    if len(ip_list) == 4:
        nip = False
        for n in ip_list:
            if n == '':
                error += 1
                nip = True
                break
        if nip:        
            continue
        
        # ip 分类
        if int(ip_list[0]) <= 126 and int(ip_list[0]) >= 1:
            a += 1
        elif int(ip_list[0]) >= 128 and int(ip_list[0]) <= 191:
            b += 1
        elif int(ip_list[0]) >= 192 and int(ip_list[0]) <= 223:
            c += 1
        elif int(ip_list[0]) >= 224 and int(ip_list[0]) <= 239:
            d += 1
        elif int(ip_list[0]) >= 240 and int(ip_list[0]) <= 255:
            e += 1

        # private
        if int(ip_list[0]) == 192 and int(ip_list[1]) ==168:
            prv += 1
        elif int(ip_list[0]) == 172 and int(ip_list[1]) >=16 and int(ip_list[1]) <= 31:
            prv += 1
        elif int(ip_list[0]) == 10:
            prv += 1
    else:
        error += 1
print('{} {} {} {} {} {} {}'.format(a,b,c,d,e,error,prv))

发表于 2024-09-09 09:14:36 回复(1)