4
\$\begingroup\$

I solved the following problem on Hackerrank.

The challenge is to:

Parse HTML input and display the tags and attributes in lexicographically ascending order.

This is the input format:

2 //number of test cases/ lines of html
<p><a href="http://www.quackit.com/html/tutorial/html_links.cfm">Example Link</a></p>
<div class="more-info"><a href="http://www.quackit.com/html/examples/html_links_examples.cfm">More Link Examples...</a></div>

This is the output format:

tag-1:attribute-1,attribute-2,attribute-3....
tag-2:attribute-1,attribute-2,attribute-3....
tag-3:attribute-1,attribute-2,attribute-3....
...
tag-n:attribute-1,attribute-2,attribute-3....

Example solution:

a:href
div:class
p:

I am trying to get better at writing meaningful code for my solutions. Any comments/suggestions?

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

public class Solution {

private static StringBuilder htmlBuilder = new StringBuilder("");
private static Pattern rgxForTagAtEnd = Pattern.compile("(<[a-z0-9]+)$");
private static Pattern rgxForTagAtStart = Pattern.compile("^[a-z0-9]+");
private static Pattern rgxToExtractTags = Pattern.compile("(<[a-z]+[^>]*>)");
private static Pattern rgxToExtractTagName = Pattern.compile("(?:<)[a-z0-9]+");
private static Pattern rgxToExtractAttribute = Pattern.compile("[a-z]+(?:=[\"\'])");

public static boolean checkForBeginningOfTag(){
    Matcher beginningOfTag = rgxForTagAtEnd.matcher(htmlBuilder.toString());
    Boolean B = beginningOfTag.find();
    return B;
}

public static boolean doesTagEndInTheSameLine(String remainingHtml){
    Matcher endingOfTag = rgxForTagAtStart.matcher(remainingHtml);
    Boolean B = endingOfTag.find();
    return B;
}

public static void printTagsAndAttributes(){
    Matcher M = rgxToExtractTags.matcher(htmlBuilder.toString());
    Map<String,TreeSet<String>> tagsAndAttributes = new TreeMap<String,TreeSet<String>>();
    while(M.find()){
        String tag = M.group();
        Matcher tagName = rgxToExtractTagName.matcher(tag);
        Matcher attrName = rgxToExtractAttribute.matcher(tag);
        TreeSet<String> attributes = new TreeSet<String>();
        while(attrName.find()){
            attributes.add(attrName.group(0));
        }
        while(tagName.find()){
            String nameOfTag = tagName.group(0);
            if(tagsAndAttributes.containsKey(nameOfTag)){
                TreeSet<String> tmpSet = new TreeSet<String>(tagsAndAttributes.get(nameOfTag));
                tmpSet.addAll(attributes);
                tagsAndAttributes.put(nameOfTag,tmpSet);
            }else{
                tagsAndAttributes.put(tagName.group(),attributes);
            }
        }
    }

    for(String tag: tagsAndAttributes.keySet()){
        String result = "";
        result = result + tag.substring(1,tag.length()) + ":";
        for(String attribute: tagsAndAttributes.get(tag)){
            result+=attribute.substring(0,attribute.length()-2)+",";
        }
        if(result.charAt(result.length()-1) == ','){
            System.out.print(result.substring(0,result.length()-1));
        }else{
            System.out.print(result);
        }
        System.out.println();
    }
}

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int T = scanner.nextInt();
    scanner.nextLine();
    for(int i=0;i<T;i++){
        if(scanner.hasNextLine()){
            String nextLine = scanner.nextLine();
            if(checkForBeginningOfTag()){
                if(!doesTagEndInTheSameLine(nextLine)){
                    htmlBuilder.append(" ");
                }
            }
            htmlBuilder.append(nextLine);
        }
    }

    printTagsAndAttributes();
}
}
\$\endgroup\$
0
1
\$\begingroup\$

Single-character variable names when used outside of 'traditional' loop constructs (e.g. i, j) or lambda bodies are bad not recommended, U(ppercase) case ones especially more so as they can get easily be confused with class names or generic type declaration (the usage most often seen). Therefore, please give better names to Matcher M and int T.

public static boolean doesTagEndInTheSameLine(String remainingHtml){
    Matcher endingOfTag = rgxForTagAtStart.matcher(remainingHtml);
    Boolean B = endingOfTag.find();
    return B;
}

I think a primitive boolean will do here. The whole method body can be simplified to just:

public static boolean doesTagEndInTheSameLine(String remainingHtml) {
    return rgxForTagAtStart.matcher(remainingHtml).find();
}

One more thing: You can do with more white spaces between operators...

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.