5
\$\begingroup\$

I am working my way through some exercises, using Java, to learn about programming. I have just finished the following Code Golf challenge:

Here is some example input, so I can explain what the problem is:

((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))

Think of this line of text as a topographic map of some mountains. Each set of parentheses illustrates one unit of altitude.

If we "view" this from the side, so that we see the mountains vertically, we will see:

         4 5                cherries    woohoo  
  1 2  3       moo       lik          e
                      i

Given one of these topographic maps, output the map, but on a vertical scale, like the output above. Separate the different items in the map with the number of characters to the next item. For example, there are 4 spaces in the output between moo and i. Likewise, there are 4 characters in the input between moo and i.

As a beginner, I am certainly not aiming to fulfill the challenge of the fewest characters. I'm merely trying to learn. I haven't looked at any other answers yet in case it puts me off posting this for feedback. So, here is my code:

public static String getLevelContent(String str, int count){

    int levelToPrint = 0;
    int spaceCount = -1;

    StringBuilder s = new StringBuilder();

    for (int i = 0; i < str.length(); i++) {

        spaceCount++;

        if (str.charAt(i) == '(') {
            levelToPrint++;
        }

        if (str.charAt(i) == ')') {
            levelToPrint--;
        }

        if (levelToPrint == count && str.charAt(i) != '(' && str.charAt(i) != ')') {

            for (int j = 0; j < spaceCount; j++) {
                s.append(" ");
            }

            spaceCount = -1;
            s.append(str.charAt(i));

        }
    }
    return s.toString();
}

public static void printTopographic(String str){

    for (int i = 3; i >= 1; i--) {
        System.out.println(getLevelContent(str, i));
    }
}

public static void main(String[] args) {

    String str = "((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))";
    printTopographic(str);
}

Output:

           4 5                cherries    woohoo
  1 2  3       moo       lik          e 
                      i 

I am largely trying to better my efforts of structuring code. My questions are:

  1. The reason I made getLevelContent a separate method is to avoid multiple for loops for each level of the output (3, 2, and 1). Is separating into methods, as I have done here, a good way to solve the problem?
  2. In the printTopographic method, is the for loop more necessary, or more readable, than three separate lines, each calling separately on its own? (I suppose with this loop in place it would be more useful for dozens of lines as opposed to just three.)
  3. Are there parts of my code which are just plain inefficient and should/would generally be written in a different way?
  4. In projects like this, where I am simply testing what happens and how, I have completely gotten used to labeling static methods, pretty much out of laziness than anything else (for when calling from other methods). Is this a bad habit?
\$\endgroup\$
3
\$\begingroup\$
  1. The reason I made getLevelContent a separate method is to avoid multiple for loops for each level of the output (3, 2, and 1). Is separating into methods, as I have done here, a good way to solve the problem?

If it works, it works. You said this is codegolf, so in the end you'll need to determine if it's worth it character-wise to use "extra" methods. Take a look at my response to point 2 and 3 though.

Apart form code golf though, I think "extra" methods help readability. By "extra" methods I mean private methods that are only used once. A better name may be superfluous methods. Say you have some long code that does something easy to understand but you only use it once in one method so it doesn't immediately make sense to extract it to its own method, if it makes the code more readable then I'd suggest extracting it.


  1. In the printTopographic method, is the for loop more necessary, or more readable, than three separate lines, each calling separately on its own? (I suppose with this loop in place it would be more useful for dozens of lines as opposed to just three.)

A for-loop is better than a separate method call for each line, in fact I'd say a separate call for each line is wrong, see the next one though.


  1. Are there parts of my code which are just plain inefficient and should/would genereally be written in a different way?

What happens if the input is (1(2(3(4))))? I don't think it's good to hard code the number of levels. Just because the example has three levels doesn't mean every input will have 3 levels. So if you want to do this right I would do something like putting the '(' on a stack to tell what level you are on, the highest number of '(' on the stack is the total number of levels, plus one if 1(2) is allowed. Pop '(' when ')' is met. Look up stuff on converting infix notation (3 * (1 + 2))) to postfix (1 2 + 3 *) for hints on how to do this.


  1. In projects like this, where I am simply testing what happens and how, I have completely gotten used to labelling static methods, pretty much out of laziness than anything else (for when calling from other methods). Is this a bad habit?

It's more important to understand what the difference between a static method and non-static method is than worrying about always using static in small projects like this.

A method being static means a few things, first is

  • static methods are on the class itself, not an instantiated object

and because of that

  • static methods are the same across all instances of the object

which may or may not matter depending on the context. (If you have what should be a "utility class" then it shouldn't be instantiated, see this where I explain what a utility class is.)

For small projects like this that are, for lack of a better term, more like making a script than a large program, most of the methods will end up being able to be static. So if you are making them static because they can be static then you are doing fine. In my opinion if a method can be static it should be static. If you are making them static because you have an obsession with static methods then you're probably missing something. static is not preferable to non-static if you need to do something related to the instance of the object. Perfect example, the idea of getters and setters...

class NumberHolder {
    static int num;
    public static int getNum() { 
        return num;
    }
    public static void setNum(int num) {
        this.num = num;
    }
}

// ...

// numberHolders is a List<NumberHolder> with size 10
for (int i = 0; i < numberHolders.size(); i++) {
    numberHolders.get(i).setNum(i);
}
for (int i = 0; i < numberHolders.size(); i++) {
    System.out.println()numberHolders.get(i).getNum(i));
}

will output

9
9
9
9
9
9
9
9
9
9

Which, depending on the context and the problem might be what you want to happen, but personally seeing something like that I would expect

0
1
2
3
4
5
6
7
8
9
\$\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.