算法-华为OD机试-识别有效的IP地址和掩码并进行分类统计

1.描述

见牛客网

https://www.nowcoder.com/practice/de538edd6f7e4bc3a5689723a7435682

2. 分析

根据题目要求,分为以下几步

1. 提取IP地址和子网掩码

我们首先需要拆分输入的每一行,分别提取IP地址和子网掩码,并检查它们的合法性。

2. 分类解析识别IP地址

根据题目提供的IP地址范围,将IP地址分类为A/B/C/D/E类地址。同时,检查IP地址是否属于私有IP地址。

3. 检查子网掩码的合法性

合法的子网掩码必须是二进制下前面是连续的1,然后全是0。非法的子网掩码需要单独归类。

4. 统计结果

最后,将所有的分类结果统计并输出。ip或者子网有一个为非法,就记为非法并统计下一条

3.代码

import sys
import re

def is_sw(ip):
    nums = ip.split('.')
    one = int(nums[0])
    two = int(nums[1])
    if one == 10:
        return True
    elif one == 172 and 16<=two<=32:
        return True
    elif one == 192 and two==168:
        return True
    return False
    
def is_ip(ip):    
    k = int(ip.split(".")[0])
    
    if 1<=k<=126:
        return "A"
    elif 128<=k<=191:
        return "B"
    elif 192<=k<=223:
        return "C"
    elif 224<=k<=239:
        return "D"
    elif 240<=k<=255:
        return "E"
    return False

def is_mask(mask):
    # 将所有数转为int型
    # m = (int(i) for i in mask.split("."))
    # # 将所有数转为二进制
    # m = (bin(i) for i in m)
    # # 连接成一个字符串,每一个去掉0b前缀,左补全0
    # mask_str = "".join( i[2:].zfill(8) for i in m)                
    # 上面的也可以写成一句
    mask_str = "".join([bin(int(i))[2:].zfill(8) for i in mask.split(".")])
    # 开始判断,只保留111110000这种格式的
    if "01" in mask_str or "1"*32==mask_str or "0"*32==mask_str:
        return False
    return True



# 定义全局结果 
result = {
    "A":0,
    "B":0,
    "C":0,
    "D":0,
    "E":0,
    "Err":0,
    "SW":0
}

for line in sys.stdin: 
    # 提取 Ip 和 mask
    ip,mask = line.split("~")
        
    # 提取无效 Ip 或者 无效掩码,不计数,开始下一行
    # 去掉非  1.12.123.123 这种格式的,如19..10.,注意这里没有过滤 大于 255的
    # 注意这里 . 要转义,用\.
    ip_ptn = "^(\d{1,3}\.){3}\d{1,3}$"
    if not re.match(ip_ptn,ip) or not re.match(ip_ptn,mask):
        result["Err"] += 1
        continue

    # 去掉 0 和127 开头的
    if ip.startswith("0.") or ip.startswith('127.'):
        continue 

    # 转为列表
    ip_part  = list(map(int,ip.split(".")))
    mask_part  = list(map(int,mask.split(".")))

    # 识别大于255的,因为\d是0-9,所以小于0的会在上面过滤掉了
    if any(i>255 for i in ip_part) or any(m>255 for m in mask_part):
        result["Err"]+=1
        continue

    # 识别非法掩码
    if not is_mask(mask):
        result["Err"] += 1
        continue
	# 因为 ip类型和私网IP不冲突,所有不用continue,两都都判断
    # 识别IP地址
    ip_type = is_ip(ip)
    if ip_type != False:
        result[ip_type] += 1

    # 识别私网IP地址
    if is_sw(ip):
        result["SW"] += 1

for v in result.values():
    print(v,end=" ")

4.知识点

1.any()的用法

any(可迭代对象) 表示,可迭代对象中,有一项为真返回真
列中用来判断 所有都要小于255的情况,即

# 表示列表中所有数任何一个大于255就返回真,所有都小于255就返回假
any(i >255 for i in list)

这里还有一个all()函数,表示可迭代对象中,有全部为真才返回真,即有一项为假就返回假

# 表示所有的都要小于255才返回真,任何一个大于255就为假
all(i<255 for i in list)

2.正则式

# 如果能在 str 内匹配到 ptn 就返回真,否则为假
re.match(ptn,str)

3.常用方法

方法名描述
join(t)连接字符串t
startswith(d)以d开头
split©按c拆分
bin(n)整数n转二进制
int(s)字符s转int
zfill(n)左补n位全零
rjust(n,c)右补n对应c字符
ljust(n,c)左补n对应c字符
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值