Java Regex | HackerRank Solution

Java Regex | HackerRank Solution

Java Regex on HackerRank asks you to write one regular expression that accepts valid IPv4-style addresses and rejects everything else. It looks like a one-liner, and in the end it is, but getting there teaches you the most useful regex skill: describing a range of numbers (here 0 to 255) using only characters, because regex has no idea what a number is.

The same pattern shows up in real work when you validate form input or parse log files. And in interviews, "write a regex for an IP address" is a common follow-up when you mention regex on your resume, so it pays to understand each part instead of copying it.

Problem

Create a class named MyRegex (not public) with a String field called pattern. The pattern must match a string only if it is an IP address of the form A.B.C.D, where:

  • each of A, B, C and D is a number from 0 to 255,
  • each part has at most 3 characters,
  • leading zeros are allowed, so 000 and 034 are fine.

By these rules, 000.12.12.034 and 121.234.12.12 are valid, while 666.666.23.23 (parts above 255), 23.45.22.32. (trailing dot), 000.12.234.23.23 (five parts) and I.Am.not.an.ip are not.

Input: several lines, each one a string made of any ASCII characters. The locked code reads them one token at a time.

Output: for each string, the locked code prints true if it matches your pattern, else false.

Input:
000.12.12.034
121.234.12.12
23.45.12.56
00.12.123.123123.123
122.23
Hello.IP

Output:
true
true
true
false
false
false

Approach

Break the job into two parts: first write a pattern for one number from 0 to 255 (call it an octet), then join four of them with dots.

Step 1: one octet. Regex sees characters, not values, so split the range into groups that are easy to describe:

  • [01]?\d?\d covers 0 to 199. It is one to three digits, and if there are three, the first is 0 or 1. This also allows leading zeros like 0, 00, 034 and 199.
  • 2[0-4]\d covers 200 to 249.
  • 25[0-5] covers 250 to 255.

Put them together with alternation: ([01]?\d?\d|2[0-4]\d|25[0-5]). Nothing above 255 can match, and nothing longer than 3 characters can match.

Step 2: four octets. Join them with \.. The backslash matters. A plain . in regex means "any character", so without the backslash 1a2b3c4 passes as an IP address.

Step 3: whole string only. The locked code calls String.matches(), which only returns true if the entire string matches. So you do not need ^ and $ here. If you ever use Matcher.find() instead, add them. Without anchors, find() says yes to 9999.1.1.1, because it finds 99.1.1.1 sitting inside it (I checked this).

Dry run: 000.12.12.034 splits as 000 (first branch, starts with 0), 12, 12 and 034 (first branch again), so it is true. 122.23 has only two parts, so the four-part pattern cannot match: false. 00.12.123.123123.123 fails because 123123 has six digits and there are five parts.

Solution in Java

import java.util.Scanner;

class Solution {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            String ip = in.next();
            System.out.println(ip.matches(new MyRegex().pattern));
        }
        in.close();
    }
}

// Must NOT be public (only one public class per file on HackerRank)
class MyRegex {
    // One octet: 0-199 (with optional leading zeros), 200-249, or 250-255
    private static final String OCTET = "([01]?\\d?\\d|2[0-4]\\d|25[0-5])";

    // Four octets joined by literal dots
    public String pattern = OCTET + "\\." + OCTET + "\\." + OCTET + "\\." + OCTET;
}

In Java source code every regex backslash is written twice, so \d becomes "\\d" and \. becomes "\\.". Building the pattern from an OCTET constant keeps it readable. The older solution on this page used (...\\.){3} plus a trailing \\b. It was correct too (I compared both against 300,000 random strings and they agreed every time), the \\b just did nothing useful because matches() already checks the full string.

Besides the sample, I tested 255.255.255.255 (true), 256.1.1.1 (false), 1.2.3.4. (false), 0000.1.1.1 (false, four characters) and 1.2.3.04 (true).

Output

true
true
true
false
false
false

Complexity

Time: O(L) per input string of length L. The pattern is fixed and small, so backtracking stays bounded.

Space: O(1) extra. One small tip for real code: String.matches() compiles the pattern every time it is called. If you check thousands of strings, compile once with Pattern.compile and reuse it.

Common mistakes

  • Writing . instead of \\., which lets any character act as the separator.
  • Using \d{1,3} for each part. That accepts 999 and 666, which are not valid.
  • Putting 25[0-5] and 2[0-4]\d logic wrong, for example 2[0-5]\d, which lets 256 to 259 through.
  • Making the class public. HackerRank already has a public Solution class in the same file, and Java allows only one.

Next in the series: Java Regex 2 - Duplicate Words. Before that, see Pattern Syntax Checker.

Tip: try to solve the problem yourself before reading the solution. Use the code as a reference to check your approach, and make sure you understand why it works.

More HackerRank solutions All coding problems MCQ practice

Comments

Post a Comment

Answered 0/0Correct 0