Reputation: 186
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
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
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