VLAN资源池

题目描述

VLAN是一种对局域网设备进行逻辑划分的技术, 为了标识不同的VLAN, 引入VLAN ID(1-4094之间的整数)的概念.

定义一个VLAN ID的资源池(下称VLAN资源池), 资源池中连续的VLAN用开始VLAN-结束VLAN表示, 不连续的用单个整数表示, 所有的VLAN用英文逗号连接起来.

现在有一个VLAN资源池, 业务需要从资源池中申请一个VLAN, 需要你输出从VLAN资源池中移除申请的VLAN后的资源池.

输入描述

第一行为字符串格式的VLAN资源池, 第二行为业务要申请的VLAN, VLAN的取值范围为 [1,4094] 之间的整数.

输出描述

从输入VLAN资源池中移除申请的VLAN后字符串格式的VLAN资源池, 输出要求满足题目描述中的格式, 并且按照VLAN从小到大升序输出. 如果申请的VLAN不在原VLAN资源池内, 输出原VLAN资源池升序排序后的字符串即可.

示例1

输入:

1-5
2

输出:

1,3-5

说明: 原VLAN资源池中有VLAN 1/2/3/4/5, 从资源池中移除2后, 剩下VLAN 1/3/4/5, 按照题目描述格式并升序后的结果为 1,3-5

示例2

输入:

20-21,15,18,30,5-10
15

输出:

5-10,18,20-21,30

说明: 原VLAN资源池中有VLAN 5/6/7/8/9/10/15/18/20/21/30, 从资源池中移除15后, 资源池中剩下的VLAN为 5/6/7/8/9/10/18/20/21/30, 按照题目描述格式并升序后的结果为 5-10,18,20-21,30.

示例3

输入:

5,1-3
10

输出:

1-3,5

题解

Python

def main():
    # 读取输入
    # 解析当前所有的 VLAN ID, 并存储到集合或者数组中
    # 然后移除指定的 ID
    # 最后新剩下的 ID 格式化输出
    parts = input().split(",")
    id_set = set()
    for part in parts:
        if "-" in part:
            range_part = part.split("-")
            start_id = int(range_part[0])
            end_id = int(range_part[1])
            for vlan_id in range(start_id, end_id + 1):
                assert 1 <= vlan_id <= 4094
                id_set.add(vlan_id)
        else:
            vlan_id = int(part)
            assert 1 <= vlan_id <= 4094
            id_set.add(vlan_id)
    assert id_set
    removed_id = int(input())

    if removed_id in id_set:
        id_set.remove(removed_id)

    # 格式化输出
    # 先转换成列表, 再排序
    id_list = list(id_set)
    id_list.sort()

    start_id = -1
    last_id = -1
    out = []
    for vlan_id in id_list:
        if last_id + 1 == vlan_id:
            # 连续 ID
            last_id = vlan_id
        else:
            # 重置连续 ID
            if last_id == -1:
                pass
            elif last_id == start_id:
                # 单个值
                out.append(str(last_id))
            else:
                # 范围
                out.append(F"{start_id}-{last_id}")
            start_id = vlan_id
            last_id = vlan_id

    # 处理最后一个元素
    if last_id == start_id:
        # 单个值
        out.append(str(last_id))
    else:
        # 范围
        out.append(F"{start_id}-{last_id}")

    # 打印结果
    print(",".join(out))

if __name__ == "__main__":
    main()

Rust

use std::collections::HashSet;
use std::io::{stdin, BufRead};

fn solution() {
    // 读取输入
    // 解析当前所有的 VLAN ID, 并存储到集合或者数组中
    // 然后移除指定的 ID
    // 最后新剩下的 ID 格式化输出
    let mut line = String::new();
    let ret = stdin().lock().read_line(&mut line);
    assert!(ret.is_ok());
    let mut id_set = HashSet::<u32>::new();
    for part in line.trim().split(",") {
        if part.contains("-") {
            let mut range_part = part.split("-");
            let start_id: u32 = range_part.next().unwrap().parse().unwrap();
            let end_id: u32 = range_part.next().unwrap().parse().unwrap();
            assert!(range_part.next().is_none());
            for vlan_id in start_id..=end_id {
                assert!((1..=4094).contains(&vlan_id));
                id_set.insert(vlan_id);
            }
        } else {
            let vlan_id: u32 = part.parse().unwrap();
            assert!((1..=4094).contains(&vlan_id));
            id_set.insert(vlan_id);
        }
    }
    assert!(!id_set.is_empty());
    line.clear();

    let ret = stdin().lock().read_line(&mut line);
    assert!(ret.is_ok());
    let removed_id: u32 = line.trim().parse().unwrap();

    id_set.remove(&removed_id);

    // 格式化输出
    // 先转换成列表, 再排序
    let mut id_list: Vec<u32> = id_set.into_iter().collect();
    id_list.sort_unstable();

    let mut start_id = u32::MAX;
    let mut last_id = u32::MAX;
    let mut out = Vec::new();
    for &vlan_id in &id_list {
        if vlan_id - 1 == last_id {
            // 连续 ID
            last_id = vlan_id;
        } else {
            // 重置连续 ID
            if last_id == u32::MAX {
                // 忽略
            } else if last_id == start_id {
                // 单个值
                out.push(last_id.to_string());
            } else {
                // 范围
                out.push(format!("{start_id}-{last_id}"));
            }
            start_id = vlan_id;
            last_id = vlan_id;
        }
    }

    // 处理最后一个元素
    if last_id == start_id {
        // 单个值
        out.push(last_id.to_string());
    } else {
        // 范围
        out.push(format!("{start_id}-{last_id}"));
    }

    // 打印结果
    println!("{}", out.join(","));
}

fn main() {
    solution();
}

C++

#include <iostream>
#include <string>
#include <sstream>
#include <unordered_set>
#include <vector>

int main() {
  // 读取输入
  // 解析当前所有的 VLAN ID, 并存储到集合或者数组中
  // 然后移除指定的 ID
  // 最后新剩下的 ID 格式化输出

  std::string line;
  std::getline(std::cin, line);

  std::vector<int> id_list;
  std::stringstream ss(line);

  std::getline(std::cin, line);
  const int removed_id = std::stoi(line);

  while (std::getline(ss, line, ',')) {
    std::cout << "line: " << line << std::endl;

    const int index = line.find('-');
    if (index == std::string::npos) {
      const int vlan_id = std::stoi(line);
      id_list.push_back(vlan_id);
    } else {
      const std::string start = line.substr(0, index);
      const int start_id = std::stoi(start);
      const std::string end = line.substr(index + 1);
      const int end_id = std::stoi(end);
      for (int vlan_id = start_id; vlan_id <= end_id; ++vlan_id) {
        id_list.push_back(vlan_id);
      }
    }
  }

  // 排序
  std::sort(id_list.begin(), id_list.end());

  // 移除指定的 ID
  auto removed_id_iter = std::find(id_list.begin(), id_list.end(), removed_id);
  if (removed_id_iter != id_list.end()) {
    id_list.erase(removed_id_iter);
  }

  int start_id = -1;
  int last_id = -1;
  std::vector<std::string> out;
  const size_t kBufLen = 64;
  char buf[kBufLen + 1];

  for (int vlan_id : id_list) {
    if (last_id + 1 == vlan_id) {
      // 连续 ID
      last_id = vlan_id;
    } else {
      // 重置连续 ID
      if (last_id == -1) {
        // pass
      } else if (last_id == start_id) {
        // 单个值
        out.push_back(std::to_string(start_id));
      } else {
        // 范围
        const int s_len = snprintf(buf, kBufLen, "%d-%d", start_id, last_id);
        out.emplace_back(buf, s_len);
      }
      start_id = vlan_id;
      last_id = vlan_id;
    }
  }

  // 处理最后一个元素
  if (last_id == start_id) {
    // 单个值
    out.push_back(std::to_string(start_id));
  } else{ 
    // 范围
    const int s_len = snprintf(buf, kBufLen, "%d-%d", start_id, last_id);
    out.emplace_back(buf, s_len);
  }

  for (int index = 0; index + 1 < out.size(); ++index) {
    std::cout << out[index] << ",";
  }
  std::cout << out[out.size() - 1] << std::endl;

  return 0;
}