Gabriel Rufino
Gabriel Rufino

Reputation: 186

Java adding whitespace to whitespace

I have a small problem that looks unsolvable:

GOAL: Justify lines (strings) in an ArrayList, by adding whitespaces to single whitespace characters, as much as needed for the text to get justified.

package com.mycompany.app;

import java.util.ArrayList; import java.util.List;

public class MaxLengthLine {

String[] words;
int size;
int qtySpaces;
public MaxLengthLine (String text, int size){
    this.words = text.split(" ");
    this.size = size;
}
List<String> lines = new ArrayList<String>();
public void lineResize() {


    int index = 0;
    for (int i = 0; i < words.length - index; i++){
        String curLine = "";
    while((curLine + words[index]).length() <= size){
        curLine += words[index] + " ";
        index++;
    }

    curLine = curLine.substring(0, curLine.length()-1);
    lines.add(curLine);
    }

    String curLine = "";
    while(index < words.length){
        curLine += words[index] + " ";
        index++;
    }

    curLine = curLine.substring(0, curLine.length()-1);
    lines.add(curLine);

}

public void lineJustify() {
    for (int i = 0; i < lines.size(); i++){
        while (lines.get(i).length() < size){
            String test = lines.get(i).replaceFirst(" ", "  ");

            lines.set(i, test);
        }
    }
}

public String getTextFull (){
    String output = "";
    for(int i = 0; i < lines.size();i++){
        output += lines.get(i) + "\n";
    }
    while (output.contains("  ")){
        output = output.replace("  ", " ");
    }
    return output;
}

}

This code is the most straightfoward solution I thought at first (besides I have already tried plenty of others), but for some reason the result keeps coming the same.

Actual output:

In the beginning God created the heavens
and the earth. Now the earth was
formless and empty, darkness was over
the surface of the deep, and the Spirit
of God was hovering over the waters.

And God said, "Let there be light," and
there was light. God saw that the light
was good, and he separated the light
from the darkness. God called the light
"day," and the darkness he called
"night." And there was evening, and
there was morning - the first day.

Desired output:

In the beginning God created the heavens
and   the  earth.   Now  the  earth  was
formless  and empty,  darkness was  over
the  surface of the deep, and the Spirit
of  God was  hovering over  the  waters.

And  God said, "Let there be light," and
there  was light. God saw that the light
was  good, and  he separated  the  light
from  the darkness. God called the light
"day,"   and  the   darkness  he  called
"night."  And  there  was  evening,  and
there  was  morning  -  the  first  day.

Edit: The input:

In the beginning God created the heavens and the earth. Now the earth was formless and empty, darkness was over the surface of the deep, and the Spirit of God was hovering over the waters. And God said, "Let there be light," and there was light. God saw that the light was good, and he separated the light from the darkness. God called the light "day," and the darkness he called "night." And there was evening, and there was morning - the first day.

(I already have code that breaks lines correctly at 40 chars without breaking words, so the last part is that function to justify the text to 40 chars)

EDIT 2: I changed that piece of code for the whole class to be more clear, the size being set on my teste is 40.

Upvotes: 0

Views: 490

Answers (2)

Kirill Simonov
Kirill Simonov

Reputation: 8481

public static List<String> justifyLines(String input, int lineLength) {
    String[] words = input.split(" ");
    List<String> result = new ArrayList<>();
    StringBuilder line = new StringBuilder();
    //here we store positions of all spaces in the current line to add more spaces there
    List<Integer> spacesPositions = new ArrayList<>();
    for (String word : words) {
        if (word.length() <= lineLength - line.length()) {
            line.append(word).append(" ");
            spacesPositions.add(line.length() - 1);
        } else {
            result.add(justifyLine(line, lineLength, spacesPositions));
            line.setLength(0);
            spacesPositions.clear();
            line.append(word).append(" ");
            spacesPositions.add(line.length() - 1);
        }
    }
    if (line.length() > 0) {
        result.add(justifyLine(line, lineLength, spacesPositions));
    }
    return result;
}

private static String justifyLine(StringBuilder line, int lineLength, List<Integer> spacesPositions) {
    //if line ends with space - remove it
    if (line.lastIndexOf(" ") == line.length() - 1) line.setLength(line.length() - 1);
    int spacesToAdd = lineLength - line.length();
    for (int j = 0; j < spacesToAdd; j++) {
        //It's the most complicated part, but I'll try to explain
        line.insert(
                // We're adding one space to each space in the line and then, if there are still spaces to insert,
                // repeating this process from the beginning - that's why we're using %
                spacesPositions.get(j % (spacesPositions.size() - 1))
                        // But each time we insert a new space, we need to take it into account for the following positions
                        // j % (spacesPositions.size() - 1) is the number of space in the line
                        // j / (spacesPositions.size() - 1) + 1 is the iteration number
                        + j % (spacesPositions.size() - 1) * (j / (spacesPositions.size() - 1) + 1), " ");
    }
    return line.toString();
}

So for (String s : justifyLines("In the beginning...", 40)) System.out.println(s); prints:

In the beginning God created the heavens
and   the   earth.  Now  the  earth  was
formless  and  empty,  darkness was over
the  surface of the deep, and the Spirit
of God was hovering over the waters. And
God  said,  "Let  there  be  light," and
there  was light. God saw that the light
was  good,  and  he  separated the light
from  the darkness. God called the light
"day,"   and   the  darkness  he  called
"night."  And  there  was  evening,  and
there  was  morning  -  the  first  day.

Upvotes: 1

Kyung Song
Kyung Song

Reputation: 36

From Java String class:

public String replaceFirst(String regex, String replacement)

Replaces the first substring of this string that matches the given regular expression with the given replacement.

So you need to give it a regex, not the space itself. In java regex for a whitespace is "\s"

String test = lines.get(i).replaceFirst("\\s", " ");

Also, as something to consider, replaceFirst only replaces the first substring that matches the regex, so this code will add whitespace only to the first whitespace you find, not evenly distributed like you want it to be (because the first space of the double space " " will still match to the regex "\s".)

Do check on this.

Upvotes: 0

Related Questions