This is an article analyzing a problem from the coding practice site LeeCode.
Problem link: LeetCode
The article is divided into several parts:

  • Problem description
  • Official examples
  • Thought process and solution methods

Problem Description

  1. Validate IP Address

Write a function to determine if a given input string is a valid IPv4 or IPv6 address.

An IPv4 address is represented in decimal format separated by dots, consisting of 4 decimal numbers ranging from 0 to 255, separated by “.” For example, 172.16.254.1;
Also, numbers in IPv4 cannot start with 0. For example, the address 172.16.254.01 is invalid.

An IPv6 address is represented by 8 groups of hexadecimal numbers, each group representing 16 bits. These groups are separated by “:”. For example, 2001:0db8:85a3:0000:0000:8a2e:0370:7334 is a valid address.
Leading zeros can be omitted, and letters can be uppercase or lowercase. Thus, 2001:db8:85a3:0:0:8A2E:0370:7334 is also a valid IPv6 address (i.e., ignoring leading zeros and case).

However, empty groups cannot be used to represent zero values in IPv6 such that “::” appears. For example, 2001:0db8:85a3::8A2E:0370:7334 is invalid.

Also, extra leading zeros are not allowed in IPv6 groups. For example, 02001:0db8:85a3:0000:0000:8a2e:0370:7334 is invalid.

Note: You may assume there are no extra spaces or special characters in the given string.

Official Examples

Example 1

Input: “172.16.254.1”

Output: “IPv4”

Explanation: This is a valid IPv4 address, so return “IPv4”.

Example 2

Input: “2001:0db8:85a3:0:0:8A2E:0370:7334”

Output: “IPv6”

Explanation: This is a valid IPv6 address, so return “IPv6”.

Example 3

Input: “256.256.256.256”

Output: “Neither”

Explanation: This address is neither a valid IPv4 nor IPv6 address.

Thought Process and Solution Method

The most straightforward method is to directly use Python’s built-in package for IP addresses: ipaddress
This package is designed to handle IPv4 and IPv6 addresses, very convenient for subnet and related operations. Since the problem requires verifying if the input is a valid IPv4 or IPv6, the ipaddress.ip_address method can easily solve this problem. See the official description:

'''
ipaddress.ip_address(address)
Return an IPv4Address or IPv6Address object depending on the IP address passed as argument. Either IPv4 or IPv6 addresses may be supplied; integers less than 2**32 will be considered to be IPv4 by default. A ValueError is raised if address does not represent a valid IPv4 or IPv6 address.

Simply put:  
Given an IP address string, this returns an IPv4 or IPv6 object. If invalid, raises ValueError.

>>>  
ipaddress.ip_address('192.168.0.1')  
IPv4Address('192.168.0.1')  
ipaddress.ip_address('2001:db8::')  
IPv6Address('2001:db8::')  
'''

So the validation code might be:

import ipaddress

class Solution:
    def validIPAddress(self, IP: str) -> str:
        try:
            addtype = type(ipaddress.ip_address(IP))
            if addtype == ipaddress.IPv4Address:
                return "IPv4"
            return "IPv6"

        except ValueError:
            return "Neither"

However, when submitting, this code fails because an address like “01.01.01.01” is considered valid IPv4 by ipaddress, but the problem states IPv4 numbers cannot start with zero.

“IPv4 numbers cannot start with 0”

Therefore, we should first split the IP address, verify parts manually, then use ipaddress for further validation.

Here is the adjusted code:

import ipaddress

class Solution:
    def validIPAddress(self, IP: str) -> str:
        try:
            addtype = type(ipaddress.ip_address(IP))
            if addtype == ipaddress.IPv4Address:
                for part in IP.split("."):
                    if len(part) > 1 and part[0] == "0":
                        return "Neither"
                return "IPv4"

            parts = IP.split(":")
            for part in parts:
                if len(part) > 4 or part == '':
                    return "Neither"
            return "IPv6"

        except ValueError:
            return "Neither"

After multiple debugging attempts, this code finally passes the tests.

Runtime: 40ms, Memory usage: 13.9MB

Summary

In fact, the ipaddress package can solve the problem directly, but since the problem adds some extra constraints, it adds some difficulty. Just fix errors step by step based on test feedback. Also, learning the ipaddress package is very useful for handling network addresses.