Open In App

Justify the given Text based on the given width of each line

Given a string str and width of each line as L, the task is to justify the string such that each line of justified text is of length L with help of space (‘ ‘) and the last line should be left-justified. Examples:

Input: str = “GeeksforGeeks is the best computer science portal for geeks.”, L = 16 Output: GeeksforGeek__is the_________best computer_science portal_______for geeks.__________ Input: str = “The quick brown fox jumps over the lazy dog.”, L = 11 Output: The___quick brown___fox jumped_over the____lazy dogs.______ The symbol _ denotes a space.

Approach: The number of spaces between words in each line cannot be computed until a complete set of words in that line is known. We will solve this problem on a line-by-line basis.

  1. Split the given text into words
  2. Firstly select the words which can be inserted in each line including a space between each word. For that, the sum of length of included words with one space between them must be smaller than or equal to L.
  3. Now count the number of spaces needed to make the length of each line L and distribute the spaces evenly.
  4. Repeat above steps for next set of words.
  5. For the last line spaces must be assigned at the end as the last line must be left-justified.

Below is the implementation of the above approach: 




// C++ program to Justify the given Text
// according to the given width of each line
#include <bits/stdc++.h>
using namespace std;
 
// Function to join the words
// with spaces spread evenly
string JoinALineWithSpace(
    vector<string>& words,
    int start, int end,
    int num_spaces)
{
 
    // Number of words in current line
    int num_words_curr_line
        = end - start + 1;
 
    // String to store the justified text
    string line;
 
    for (int i = start; i < end; i++) {
 
        line += words[i];
        --num_words_curr_line;
 
        // Count number of current space needed
        int num_curr_space
            = ceil((double)(num_spaces)
                / num_words_curr_line);
 
        // Insert spaces in string line
        line.append(num_curr_space, ' ');
 
        // Delete the spaces inserted in line
        num_spaces -= num_curr_space;
    }
 
    // Insert word to string line
    line += words[end];
    line.append(num_spaces, ' ');
 
    // Return justified text
    return line;
}
 
// Function that justify the words of
// sentence of length of line L
vector<string> JustifyText(
    vector<string>& words,
    int L)
{
 
    int curr_line_start = 0;
    int num_words_curr_line = 0;
    int curr_line_length = 0;
 
    // To store the justified text
    vector<string> result;
 
    // Traversing the words array
    for (int i = 0; i < words.size(); i++) {
 
        // curr_line_start is the first word
        // in the current line, and i is
        // used to identify the last word
        ++num_words_curr_line;
 
        int lookahead_line_length
            = curr_line_length
            + words[i].size()
            + (num_words_curr_line - 1);
 
        // If by including the words length becomes L,
        // then that set of words is justified
        // and add the justified text to result
        if (lookahead_line_length == L) {
 
            // Justify the set of words
            string ans
                = JoinALineWithSpace(
                    words,
                    curr_line_start,
                    i,
                    i - curr_line_start);
 
            // Store the justified text in result
            result.emplace_back(ans);
 
            // Start the current line
            // with next index
            curr_line_start = i + 1;
 
            // num of words in the current line
            // and current line length set to 0
            num_words_curr_line = 0;
            curr_line_length = 0;
        }
 
        // If by including the words such that
        // length of words becomes greater than L,
        // then hat set is justified with
        // one less word and add the
        // justified text to result
        else if (lookahead_line_length > L) {
 
            // Justify the set of words
            string ans
                = JoinALineWithSpace(
                    words,
                    curr_line_start,
                    i - 1,
                    L - curr_line_length);
 
            // Store the justified text in result
            result.emplace_back(ans);
 
            // Current line set to current word
            curr_line_start = i;
 
            // Number of words set to 1
            num_words_curr_line = 1;
 
            // Current line length set
            // to current word length
            curr_line_length = words[i].size();
        }
 
        // If length is less than L then,
        // add the word to current line length
        else {
            curr_line_length
                += words[i].size();
        }
    }
 
    // Last line is to be left-aligned
    if (num_words_curr_line > 0) {
        string line
            = JoinALineWithSpace(
                words,
                curr_line_start,
                words.size() - 1,
                num_words_curr_line - 1);
 
        line.append(
            L - curr_line_length
                - (num_words_curr_line - 1),
            ' ');
 
        // Insert the last line
        // left-aligned to result
        result.emplace_back(line);
    }
 
    // Return result
    return result;
}
 
// Function to insert words
// of sentence
vector<string> splitWords(string str)
{
 
    vector<string> words;
    string a = "";
    for (int i = 0; str[i]; i++) {
 
        // Add char to string a
        // to get the word
        if (str[i] != ' ') {
            a += str[i];
        }
 
        // If a space occurs
        // split the words and
        // add it to vector
        else {
            words.push_back(a);
            a = "";
        }
    }
 
    // Push_back the last word
    // of sentence
    words.push_back(a);
 
    // Return the vector of
    // words extracted from
    // string
    return words;
}
 
// Function to print justified text
void printJustifiedText(vector<string>& result)
{
    for (auto& it : result) {
        cout << it << endl;
    }
}
 
// Function to call the justification
void justifyTheText(string str, int L)
{
 
    vector<string> words;
 
    // Inserting words from
    // given string
    words = splitWords(str);
 
    // Function call to
    // justify the text
    vector<string> result
        = JustifyText(words, L);
 
    // Print the justified
    // text
    printJustifiedText(result);
}
 
// Driver Code
int main()
{
    string str
        = "GeeksforGeeks is the best"
        " computer science portal"
        " for geeks.";
    int L = 16;
 
    justifyTheText(str, L);
 
    return 0;
}




import java.util.ArrayList;
 
public class TextJustification {
 
    // Function to join the words
    // with spaces spread evenly
    static String joinALineWithSpace(
            ArrayList<String> words,
            int start, int end,
            int num_spaces) {
 
        // Number of words in current line
        int num_words_curr_line
                = end - start + 1;
 
        // String to store the justified text
        StringBuilder line = new StringBuilder();
 
        for (int i = start; i < end; i++) {
 
            line.append(words.get(i));
            --num_words_curr_line;
 
            // Count number of current space needed
            int num_curr_space
                    = (int) Math.ceil((double) (num_spaces)
                    / num_words_curr_line);
 
            // Insert spaces in string line
            for (int j = 0; j < num_curr_space; j++) {
                line.append(' ');
            }
 
            // Delete the spaces inserted in line
            num_spaces -= num_curr_space;
        }
 
        // Insert word to string line
        line.append(words.get(end));
        for (int i = 0; i < num_spaces; i++) {
            line.append(' ');
        }
 
        // Return justified text
        return line.toString();
    }
 
    // Function that justifies the words of
    // sentence of length of line L
    static ArrayList<String> justifyText(
            ArrayList<String> words,
            int L) {
 
        int curr_line_start = 0;
        int num_words_curr_line = 0;
        int curr_line_length = 0;
 
        // To store the justified text
        ArrayList<String> result = new ArrayList<>();
 
        // Traversing the words array
        for (int i = 0; i < words.size(); i++) {
 
            // currLineStart is the first word
            // in the current line, and i is
            // used to identify the last word
            ++num_words_curr_line;
 
            int lookahead_line_length
                    = curr_line_length
                    + words.get(i).length()
                    + (num_words_curr_line - 1);
 
            // If by including the words length becomes L,
            // then that set of words is justified
            // and add the justified text to result
            if (lookahead_line_length == L) {
 
                // Justify the set of words
                String ans
                        = joinALineWithSpace(
                        words,
                        curr_line_start,
                        i,
                        i - curr_line_start);
 
                // Store the justified text in result
                result.add(ans);
 
                // Start the current line
                // with next index
                curr_line_start = i + 1;
 
                // num of words in the current line
                // and current line length set to 0
                num_words_curr_line = 0;
                curr_line_length = 0;
            }
 
            // If by including the words such that
            // length of words becomes greater than L,
            // then that set is justified with
            // one less word and add the
            // justified text to result
            else if (lookahead_line_length > L) {
 
                // Justify the set of words
                String ans
                        = joinALineWithSpace(
                        words,
                        curr_line_start,
                        i - 1,
                        L - curr_line_length);
 
                // Store the justified text in result
                result.add(ans);
 
                // Current line set to current word
                curr_line_start = i;
 
                // Number of words set to 1
                num_words_curr_line = 1;
 
                // Current line length set
                // to current word length
                curr_line_length = words.get(i).length();
            }
 
            // If length is less than L then,
            // add the word to current line length
            else {
                curr_line_length
                        += words.get(i).length();
            }
        }
 
        // Last line is to be left-aligned
        if (num_words_curr_line > 0) {
            StringBuilder line
                    = new StringBuilder(joinALineWithSpace(
                    words,
                    curr_line_start,
                    words.size() - 1,
                    num_words_curr_line - 1));
 
            line.append(
                    " ".repeat(
                            L - curr_line_length
                                    - (num_words_curr_line - 1)));
 
            // Insert the last line
            // left-aligned to result
            result.add(line.toString());
        }
 
        // Return result
        return result;
    }
 
    // Function to insert words
    // of sentence
    static ArrayList<String> splitWords(String str) {
 
        ArrayList<String> words = new ArrayList<>();
        StringBuilder a = new StringBuilder();
 
        for (char c : str.toCharArray()) {
 
            // Add char to string currentWord
            // to get the word
            if (c != ' ') {
                a.append(c);
            }
 
            // If a space occurs
            // split the words and
            // add it to vector
            else {
                words.add(a.toString());
                a = new StringBuilder();
            }
        }
 
        // Push_back the last word
        // of sentence
        words.add(a.toString());
 
        // Return the vector of
        // words extracted from
        // string
        return words;
    }
 
    // Function to print justified text
    static void printJustifiedText(ArrayList<String> result) {
        for (String line : result) {
            System.out.println(line);
        }
    }
 
    // Function to call the justification
    static void justifyTheText(String str, int L) {
 
        ArrayList<String> words;
 
        // Inserting words from
        // given string
        words = splitWords(str);
 
        // Function call to
        // justify the text
        ArrayList<String> result
                = justifyText(words, L);
 
        // Print the justified
        // text
        printJustifiedText(result);
    }
 
    // Driver Code
    public static void main(String[] args) {
        String str
                = "GeeksforGeeks is the best"
                + " computer science portal"
                + " for geeks.";
        int L = 16;
 
        justifyTheText(str, L);
    }
}
// This Code is Contributed by Yash Agarwal(yashagarwal2852002)




# Function to join the words
# with spaces spread evenly
def join_a_line_with_space(words, start, end, num_spaces):
    # Number of words in the current line
    num_words_curr_line = end - start + 1
 
    # String to store the justified text
    line = ""
 
    for i in range(start, end):
        line += words[i]
        num_words_curr_line -= 1
 
        # Count the number of current space needed
        num_curr_space = (num_spaces + num_words_curr_line - 1) // num_words_curr_line
 
        # Insert spaces in the string line
        line += " " * num_curr_space
 
        # Delete the spaces inserted in the line
        num_spaces -= num_curr_space
 
    # Insert the last word to the string line
    line += words[end]
    line += " " * num_spaces
 
    # Return justified text
    return line
 
 
# Function that justifies the words of
# a sentence of length of line L
def justify_text(words, L):
    curr_line_start = 0
    num_words_curr_line = 0
    curr_line_length = 0
 
    # To store the justified text
    result = []
 
    # Traversing the words array
    for i in range(len(words)):
        # curr_line_start is the first word
        # in the current line, and i is
        # used to identify the last word
        num_words_curr_line += 1
 
        lookahead_line_length = curr_line_length + len(words[i]) + (num_words_curr_line - 1)
 
        # If by including the words, the length becomes L,
        # then that set of words is justified
        # and add the justified text to result
        if lookahead_line_length == L:
            # Justify the set of words
            ans = join_a_line_with_space(words, curr_line_start, i, i - curr_line_start)
 
            # Store the justified text in the result
            result.append(ans)
 
            # Start the current line
            # with the next index
            curr_line_start = i + 1
 
            # num of words in the current line
            # and current line length set to 0
            num_words_curr_line = 0
            curr_line_length = 0
 
        # If by including the words such that
        # length of words becomes greater than L,
        # then that set is justified with
        # one less word and add the
        # justified text to result
        elif lookahead_line_length > L:
            # Justify the set of words
            ans = join_a_line_with_space(words, curr_line_start, i - 1, L - curr_line_length)
 
            # Store the justified text in the result
            result.append(ans)
 
            # Current line set to the current word
            curr_line_start = i
 
            # Number of words set to 1
            num_words_curr_line = 1
 
            # Current line length set
            # to the current word length
            curr_line_length = len(words[i])
 
        # If length is less than L then,
        # add the word to current line length
        else:
            curr_line_length += len(words[i])
 
    # Last line is to be left-aligned
    if num_words_curr_line > 0:
        line = join_a_line_with_space(words, curr_line_start, len(words) - 1, num_words_curr_line - 1)
 
        line += " " * (L - curr_line_length - (num_words_curr_line - 1))
 
        # Insert the last line
        # left-aligned to result
        result.append(line)
 
    # Return result
    return result
 
 
# Function to insert words
# of a sentence
def split_words(s):
    words = s.split()
    return words
 
 
# Function to print justified text
def print_justified_text(result):
    for line in result:
        print(line)
 
 
# Function to call the justification
def justify_the_text(s, L):
    # Inserting words from
    # the given string
    words = split_words(s)
 
    # Function call to
    # justify the text
    result = justify_text(words, L)
 
    # Print the justified
    # text
    print_justified_text(result)
 
 
# Driver Code
if __name__ == "__main__":
    s = "GeeksforGeeks is the best computer science portal for geeks."
    L = 16
 
    justify_the_text(s, L)




using System;
using System.Collections.Generic;
using System.Text;
 
public class TextJustification
{
    // Function to join the words
    // with spaces spread evenly
    static string JoinALineWithSpace(List<string> words, int start, int end, int num_spaces)
    {
        // Number of words in current line
        int num_words_curr_line = end - start + 1;
 
        // String to store the justified text
        StringBuilder line = new StringBuilder();
 
        for (int i = start; i < end; i++)
        {
            line.Append(words[i]);
            --num_words_curr_line;
 
            // Count number of current space needed
            int num_curr_space = (int)Math.Ceiling((double)(num_spaces) / num_words_curr_line);
 
            // Insert spaces in string line
            for (int j = 0; j < num_curr_space; j++)
            {
                line.Append(' ');
            }
 
            // Delete the spaces inserted in line
            num_spaces -= num_curr_space;
        }
 
        // Insert word to string line
        line.Append(words[end]);
        for (int i = 0; i < num_spaces; i++)
        {
            line.Append(' ');
        }
 
        // Return justified text
        return line.ToString();
    }
 
    // Function that justifies the words of
    // sentence of length of line L
    static List<string> JustifyText(List<string> words, int L)
    {
        int curr_line_start = 0;
        int num_words_curr_line = 0;
        int curr_line_length = 0;
 
        // To store the justified text
        List<string> result = new List<string>();
 
        // Traversing the words array
        for (int i = 0; i < words.Count; i++)
        {
            // currLineStart is the first word
            // in the current line, and i is
            // used to identify the last word
            ++num_words_curr_line;
 
            int lookahead_line_length = curr_line_length + words[i].Length + (num_words_curr_line - 1);
 
            // If by including the words length becomes L,
            // then that set of words is justified
            // and add the justified text to result
            if (lookahead_line_length == L)
            {
                // Justify the set of words
                string ans = JoinALineWithSpace(words, curr_line_start, i, i - curr_line_start);
 
                // Store the justified text in result
                result.Add(ans);
 
                // Start the current line
                // with the next index
                curr_line_start = i + 1;
 
                // num of words in the current line
                // and current line length set to 0
                num_words_curr_line = 0;
                curr_line_length = 0;
            }
            // If by including the words such that
            // length of words becomes greater than L,
            // then that set is justified with
            // one less word and add the
            // justified text to result
            else if (lookahead_line_length > L)
            {
                // Justify the set of words
                string ans = JoinALineWithSpace(words, curr_line_start, i - 1, L - curr_line_length);
 
                // Store the justified text in result
                result.Add(ans);
 
                // Current line set to current word
                curr_line_start = i;
 
                // Number of words set to 1
                num_words_curr_line = 1;
 
                // Current line length set
                // to current word length
                curr_line_length = words[i].Length;
            }
            // If length is less than L then,
            // add the word to current line length
            else
            {
                curr_line_length += words[i].Length;
            }
        }
 
        // Last line is to be left-aligned
        if (num_words_curr_line > 0)
        {
            StringBuilder line =
              new StringBuilder(JoinALineWithSpace(words, curr_line_start,
                                                   words.Count - 1, num_words_curr_line - 1));
 
            line.Append(" ".PadRight(L - curr_line_length - (num_words_curr_line - 1)));
 
            // Insert the last line
            // left-aligned to result
            result.Add(line.ToString());
        }
 
        // Return result
        return result;
    }
 
    // Function to insert words
    // of sentence
    static List<string> splitWords(string str)
    {
        List<string> words = new List<string>();
        StringBuilder currentWord = new StringBuilder();
 
        foreach (char c in str)
        {
            // Add char to string currentWord
            // to get the word
            if (c != ' ')
            {
                currentWord.Append(c);
            }
            // If a space occurs
            // split the words and
            // add it to vector
            else
            {
                words.Add(currentWord.ToString());
                currentWord = new StringBuilder();
            }
        }
 
        // Add the last word of the sentence
        words.Add(currentWord.ToString());
 
        // Return the list of
        // words extracted from
        // string
        return words;
    }
 
    // Function to print justified text
    static void printJustifiedText(List<string> result)
    {
        foreach (string line in result)
        {
            Console.WriteLine(line);
        }
    }
 
    // Function to call the justification
    static void justifyTheText(string str, int L)
    {
        List<string> words;
 
        // Inserting words from
        // given string
        words = splitWords(str);
 
        // Function call to
        // justify the text
        List<string> result = JustifyText(words, L);
 
        // Print the justified
        // text
        printJustifiedText(result);
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
        string str = "GeeksforGeeks is the best computer science portal for geeks.";
        int L = 16;
 
        justifyTheText(str, L);
    }
}
 
// This code is contributed by Yash Agarwal(yashagarwal2852002)




// Function to join the words
// with spaces spread evenly
function JoinALineWithSpace(words, start, end, num_spaces) {
    // Number of words in the current line
    let num_words_curr_line = end - start + 1;
 
    // String to store the justified text
    let line = '';
 
    for (let i = start; i < end; i++) {
        line += words[i];
        num_words_curr_line--;
 
        // Count number of current space needed
        let num_curr_space = Math.ceil(num_spaces / num_words_curr_line);
 
        // Insert spaces in string line
        line += ' '.repeat(num_curr_space);
 
        // Delete the spaces inserted in line
        num_spaces -= num_curr_space;
    }
 
    // Insert word to string line
    line += words[end];
    line += ' '.repeat(num_spaces);
 
    // Return justified text
    return line;
}
 
// Function that justifies the words of
// sentence of length of line L
function JustifyText(words, L) {
    let curr_line_start = 0;
    let num_words_curr_line = 0;
    let curr_line_length = 0;
 
    // To store the justified text
    const result = [];
 
    // Traversing the words array
    for (let i = 0; i < words.length; i++) {
        num_words_curr_line++;
 
        const lookahead_line_length = curr_line_length + words[i].length + (num_words_curr_line - 1);
 
        // If by including the words length becomes L,
        // then that set of words is justified
        // and add the justified text to result
        if (lookahead_line_length === L) {
            const ans = JoinALineWithSpace(words, curr_line_start, i, i - curr_line_start);
            result.push(ans);
 
            // Start the current line with the next index
            curr_line_start = i + 1;
            num_words_curr_line = 0;
            curr_line_length = 0;
        }
        // If by including the words such that
        // length of words becomes greater than L,
        // then that set is justified with
        // one less word and add the
        // justified text to result
        else if (lookahead_line_length > L) {
            const ans = JoinALineWithSpace(words, curr_line_start, i - 1, L - curr_line_length);
            result.push(ans);
 
            // Current line set to current word
            curr_line_start = i;
            num_words_curr_line = 1;
            curr_line_length = words[i].length;
        }
        // If length is less than L then,
        // add the word to current line length
        else {
            curr_line_length += words[i].length;
        }
    }
 
    // Last line is to be left-aligned
    if (num_words_curr_line > 0) {
        let line = JoinALineWithSpace(words, curr_line_start, words.length - 1, num_words_curr_line - 1);
        line += ' '.repeat(L - curr_line_length - (num_words_curr_line - 1));
 
        // Insert the last line left-aligned to result
        result.push(line);
    }
 
    // Return result
    return result;
}
 
// Function to insert words
// of sentence
function splitWords(str) {
    const words = [];
    let a = '';
    for (let i = 0; str[i]; i++) {
 
        // Add char to string a
        // to get the word
        if (str[i] !== ' ') {
            a += str[i];
        }
 
        // If a space occurs
        // split the words and
        // add it to vector
        else {
            words.push(a);
            a = '';
        }
    }
 
    // Push back the last word
    // of sentence
    words.push(a);
 
    // Return the vector of
    // words extracted from
    // string
    return words;
}
 
// Function to print justified text
function printJustifiedText(result) {
    for (const it of result) {
        console.log(it);
    }
}
 
// Function to call the justification
function justifyTheText(str, L) {
 
    let words;
 
    // Inserting words from
    // given string
    words = splitWords(str);
 
    // Function call to
    // justify the text
    const result = JustifyText(words, L);
 
    // Print the justified
    // text
    printJustifiedText(result);
}
 
// Driver Code
const str = "GeeksforGeeks is the best computer science portal for geeks.";
const L = 16;
 
justifyTheText(str, L);

Output
GeeksforGeeks is
the         best
computer science
portal       for
geeks.          

Time Complexity: O(N), where N = length of string


Article Tags :