Column Aligned Table

medium Files and I/O

Problem

Every input line is a row of words separated by spaces. Print the rows as a table: the cells of a column are padded on the right with spaces to the width of the widest cell in that column, and the cells of a row are joined with the text ' | '. The last cell of every row is not padded. Rows may have different numbers of cells.

Constraints

  • 1 <= rows <= 1000
  • words have no spaces

Examples

Input

name age
amit 20
bela 7

Output

name | age
amit | 20
bela | 7

Solutions

Best approachTime O(total characters)Space O(n)

We cannot write the first row before we know the widest cell of a column, so the table is read twice: once to measure and once to print.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process lines.
 * Input   : Several lines.
 * Output  : The formatted rows.
 * Approach: Two passes over the rows.
 * Time    : O(total characters)
 * Space   : O(n)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        // Step 1: First pass: find the widest cell of every column.
        String[][] rows = new String[lines.length][];
        int columns = 0;
        for (int i = 0; i < lines.length; i++) {
            rows[i] = lines[i].split("\\s+");
            columns = Math.max(columns, rows[i].length);
        }
        int[] widths = new int[columns];
        for (String[] row : rows) {
            for (int c = 0; c < row.length; c++) {
                widths[c] = Math.max(widths[c], row[c].length());
            }
        }
        // Step 2: Second pass: write every cell, padded to its column width. The last cell of a row is not padded.
        String[] output = new String[lines.length];
        for (int i = 0; i < rows.length; i++) {
            StringBuilder line = new StringBuilder();
            for (int c = 0; c < rows[i].length; c++) {
                if (c > 0) {
                    line.append(" | ");
                }
                line.append(rows[i][c]);
                if (c < rows[i].length - 1) {
                    for (int pad = rows[i][c].length(); pad < widths[c]; pad++) {
                        line.append(' ');
                    }
                }
            }
            output[i] = line.toString();
        }
        return output;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        java.util.List<String> all = new java.util.ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (!line.isEmpty()) {
                all.add(line);
            }
        }
        String[] lines = all.toArray(new String[0]);
        System.out.println(String.join("\n", solve(lines)));
    }
}
Hints (2)
  1. Why are two passes needed?
  2. Why is the last cell not padded?