Align columns

From Rosetta Code
(Redirected from Column Aligner)
Jump to: navigation, search
Task
Align columns
You are encouraged to solve this task according to the task description, using any language you may know.

Given a text file of many lines, where fields within a line are delineated by a single 'dollar' character, write a program that aligns each column of fields by ensuring that words in each column are separated by at least one space. Further, allow for each word in a column to be either left justified, right justified, or center justified within its column.


Use the following text to test your programs:

Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.

Note that:

  1. The example input texts lines may, or may not, have trailing dollar characters.
  2. All columns should share the same alignment.
  3. Consecutive space characters produced adjacent to the end of lines are insignificant for the purposes of the task.
  4. Output text will be viewed in a mono-spaced font on a plain text editor or basic terminal.
  5. The minimum space between columns should be computed from the text and not hard-coded.
  6. It is not a requirement to add separating characters between or around columns.

Contents

[edit] ABAP

report z_align no standard page header.
start-of-selection.
 
data: lt_strings type standard table of string,
lv_strings type string.
append: 'Given$a$text$file$of$many$lines,$where$fields$within$a$line$' to lt_strings,
'are$delineated$by$a$single$''dollar''$character,$write$a$program' to lt_strings,
'that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$' to lt_strings,
'column$are$separated$by$at$least$one$space.' to lt_strings,
'Further,$allow$for$each$word$in$a$column$to$be$either$left$' to lt_strings,
'justified,$right$justified,$or$center$justified$within$its$column.' to lt_strings.
types ty_strings type standard table of string.
 
perform align_col using 'LEFT' lt_strings.
skip.
perform align_col using 'RIGHT' lt_strings.
skip.
perform align_col using 'CENTER' lt_strings.
 
 
form align_col using iv_just type string iv_strings type ty_strings.
constants: c_del value '$'.
data: lv_string type string,
lt_strings type table of string,
lt_tables like table of lt_strings,
lv_first type string,
lv_second type string,
lv_longest type i value 0,
lv_off type i value 0,
lv_len type i.
" Loop through the supplied text. It is expected at the input is a table of strings, with each
" entry in the table representing a new line of the input.
loop at iv_strings into lv_string.
" Split the current line at the delimiter.
split lv_string at c_del into lv_first lv_second.
" Loop through the line splitting at every delimiter.
do.
append lv_first to lt_strings.
lv_len = strlen( lv_first ).
" Check if the length of the new string is greater than the currently stored length.
if lv_len > lv_longest.
lv_longest = lv_len.
endif.
if lv_second na c_del.
" Check if the string is longer than the recorded maximum.
lv_len = strlen( lv_second ).
if lv_len > lv_longest.
lv_longest = lv_len.
endif.
append lv_second to lt_strings.
exit.
endif.
split lv_second at c_del into lv_first lv_second.
enddo.
 
append lt_strings to lt_tables.
clear lt_strings.
endloop.
 
" Loop through each line of input.
loop at lt_tables into lt_strings.
" Loop through each word in the line (Separated by specified delimiter).
loop at lt_strings into lv_string.
lv_off = ( sy-tabix - 1 ) * ( lv_longest + 2 ).
case iv_just.
when 'LEFT'.
write : at (lv_longest) lv_string left-justified.
when 'RIGHT'.
write at (lv_longest) lv_string right-justified.
when 'CENTER'.
write at (lv_longest) lv_string centered.
endcase.
endloop.
skip.
sy-linno = sy-linno - 1.
endloop.
endform.
Given      a          text       file       of         many       lines,     where      fields     within     a          line
are        delineated by         a          single     'dollar'   character, write      a          program
that       aligns     each       column     of         fields     by         ensuring   that       words      in         each
column     are        separated  by         at         least      one        space.
Further,   allow      for        each       word       in         a          column     to         be         either     left
justified, right      justified, or         center     justified  within     its        column.

     Given          a       text       file         of       many     lines,      where     fields     within          a       line
       are delineated         by          a     single   'dollar' character,      write          a    program
      that     aligns       each     column         of     fields         by   ensuring       that      words         in       each
    column        are  separated         by         at      least        one     space.
  Further,      allow        for       each       word         in          a     column         to         be     either       left
justified,      right justified,         or     center  justified     within        its    column.

  Given        a         text       file        of        many      lines,     where      fields     within       a         line
   are     delineated     by         a        single    'dollar'  character,   write        a       program
   that      aligns      each      column       of       fields       by      ensuring     that      words        in        each
  column      are     separated      by         at       least       one       space.
 Further,    allow       for        each       word        in         a        column       to         be       either      left
justified,   right    justified,     or       center   justified    within      its      column.

[edit] Ada

with Ada.Characters.Latin_1;  use Ada.Characters.Latin_1;
with Ada.Text_IO; use Ada.Text_IO;
with Strings_Edit; use Strings_Edit;
 
procedure Column_Aligner is
Text : constant String :=
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$" & NUL &
"are$delineated$by$a$single$'dollar'$character,$write$a$program" & NUL &
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" & NUL &
"column$are$separated$by$at$least$one$space." & NUL &
"Further,$allow$for$each$word$in$a$column$to$be$either$left$" & NUL &
"justified,$right$justified,$or$center$justified$within$its$column." & NUL;
File  : File_Type;
Width  : array (1..1_000) of Natural := (others => 0);
Line  : String (1..200);
Column  : Positive := 1;
Start  : Positive := 1;
Pointer : Positive;
begin
Create (File, Out_File, "columned.txt");
-- Determining the widths of columns
for I in Text'Range loop
case Text (I) is
when '$' | NUL =>
Width (Column) := Natural'Max (Width (Column), I - Start + 1);
Start  := I + 1;
if Text (I) = NUL then
Column := 1;
else
Column := Column + 1;
end if;
when others =>
null;
end case;
end loop;
-- Formatting
for Align in Alignment loop
Column  := 1;
Start  := 1;
Pointer := 1;
for I in Text'Range loop
case Text (I) is
when '$' | NUL =>
Put -- Formatted output of a word
( Destination => Line,
Pointer => Pointer,
Value => Text (Start..I - 1),
Field => Width (Column),
Justify => Align
);
Start  := I + 1;
if Text (I) = NUL then
Put_Line (File, Line (1..Pointer - 1));
Pointer := 1;
Column := 1;
else
Column := Column + 1;
end if;
when others =>
null;
end case;
end loop;
end loop;
Close (File);
end Column_Aligner;

Formatted file sample:

Given      a          text       file   of     many      lines,     where    fields  within  a      line  
are        delineated by         a      single 'dollar'  character, write    a       program 
that       aligns     each       column of     fields    by         ensuring that    words   in     each  
column     are        separated  by     at     least     one        space.   
Further,   allow      for        each   word   in        a          column   to      be      either left  
justified, right      justified, or     center justified within     its      column. 
      Given          a       text   file     of      many     lines,    where  fields  within      a line 
        are delineated         by      a single  'dollar' character,    write       a program
       that     aligns       each column     of    fields         by ensuring    that   words     in each 
     column        are  separated     by     at     least        one   space.
   Further,      allow        for   each   word        in          a   column      to      be either left 
 justified,      right justified,     or center justified     within      its column.
   Given        a        text     file    of      many     lines,     where   fields  within    a   line  
    are    delineated     by        a   single  'dollar' character,   write     a    program 
   that      aligns      each    column   of     fields      by     ensuring   that   words    in   each  
  column       are     separated   by     at     least       one     space.  
 Further,     allow       for     each   word      in         a      column     to      be   either left  
justified,    right   justified,   or   center justified   within      its   column. 

[edit] ALGOL 68

STRING nl = REPR 10;
STRING text in list := "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"+nl+
"are$delineated$by$a$single$'dollar'$character,$write$a$program"+nl+
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"+nl+
"column$are$separated$by$at$least$one$space."+nl+
"Further,$allow$for$each$word$in$a$column$to$be$either$left$"+nl+
"justified,$right$justified,$or$center$justified$within$its$column.";
 
MODE PAGE = FLEX[0,0]STRING;
PAGE page;
 
PROC flex page = (PAGE in page, INT row, col)PAGE:(
HEAP FLEX[row, col]STRING out page;
out page[:1 UPB in page, :2 UPB in page] := in page;
FOR r TO row DO
FOR c FROM 2 UPB in page + 1 TO col DO out page[r,c]:="" OD
OD;
FOR r FROM 1 UPB in page + 1 TO row DO
FOR c FROM 1 TO col DO out page[r,c]:="" OD
OD;
out page
);
 
FILE text in file;
associate(text in file, text in list);
make term(text in file, "$");
 
on physical file end(text in file, (REF FILE skip)BOOL: stop iteration);
on logical file end(text in file, (REF FILE skip)BOOL: stop iteration);
FOR row DO
on line end(text in file, (REF FILE skip)BOOL: stop iteration);
FOR col DO
STRING tok;
getf(text in file, ($gx$,tok));
IF row > 1 UPB page THEN page := flex page(page, row, 2 UPB page) FI;
IF col > 2 UPB page THEN page := flex page(page, 1 UPB page, col) FI;
page[row,col]:=tok
OD;
stop iteration:
SKIP
OD;
stop iteration:
SKIP;
 
BEGIN
PROC aligner = (PAGE in page, PROC (STRING,INT)STRING aligner)VOID:(
PAGE page := in page;
[2 UPB page]INT max width;
FOR col TO 2 UPB page DO
INT max len:=0; FOR row TO UPB page DO IF UPB page[row,col]>max len THEN max len:=UPB page[row,col] FI OD;
FOR row TO UPB page DO page[row,col] := aligner(page[row,col], maxlen) OD
OD;
printf(($n(UPB page)(n(2 UPB page -1)(gx)gl)$,page))
);
 
PROC left = (STRING in, INT len)STRING: in + " "*(len - UPB in),
right = (STRING in, INT len)STRING: " "*(len - UPB in) + in,
centre = (STRING in, INT len)STRING: ( INT pad=len-UPB in; pad%2*" "+ in + (pad-pad%2)*" " );
 
[]STRUCT(STRING name, PROC(STRING,INT)STRING align) aligners = (("Left",left), ("Left",right), ("Centre",centre));
 
FOR index TO UPB aligners DO
print((new line, "# ",name OF aligners[index]," Column-aligned output:",new line));
aligner(page, align OF aligners[index])
OD
END

[edit] AutoHotkey

lines = 
(
|$|$|$|$|$|$|$|$|$|$|$|
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
)
 
Clipboard := ColumnJustify(lines, "l")
 
MsgBox, , Column Justify, The clipboard now contains the justified text. Paste it into a text editor to see it.
 
ColumnJustify(lines, lcr = "l", del="$")
{
Loop, Parse, lines, `n, `r
Loop, Parse, A_LoopField, %del%
{
If ((t := StrLen(A_LoopField)) > c%A_Index% )
c%A_Index% := t
If (t > max)
max := t
}
blank := Fill( " ", max )
If (lcr = "l") ;left-justify
Loop, Parse, lines, `n, `r
Loop, Parse, A_LoopField, %del%
out .= (A_Index = 1 ? "`n" : " ") SubStr(A_LoopField blank, 1, c%A_Index%)
Else If (lcr = "r") ;right-justify
Loop, Parse, lines, `n, `r
Loop, Parse, A_LoopField, %del%
out .= (A_Index = 1 ? "`n" : " ") SubStr(blank A_LoopField, -c%A_Index%+1)
Else If (lcr = "c") ;center-justify
Loop, Parse, lines, `n, `r
Loop, Parse, A_LoopField, %del%
out .= (A_Index = 1 ? "`n" : " ") SubStr(blank A_LoopField blank
, (Ceil((max * 2 + StrLen(A_LoopField))/2) - Ceil(c%A_Index%/2) + 1)
, c%A_Index%)
return SubStr(out, 2)
}
 
Fill(chr, len)
{
static y
if !y
VarSetCapacity(x, 64), VarSetCapacity(x, 0), y := True
return x, VarSetCapacity(x, len, Asc(chr))
}

[edit] AutoIt

 
; == If the given text is in an file, it will read with:
#include <File.au3>
Global $aRead
_FileReadToArray($sPath, $aRead) ; == $aRead[0] includes count of lines, every line stored in one item (without linebreak)
 
; == For example we get the same result with StringSplit()
Global $sText = _
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$" & @CRLF & _
"are$delineated$by$a$single$'dollar'$character,$write$a$program" & @CRLF & _
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" & @CRLF & _
"column$are$separated$by$at$least$one$space." & @CRLF & _
"Further,$allow$for$each$word$in$a$column$to$be$either$left$" & @CRLF & _
"justified,$right$justified,$or$center$justified$within$its$column." & @CRLF
 
$aRead = StringSplit($sText, @CRLF, 1)
 
; == strip leading and trailing "$" and trailing spaces, count remaining "$" to get max column number
Global $iMaxColumn = 0, $iLines = 0
For $i = 1 To $aRead[0]
If $aRead[$i] = '' Then ContinueLoop ; skip empty lines
$iLines += 1
$aRead[$i] = StringRegExpReplace(StringRegExpReplace(StringRegExpReplace($aRead[$i], '^\$', ''), '\$$', ''), '\s*$', '')
StringReplace($aRead[$i], '$', '$')
If @extended +1 > $iMaxColumn Then $iMaxColumn = @extended +1
Next
 
; == build array to store all fields and length of every item
Global $aFields[$iLines][$iMaxColumn +1][2]
; == and store the max. length of item in columns
Global $aColLen[$iMaxColumn]
 
; == fill the array
Global $aSplitLine
$iLines = 0
For $i = 1 To $aRead[0]
If $aRead[$i] = '' Then ContinueLoop ; skip empty lines
$iMaxColLen = 0
$aSplitLine = StringSplit($aRead[$i], '$')
For $j = 1 To $aSplitLine[0]
$aFields[$iLines][$j-1][0] = $aSplitLine[$j]
$aFields[$iLines][$j-1][1] = StringLen($aSplitLine[$j])
If $aFields[$iLines][$j-1][1] > $aColLen[$j-1] Then $aColLen[$j-1] = $aFields[$iLines][$j-1][1]
Next
$iLines += 1
Next
 
; == let the user select the alignment for every column
$sAlign = InputBox('Column alignment', 'There are ' & $iMaxColumn & ' columns.' & @LF & '0 = left 1 = center 2 = right' & @LF & _
'Input alignment for all columns without delimiters.' & @LF & 'Let it empty, to align all left.')
If $sAlign = '' Then
For $i = 1 To $iMaxColumn
$sAlign &= '0'
Next
EndIf
Global $aAlignment = StringSplit($sAlign, '', 2)
 
; == output all to console
Global $sLineOut
For $i = 0 To UBound($aFields) -1
$sLineOut = ''
For $j = 0 To $iMaxColumn -1
If $aFields[$i][$j][0] = '' Then ContinueLoop
$sLineOut &= _GetAligned($aFields[$i][$j][0], $aFields[$i][$j][1], $aAlignment[$j], $aColLen[$j])
Next
ConsoleWrite(StringTrimRight($sLineOut, 1) & @LF)
Next
 
Func _GetAligned($_sString, $_iLen, $_iAlign, $_iMaxLen)
Local $sSpace = ''
For $i = 1 To $_iMaxLen
$sSpace &= ' '
Next
Switch $_iAlign
Case 0
Return $_sString & StringLeft($sSpace, $_iMaxLen - $_iLen +1)
Case 1
Local $iLenLeft = Int(($_iMaxLen - $_iLen)/2)
Local $iLenRight = $_iMaxLen - $iLenLeft - $_iLen
Return StringLeft($sSpace, $iLenLeft) & $_sString & StringLeft($sSpace, $iLenRight) & ' '
Case 2
Return StringLeft($sSpace, $_iMaxLen - $_iLen) & $_sString & ' '
EndSwitch
EndFunc ;==>_GetAligned
 

Example output in Alignment: left - center - right - left - center - right - left - center - right - left - center - right

Given          a            text file     of        many lines,      where    fields within    a    line
are        delineated         by a      single  'dollar' character,  write         a program
that         aligns         each column   of      fields by         ensuring    that words     in   each
column        are      separated by       at       least one         space. 
Further,     allow           for each    word         in a           column       to be      either left
justified,   right    justified, or     center justified within       its    column.

--BugFix (talk) 13:02, 17 November 2013 (UTC)

[edit] AWK

BEGIN {
FS="$"
lcounter = 1
maxfield = 0
# justification; pick one
#justify = "left"
justify = "center"
#justify = "right"
}
{
if ( NF > maxfield ) maxfield = NF;
for(i=1; i <= NF; i++) {
line[lcounter,i] = $i
if ( longest[i] == "" ) longest[i] = 0;
if ( length($i) > longest[i] ) longest[i] = length($i);
}
lcounter++
}
END {
just = (justify == "left") ? "-" : ""
for(i=1; i <= NR; i++) {
for(j=1; j <= maxfield; j++) {
if ( justify != "center" ) {
template = "%" just longest[j] "s "
} else {
v = int((longest[j] - length(line[i,j]))/2)
rt = "%" v+1 "s%%-%ds"
template = sprintf(rt, "", longest[j] - v)
}
printf(template, line[i,j])
}
print ""
}
}

[edit] BBC BASIC

      DATA 6
DATA "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
DATA "are$delineated$by$a$single$'dollar'$character,$write$a$program"
DATA "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
DATA "column$are$separated$by$at$least$one$space."
DATA "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
DATA "justified,$right$justified,$or$center$justified$within$its$column."
 
REM First find the maximum length of a 'word':
max% = 0
READ nlines%
FOR Line% = 1 TO nlines%
READ text$
REPEAT
word$ = FNword(text$, "$")
IF LEN(word$) > max% THEN max% = LEN(word$)
UNTIL word$ = ""
NEXT Line%
@% = max% : REM set column width
 
REM Now display the aligned text:
RESTORE
READ nlines%
FOR Line% = 1 TO nlines%
READ text$
REPEAT
word$ = FNword(text$, "$")
PRINT FNjustify(word$, max%, "left"),;
UNTIL word$ = ""
PRINT
NEXT Line%
 
END
 
DEF FNword(text$, delim$)
PRIVATE delim%
LOCAL previous%
IF delim% = 0 THEN
previous% = 1
ELSE
previous% = delim% + LEN(delim$)
ENDIF
delim% = INSTR(text$+delim$, delim$, previous%)
IF delim% = 0 THEN
= ""
ELSE
= MID$(text$, previous%, delim%-previous%) + " "
ENDIF
 
DEF FNjustify(word$, field%, mode$)
IF word$ = "" THEN = ""
CASE mode$ OF
WHEN "center": = STRING$((field%-LEN(word$)) DIV 2, " ") + word$
WHEN "right": = STRING$(field%-LEN(word$), " ") + word$
ENDCASE
= word$

[edit] C

See Column Aligner/C

[edit] C++

See Column Aligner/C++

[edit] C#

Uses a delegate, which were added to the language in C# 2, to define left-, right-, or center-justified.

Works with: C# version 2+
using System;
class ColumnAlignerProgram
{
delegate string Justification(string s, int width);
 
static string[] AlignColumns(string[] lines, Justification justification)
{
const char Separator = '$';
// build input table and calculate columns count
string[][] table = new string[lines.Length][];
int columns = 0;
for (int i = 0; i < lines.Length; i++)
{
string[] row = lines[i].TrimEnd(Separator).Split(Separator);
if (columns < row.Length) columns = row.Length;
table[i] = row;
}
// create formatted table
string[][] formattedTable = new string[table.Length][];
for (int i = 0; i < formattedTable.Length; i++)
{
formattedTable[i] = new string[columns];
}
for (int j = 0; j < columns; j++)
{
// get max column width
int columnWidth = 0;
for (int i = 0; i < table.Length; i++)
{
if (j < table[i].Length && columnWidth < table[i][j].Length)
columnWidth = table[i][j].Length;
}
// justify column cells
for (int i = 0; i < formattedTable.Length; i++)
{
if (j < table[i].Length)
formattedTable[i][j] = justification(table[i][j], columnWidth);
else
formattedTable[i][j] = new String(' ', columnWidth);
}
}
// create result
string[] result = new string[formattedTable.Length];
for (int i = 0; i < result.Length; i++)
{
result[i] = String.Join(" ", formattedTable[i]);
}
return result;
}
 
static string JustifyLeft(string s, int width) { return s.PadRight(width); }
static string JustifyRight(string s, int width) { return s.PadLeft(width); }
static string JustifyCenter(string s, int width)
{
return s.PadLeft((width + s.Length) / 2).PadRight(width);
}
 
static void Main()
{
string[] input = {
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$",
"are$delineated$by$a$single$'dollar'$character,$write$a$program",
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$",
"column$are$separated$by$at$least$one$space.",
"Further,$allow$for$each$word$in$a$column$to$be$either$left$",
"justified,$right$justified,$or$center$justified$within$its$column.",
};
 
foreach (string line in AlignColumns(input, JustifyCenter))
{
Console.WriteLine(line);
}
}
}

Output (centered):

  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program            
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.                             
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column.                    

[edit] Clojure

 
(ns rosettacode.align-columns
(:require [clojure.contrib.string :as str]))
 
(def data "Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column."
)
 
(def table (map #(str/split #"\$" %) (str/split-lines data)))
 
(defn col-width [n table] (reduce max (map #(try (count (nth % n))
(catch Exception _ 0))
table)))
(defn spaces [n] (str/repeat n " "))
(defn add-padding
"if the string is too big turncate it, else return a string with padding"
[string width justification]
(if (>= (count string) width) (str/take width string)
(let [pad-len (int (- width (count string))) ;we don't want rationals
half-pad-len (int (/ pad-len 2))]
(case justification
 :right (str (spaces pad-len) string)
 :left (str string (spaces pad-len))
 :center (str (spaces half-pad-len) string (spaces (- pad-len half-pad-len)))))))
 
(defn aligned-table
"get the width of each column, then generate a new table with propper padding for eath item"
([table justification]
(let [col-widths (map #(+ 2 (col-width % table)) (range (count(first table))))]
(map
(fn [row] (map #(add-padding %1 %2 justification) row col-widths))
table))))
 
(defn print-table
[table]
(do (println)
(print (str/join "" (flatten (interleave table (repeat "\n")))))))
 
(print-table (aligned-table table :center))
 

[edit] CoffeeScript

 
pad = (n) ->
s = ''
while n > 0
s += ' '
n -= 1
s
 
align = (input, alignment = 'center') ->
tokenized_lines = (line.split '$' for line in input)
col_widths = {}
for line in tokenized_lines
for token, i in line
if !col_widths[i]? or token.length > col_widths[i]
col_widths[i] = token.length
padders =
center: (s, width) ->
excess = width - s.length
left = Math.floor excess / 2
right = excess - left
pad(left) + s + pad(right)
 
right: (s, width) ->
excess = width - s.length
pad(excess) + s
 
left: (s, width) ->
excess = width - s.length
s + pad(excess)
 
padder = padders[alignment]
 
for line in tokenized_lines
padded_tokens = (padder(token, col_widths[i]) for token, i in line)
console.log padded_tokens.join ' '
 
 
input = [
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
"are$delineated$by$a$single$'dollar'$character,$write$a$program"
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
"column$are$separated$by$at$least$one$space."
"Further,$allow$for$each$word$in$a$column$to$be$either$left$"
"justified,$right$justified,$or$center$justified$within$its$column."
]
 
for alignment in ['center', 'right', 'left']
console.log "\n----- #{alignment}"
align input, alignment
 

output

 
> coffee align_columns.coffee
 
----- center
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 
----- right
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 
----- left
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 


[edit] Common Lisp

(defun nonempty (seq)
(position-if (lambda (x) (declare (ignore x)) t) seq))
 
(defun split (delim seq)
"Splits seq on delim into a list of subsequences. Trailing empty
subsequences are removed."

(labels
((f (seq &aux (pos (position delim seq)))
(if pos
(cons
(subseq seq 0 pos)
(f (subseq seq (1+ pos))))
(list seq))))
(let* ((list (f seq))
(end (position-if #'nonempty list :from-end t)))
(subseq list 0 (1+ end)))))
 
(defun lengthen (list minlen filler-elem &aux (len (length list)))
"Destructively pads list with filler-elem up to minlen."
(if (< len minlen)
(nconc list (make-list (- minlen len) :initial-element filler-elem))
list))
 
(defun align-columns (text
&key (align :left)
&aux
(fmtmod (case align
(:left "@")
(:right ":")
(:center "@:")
(t (error "Invalid alignment."))))
(fields (mapcar (lambda (line) (split #\$ line))
(split #\Newline text)))
(mostcols (loop for l in fields
maximize (length l)))
widest)
(setf fields (mapcar (lambda (l) (lengthen l mostcols ""))
fields))
(setf widest (loop for col below (length (first fields))
collect (loop for row in fields
maximize (length (elt row col)))))
(format nil
(with-output-to-string (s)
(princ "~{~{" s)
(dolist (w widest)
(format s "~~~d~a<~~a~~>" (1+ w) fmtmod))
(princ "~}~%~}" s))
fields))

[edit] D

import std.stdio, std.string, std.algorithm, std.range, std.typetuple;
 
void main() {
auto data =
"Given$a$txt$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column."

.split.map!(r => r.chomp("$").split("$"));
 
int[int] maxWidths;
foreach (const line; data)
foreach (immutable i, const word; line)
maxWidths[i] = max(maxWidths.get(i, 0), word.length);
 
foreach (const just; TypeTuple!(leftJustify, center, rightJustify))
foreach (const line; data)
writefln("%-(%s %)", line.length.iota
.map!(i => just(line[i], maxWidths[i], ' ')));
}
Output:
Given      a          txt        file   of     many      lines,     where    fields  within  a      line 
are        delineated by         a      single 'dollar'  character, write    a       program 
that       aligns     each       column of     fields    by         ensuring that    words   in     each 
column     are        separated  by     at     least     one        space.   
Further,   allow      for        each   word   in        a          column   to      be      either left 
justified, right      justified, or     center justified within     its      column. 
  Given        a         txt      file    of     many      lines,    where   fields  within    a    line 
   are     delineated     by       a    single 'dollar'  character,  write      a    program 
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each 
  column      are     separated    by     at     least      one      space.  
 Further,    allow       for      each   word     in         a       column    to      be    either left 
justified,   right    justified,   or   center justified   within     its    column. 
     Given          a        txt   file     of      many     lines,    where  fields  within      a line 
       are delineated         by      a single  'dollar' character,    write       a program 
      that     aligns       each column     of    fields         by ensuring    that   words     in each 
    column        are  separated     by     at     least        one   space. 
  Further,      allow        for   each   word        in          a   column      to      be either left 
justified,      right justified,     or center justified     within      its column. 

[edit] Delphi

 
USES
StdCtrls, Classes, SysUtils, StrUtils, Contnrs;
 
procedure AlignByColumn(Output: TMemo; Align: TAlignment);
const
TextToAlign =
'Given$a$text$file$of$many$lines,$where$fields$within$a$line$'#$D#$A +
'are$delineated$by$a$single$''dollar''$character,$write$a$program'#$D#$A +
'that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$'#$D#$A +
'column$are$separated$by$at$least$one$space.'#$D#$A +
'Further,$allow$for$each$word$in$a$column$to$be$either$left$'#$D#$A +
'justified,$right$justified,$or$center$justified$within$its$column.';
var
TextLine, TempTString: TStringlist;
TextLines: TObjectList;
MaxLength, i, j: Byte;
OutPutString, EmptyString, Item: String;
begin
TRY
MaxLength := 0;
TextLines := TObjectList.Create(True);
TextLine := TStringList.Create;
TextLine.text := TextToAlign;
for i:= 0 to TextLine.Count - 1 do
begin
TempTString := TStringlist.create;
TempTString.text :=AnsiReplaceStr(TextLine[i], '$', #$D#$A);
TextLines.Add(TempTString);
end;
for i := 0 to TextLines.Count - 1 do
for j := 0 to TStringList(TextLines.Items[i]).Count - 1 do
If Length(TStringList(TextLines.Items[i])[j]) > MaxLength then
MaxLength := Length(TStringList(TextLines.Items[i])[j]);
If MaxLength > 0 then
MaxLength := MaxLength + 2; // Add to empty spaces to it
for i := 0 to TextLines.Count - 1 do
begin
OutPutString := '';
for j := 0 to TStringList(TextLines.Items[i]).Count - 1 do
begin
EmptyString := StringOfChar(' ', MaxLength);
Item := TStringList(TextLines.Items[i])[j];
case Align of
taLeftJustify: Move(Item[1], EmptyString[2], Length(Item));
taRightJustify: Move(Item[1], EmptyString[MaxLength - Length(Item) + 1], Length(Item));
taCenter: Move(Item[1], EmptyString[(MaxLength - Length(Item) + 1) div 2 + 1], Length(Item));
end;
OutPutString := OutPutString + EmptyString;
end;
Output.Lines.Add(OutPutString);
end;
FINALLY
FreeAndNil(TextLine);
FreeAndNil(TextLines);
END;
end;
 

[edit] E

pragma.enable("accumulator")
 
def left(width, word) {
return word + " " * (width - word.size())
}
 
def center(width, word) {
def leftCount := (width - word.size()) // 2
return " " * leftCount + word + " " * (width - word.size() - leftCount)
}
 
def right(width, word) {
return " " * (width - word.size()) + word
}
 
def alignColumns(align, text) {
def split := accum [] for line in text.split("\n") { _.with(line.split("$")) }
var widths := []
for line in split {
for i => word in line {
widths with= (i, widths.fetch(i, fn{0}).max(word.size()))
}
}
return accum "" for line in split {
_ + accum "" for i => word in line {
_ + align(widths[i] + 1, word)
} + "\n"
}
}
? def text := "Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column."
; null
 
? println(alignColumns(left, text))
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 
? println(alignColumns(center, text))
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 
? println(alignColumns(right, text))
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.

[edit] Erlang

 
-module (align_columns).
 
-export([align_left/0, align_right/0, align_center/0]).
-define (Lines,
["Given\$a\$text\$file\$of\$many\$lines\$where\$fields\$within\$a\$line\$",
"are\$delineated\$by\$a\$single\$'dollar'\$character,\$write\$a\$program",
"that\$aligns\$each\$column\$of\$fields\$by\$ensuring\$that\$words\$in\$each\$",
"column\$are\$separated\$by\$at\$least\$one\$space.",
"Further,\$allow\$for\$each\$word\$in\$a\$column\$to\$be\$either\$left\$",
"justified,\$right\$justified,\$or\$center\$justified\$within\$its\$column."].
 
align_left()-> align_columns(left).
align_right()-> align_columns(right).
align_center()-> align_columns(centre).
align_columns(Alignment) ->
Words = [ string:tokens(Line, "\$") || Line <- ?Lines ],
Words_length = lists:foldl( fun max_length/2, [], Words),
Result = [prepare_line(Words_line, Words_length, Alignment)
|| Words_line <- Words],
 
[ io:fwrite("~s~n", [lists:flatten(Line)]) || Line <- Result],
ok.
 
max_length(Words_of_a_line, Acc_maxlength) ->
Line_lengths = [length(W) || W <- Words_of_a_line ],
Max_nb_of_length = lists:max([length(Acc_maxlength), length(Line_lengths)]),
Line_lengths_prepared = adjust_list (Line_lengths, Max_nb_of_length, 0),
Acc_maxlength_prepared = adjust_list(Acc_maxlength, Max_nb_of_length, 0),
Two_lengths =lists:zip(Line_lengths_prepared, Acc_maxlength_prepared),
[ lists:max([A, B]) || {A, B} <- Two_lengths].
adjust_list(L, Desired_length, Elem) ->
L++lists:duplicate(Desired_length - length(L), Elem).
 
prepare_line(Words_line, Words_length, Alignment) ->
All_words = adjust_list(Words_line, length(Words_length), ""),
Zipped = lists:zip (All_words, Words_length),
[ apply(string, Alignment, [Word, Length + 1, $\s])
|| {Word, Length} <- Zipped].
 
=== Output
 
 
1> c(align_columns).
{ok,align_columns}
2> align_columns:align_center().
Given a text file of many lines where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
ok
3> align_columns:align_left().
Given a text file of many lines where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
ok
4> align_columns:align_right().
Given a text file of many lines where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
ok
 
 
 

[edit] Euphoria

constant data = {
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$",
"are$delineated$by$a$single$'dollar'$character,$write$a$program",
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$",
"column$are$separated$by$at$least$one$space.",
"Further,$allow$for$each$word$in$a$column$to$be$either$left$",
"justified,$right$justified,$or$center$justified$within$its$column."
}
 
function split(sequence s, integer c)
sequence out
integer first, delim
out = {}
first = 1
while first<=length(s) do
delim = find_from(c,s,first)
if delim = 0 then
delim = length(s)+1
end if
out = append(out,s[first..delim-1])
first = delim + 1
end while
return out
end function
 
function align(sequence s, integer width, integer alignment)
integer n
n = width - length(s)
if n <= 0 then
return s
elsif alignment < 0 then
return s & repeat(' ', n)
elsif alignment > 0 then
return repeat(' ', n) & s
else
return repeat(' ', floor(n/2)) & s & repeat(' ', floor(n/2+0.5))
end if
end function
 
integer maxlen
sequence lines
maxlen = 0
lines = repeat(0,length(data))
for i = 1 to length(data) do
lines[i] = split(data[i],'$')
for j = 1 to length(lines[i]) do
if length(lines[i][j]) > maxlen then
maxlen = length(lines[i][j])
end if
end for
end for
 
for a = -1 to 1 do
for i = 1 to length(lines) do
for j = 1 to length(lines[i]) do
puts(1, align(lines[i][j],maxlen,a) & ' ')
end for
puts(1,'\n')
end for
puts(1,'\n')
end for

Output:

Given      a          text       file       of         many       lines,     where      fields     within     a          line       
are        delineated by         a          single     'dollar'   character, write      a          program    
that       aligns     each       column     of         fields     by         ensuring   that       words      in         each       
column     are        separated  by         at         least      one        space.     
Further,   allow      for        each       word       in         a          column     to         be         either     left       
justified, right      justified, or         center     justified  within     its        column.    

  Given        a         text       file        of        many      lines,     where      fields     within       a         line    
   are     delineated     by         a        single    'dollar'  character,   write        a       program   
   that      aligns      each      column       of       fields       by      ensuring     that      words        in        each    
  column      are     separated      by         at       least       one       space.   
 Further,    allow       for        each       word        in         a        column       to         be       either      left    
justified,   right    justified,     or       center   justified    within      its      column.   

     Given          a       text       file         of       many     lines,      where     fields     within          a       line 
       are delineated         by          a     single   'dollar' character,      write          a    program 
      that     aligns       each     column         of     fields         by   ensuring       that      words         in       each 
    column        are  separated         by         at      least        one     space. 
  Further,      allow        for       each       word         in          a     column         to         be     either       left 
justified,      right justified,         or     center  justified     within        its    column. 


[edit] F#

open System
open System.IO
 
let tableFromPath path =
let lines =
[ for line in File.ReadAllLines(path) -> (line.TrimEnd('$').Split('$')) ]
let width = List.fold (fun max (line : string[]) -> if max < line.Length then line.Length else max) 0 lines
List.map (fun (a : string[]) -> (List.init width (fun i -> if i < a.Length then a.[i] else ""))) lines
 
let rec trans m =
match m with
| []::_ -> []
| _ -> (List.map List.head m) :: trans (List.map List.tail m)
 
let colWidth table =
List.map (fun col -> List.max (List.map String.length col)) (trans table)
 
let left = (fun (s : string) n -> s.PadRight(n))
let right = (fun (s : string) n -> s.PadLeft(n))
let center = (fun (s : string) n -> s.PadLeft((n + s.Length) / 2).PadRight(n))
 
[<EntryPoint>]
let main argv =
let table = tableFromPath argv.[0]
let width = Array.ofList (colWidth table)
let format table align =
List.map (fun (row : string list) -> List.mapi (fun i s -> sprintf "%s" (align s width.[i])) row) table
|> List.iter (fun row -> printfn "%s" (String.Join(" ", Array.ofList row)))
 
for align in [ left; right; center ] do
format table align
printfn "%s" (new String('-', (Array.sum width) + width.Length - 1))
0

Output, when called with a file containing the sample input

Given      a          text       file   of     many      lines,     where    fields  within  a      line
are        delineated by         a      single 'dollar'  character, write    a       program
that       aligns     each       column of     fields    by         ensuring that    words   in     each
column     are        separated  by     at     least     one        space.
Further,   allow      for        each   word   in        a          column   to      be      either left
justified, right      justified, or     center justified within     its      column.
--------------------------------------------------------------------------------------------------------
     Given          a       text   file     of      many     lines,    where  fields  within      a line
       are delineated         by      a single  'dollar' character,    write       a program
      that     aligns       each column     of    fields         by ensuring    that   words     in each
    column        are  separated     by     at     least        one   space.
  Further,      allow        for   each   word        in          a   column      to      be either left
justified,      right justified,     or center justified     within      its column.
--------------------------------------------------------------------------------------------------------
  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column.
--------------------------------------------------------------------------------------------------------

[edit] FBSL

Using a multiline string:

#APPTYPE CONSOLE
 
DIM s = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column."

 
DIM lines[] = SPLIT(s, CRLF), tokens[], l, t, length, margin, justify = "center"
 
FOREACH l IN lines
tokens = SPLIT(l, "$")
FOREACH t IN tokens
IF STRLEN(t) > length THEN length = INCR(STRLEN)
NEXT
NEXT
 
FOREACH l IN lines
tokens = SPLIT(l, "$")
FOREACH t IN tokens
SELECT CASE justify
CASE "left"
PRINT t, SPACE(length - STRLEN(t));
CASE "center"
margin = (length - STRLEN(t)) \ 2
PRINT SPACE(margin), t, SPACE(length - STRLEN - margin);
CASE "right"
PRINT SPACE(length - STRLEN(t)), t;
END SELECT
NEXT
PRINT
NEXT
 
PAUSE

Output:

   Given        a        text       file        of        many      lines,      where     fields     within        a        line
    are    delineated     by          a       single    'dollar'  character,    write        a       program
   that      aligns      each      column       of       fields       by      ensuring     that       words       in        each
  column       are     separated     by         at        least       one      space.
 Further,     allow       for       each       word        in          a       column       to         be       either      left
justified,    right   justified,     or       center    justified   within       its      column.

Press any key to continue...

[edit] Factor

USING: fry io kernel math math.functions math.order sequences
splitting strings ;
IN: rosetta.column-aligner
 
CONSTANT: example-text "Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column."
 
: split-and-pad ( text -- lines )
"\n" split [ "$" split harvest ] map
dup [ length ] [ max ] map-reduce
'[ _ "" pad-tail ] map ;
 
: column-widths ( columns -- widths )
[ [ length ] [ max ] map-reduce ] map ;
 
SINGLETONS: +left+ +middle+ +right+ ;
 
GENERIC: align-string ( str n alignment -- str' )
 
M: +left+ align-string drop CHAR: space pad-tail ;
M: +right+ align-string drop CHAR: space pad-head ;
 
M: +middle+ align-string
drop
over length - 2 /
[ floor CHAR: space <string> ]
[ ceiling CHAR: space <string> ] bi surround ;
 
: align-columns ( columns alignment -- columns' )
[ dup column-widths ] dip '[
[ _ align-string ] curry map
] 2map ;
 
: print-aligned ( text alignment -- )
[ split-and-pad flip ] dip align-columns flip
[ [ write " " write ] each nl ] each ;
example-text { +left+ +middle+ +right+ } [ print-aligned ] with each

[edit] Forth

Works with: GNU Forth
\ align columns
 
: split ( addr len char -- addr len1 addr len-len1 )
>r 2dup r> scan 2swap 2 pick - ;
 
variable column
 
: for-each-line ( file len xt -- )
>r begin #lf split r@ execute 1 /string dup 0<= until 2drop rdrop ;
 
: for-each-field ( line len xt -- )
0 column !
>r begin '$ split r@ execute 1 column +! 1 /string dup 0<= until 2drop rdrop ;
 
0 value num-columns
 
: count-columns ( line len -- )
['] 2drop for-each-field
num-columns column @ max to num-columns ;
: find-num-columns ( file len -- )
0 to num-columns
['] count-columns for-each-line ;
 
0 value column-widths
 
: column-width ( field len -- )
column-widths column @ + c@
max
column-widths column @ + c!
drop ;
: measure-widths ( line len -- )
['] column-width for-each-field ;
: find-column-widths ( file len -- )
num-columns allocate throw to column-widths
column-widths num-columns erase
['] measure-widths for-each-line ;
 
\ type aligned, same naming convention as standard numeric U.R, .R
: type.l ( addr len width -- )
over - >r type r> spaces ;
: type.c ( addr len width -- )
over - dup 2/ spaces >r type r> 1+ 2/ spaces ;
: type.r ( addr len width -- )
over - spaces type ;
 
defer type.aligned
 
: print-field ( field len -- )
column-widths column @ + c@ type.aligned space ;
: print-line ( line len -- ) cr ['] print-field for-each-field ;
: print-fields ( file len -- ) ['] print-line for-each-line ;
 
 
\ read file
s" columns.txt" slurp-file ( file len )
 
\ scan once to determine num-columns
2dup find-num-columns
 
\ scan again to determine column-widths
2dup find-column-widths
 
\ print columns, once for each alignment type
' type.l is type.aligned 2dup print-fields cr
' type.c is type.aligned 2dup print-fields cr
' type.r is type.aligned 2dup print-fields cr
 
\ cleanup
nip free throw
column-widths free throw

[edit] Go

package main
 
import (
"fmt"
"strings"
)
 
const text = `Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.`

 
type formatter struct {
text [][]string
width []int
}
 
func newFormatter(text string) *formatter {
var f formatter
for _, line := range strings.Split(text, "\n") {
words := strings.Split(line, "$")
for words[len(words)-1] == "" {
words = words[:len(words)-1]
}
f.text = append(f.text, words)
for i, word := range words {
if i == len(f.width) {
f.width = append(f.width, len(word))
} else if len(word) > f.width[i] {
f.width[i] = len(word)
}
}
}
return &f
}
 
const (
left = iota
middle
right
)
 
func (f formatter) print(j int) {
for _, line := range f.text {
for i, word := range line {
fmt.Printf("%-*s ", f.width[i], fmt.Sprintf("%*s",
len(word)+(f.width[i]-len(word))*j/2, word))
}
fmt.Println("")
}
fmt.Println("")
}
 
func main() {
f := newFormatter(text)
f.print(left)
f.print(middle)
f.print(right)
}
Given      a          text       file   of     many      lines,     where    fields  within  a      line
are        delineated by         a      single 'dollar'  character, write    a       program
that       aligns     each       column of     fields    by         ensuring that    words   in     each
column     are        separated  by     at     least     one        space.
Further,   allow      for        each   word   in        a          column   to      be      either left
justified, right      justified, or     center justified within     its      column.

  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column.

     Given          a       text   file     of      many     lines,    where  fields  within      a line
       are delineated         by      a single  'dollar' character,    write       a program
      that     aligns       each column     of    fields         by ensuring    that   words     in each
    column        are  separated     by     at     least        one   space.
  Further,      allow        for   each   word        in          a   column      to      be either left
justified,      right justified,     or center justified     within      its column.

[edit] Groovy

Solution:

def alignColumns = { align, rawText ->
def lines = rawText.tokenize('\n')
def words = lines.collect { it.tokenize(/\$/) }
def maxLineWords = words.collect {it.size()}.max()
words = words.collect { line -> line + [''] * (maxLineWords - line.size()) }
def columnWidths = words.transpose().collect{ column -> column.collect { it.size() }.max() }
 
def justify = [ Right  : { width, string -> string.padLeft(width) },
Left  : { width, string -> string.padRight(width) },
Center : { width, string -> string.center(width) } ]
def padAll = { pad, colWidths, lineWords -> [colWidths, lineWords].transpose().collect { pad(it) + ' ' } }
 
words.each { padAll(justify[align], columnWidths, it).each { print it }; println() }
}

Test Program:

def rawTextInput = '''Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.'''

 
['Left', 'Center', 'Right'].each { align ->
println "${align} Justified:"
alignColumns(align, rawTextInput)
println()
}

Output:

Left Justified:
Given      a          text       file   of     many      lines,     where    fields  within  a      line 
are        delineated by         a      single 'dollar'  character, write    a       program             
that       aligns     each       column of     fields    by         ensuring that    words   in     each 
column     are        separated  by     at     least     one        space.                               
Further,   allow      for        each   word   in        a          column   to      be      either left 
justified, right      justified, or     center justified within     its      column.                     

Center Justified:
  Given        a         text     file    of     many      lines,    where   fields  within    a    line 
   are     delineated     by       a    single 'dollar'  character,  write      a    program             
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each 
  column      are     separated    by     at     least      one      space.                              
 Further,    allow       for      each   word     in         a       column    to      be    either left 
justified,   right    justified,   or   center justified   within     its    column.                     

Right Justified:
     Given          a       text   file     of      many     lines,    where  fields  within      a line 
       are delineated         by      a single  'dollar' character,    write       a program             
      that     aligns       each column     of    fields         by ensuring    that   words     in each 
    column        are  separated     by     at     least        one   space.                             
  Further,      allow        for   each   word        in          a   column      to      be either left 
justified,      right justified,     or center justified     within      its column.

[edit] Haskell

import Data.List
import Control.Monad
import Control.Arrow
 
dat = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$\n" ++
"are$delineated$by$a$single$'dollar'$character,$write$a$program\n" ++
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$\n" ++
"column$are$separated$by$at$least$one$space.\n" ++
"Further,$allow$for$each$word$in$a$column$to$be$either$left$\n" ++
"justified,$right$justified,$or$center$justified$within$its$column.\n"
 
brkdwn = takeWhile (not.null) . unfoldr (Just . second (drop 1) . span ('$'/=))
 
format j ls = map (unwords. zipWith align colw) rows
where
rows = map brkdwn $ lines ls
colw = map (maximum. map length) . transpose $ rows
align cw w =
case j of
'c' -> (replicate l ' ') ++ w ++ (replicate r ' ')
'r' -> (replicate dl ' ') ++ w
'l' -> w ++ (replicate dl ' ')
where
dl = cw-length w
(l,r) = (dl `div` 2, dl-l)

output example:

*Main> mapM_ putStrLn $ format 'c' dat
  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column.

[edit] HicEst

A file opened with a Format option describing the column format(s) can be addressed like a standard in-memory array. In addition the DLG function (MatrixExplorer) allows this text/numeric file to be edited or visualized in many ways, but string columns are always left adjusted while numeric columns are right adjusted. Export is possible.

 
CHARACTER Fnam = "\HicEst\Rosetta\Align columns.txt"
 
OPEN(FIle=Fnam, Format="12$", LENgth=rows)
! call the DLG function in MatrixExplorer mode:
DLG(Edit=Fnam, Format='12A10') ! left adjusted, 12 columns, 10 spaces each
 
! or the standard way:
CALL Align( "LLLLLLLLLLL ", Fnam, rows) ! left align
CALL Align( "CCCCCCCCCCC ", Fnam, rows) ! center align
CALL Align( "RRRRRRRRRRR ", Fnam, rows) ! right align
END
 
SUBROUTINE Align(picture, filename, rows)
CHARACTER picture, filename
CHARACTER out*400, txt*20
 
W = LEN(picture)
DO i = 1, rows
out = " "
DO j = 0, 100
txt = filename(i, j+1, *9) ! on error branch to label 9
WRITE(Text=out(j*W+1 : ), Format=picture) txt
ENDDO
9 CONTINUE
WRITE() out
ENDDO
END
Given       a           text        file        of          many        lines,      where       fields      within      a           line
are         delineated  by          a           single      'dollar'    character,  write       a           program
that        aligns      each        column      of          fields      by          ensuring    that        words       in          each
column      are         separated   by          at          least       one         space.
Further,    allow       for         each        word        in          a           column      to          be          either      left
justified,  right       justified,  or          center      justified   within      its         column.
   Given         a         text        file         of         many       lines,       where      fields      within         a         line
    are     delineated      by           a        single     'dollar'   character,     write         a        program
   that       aligns       each       column        of        fields        by       ensuring      that        words        in         each
  column        are      separated      by          at         least        one       space.
 Further,      allow        for        each        word         in           a        column        to          be        either       left
justified,     right    justified,      or        center     justified    within        its       column.
      Given           a        text        file          of        many      lines,       where      fields      within           a        line
        are  delineated          by           a      single    'dollar'  character,       write           a     program
       that      aligns        each      column          of      fields          by    ensuring        that       words          in        each
     column         are   separated          by          at       least         one      space.
   Further,       allow         for        each        word          in           a      column          to          be      either        left
 justified,       right  justified,          or      center   justified      within         its     column.

[edit] Icon and Unicon

An argument of left, center, or right controls the column alignment. The default is left-alignment.

global width
 
procedure main(args)
lines := []
width := 0
format := left
match("left"|"right"|"center", format <- !args)
every put(lines,prepare(!&input))
display(lines, proc(format,3))
end
 
procedure prepare(lines)
line := []
lines ? {
while (not pos(0)) & (field := tab(upto('$')|0)) do {
put(line, field)
width <:= *field
move(1)
}
}
return line
end
 
procedure display(lines, format)
width +:= 1
every line := !lines do {
every writes(format(!line, width))
write()
}
end

Sample run:

->align right <align.txt
      Given          a       text       file         of       many     lines,      where     fields     within          a       line
        are delineated         by          a     single   'dollar' character,      write          a    program
       that     aligns       each     column         of     fields         by   ensuring       that      words         in       each
     column        are  separated         by         at      least        one     space.
   Further,      allow        for       each       word         in          a     column         to         be     either       left
 justified,      right justified,         or     center  justified     within        its    column.
->

[edit] J

Solution

'LEFT CENTER RIGHT'=: i.3                NB. justification constants
 
NB.* alignCols v Format delimited text in justified columns
NB. y: text to format
NB. rows marked by last character in text
NB. columns marked by $
NB. optional x: justification. Default is LEFT
NB. result: text table
alignCols=: verb define
LEFT alignCols y NB. default
:
global=. dyad def'9!:x y'each
oldbox=. 6 16 global '';'' NB. save settings
7 17 global (11#' ');,~x NB. apply new settings
result=. _2{:\ ": <;._2 @:,&'$';._2 y NB. parse & format text
7 17 global oldbox NB. restore settings
result
)

Example:

   text=: noun define
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
)
 
alignCols text NB. default justification
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 
CENTER alignCols text NB. specify desired justification as left argument
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.

[edit] Java

Works with: Java version 7
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
 
import org.apache.commons.lang3.StringUtils;
 
/**
* Aligns fields into columns, separated by "|"
*/

public class ColumnAligner {
private List<String[]> words = new ArrayList<>();
private int columns = 0;
private List<Integer> columnWidths = new ArrayList<>();
 
/**
* Initialize columns aligner from lines in a single string
*
* @param s
* lines in a single string. Empty string does form a column.
*/

public ColumnAligner(String s) {
String[] lines = s.split("\\n");
for (String line : lines) {
processInputLine(line);
}
}
 
/**
* Initialize columns aligner from lines in a list of strings
*
* @param lines
* lines in a single string. Empty string does form a column.
*/

public ColumnAligner(List<String> lines) {
for (String line : lines) {
processInputLine(line);
}
}
 
private void processInputLine(String line) {
String[] lineWords = line.split("\\$");
words.add(lineWords);
columns = Math.max(columns, lineWords.length);
for (int i = 0; i < lineWords.length; i++) {
String word = lineWords[i];
if (i >= columnWidths.size()) {
columnWidths.add(word.length());
} else {
columnWidths.set(i, Math.max(columnWidths.get(i), word.length()));
}
}
}
 
interface AlignFunction {
String align(String s, int length);
}
 
/**
* Left-align all columns
*
* @return Lines, terminated by "\n" of columns, separated by "|"
*/

public String alignLeft() {
return align(new AlignFunction() {
@Override
public String align(String s, int length) {
return StringUtils.rightPad(s, length);
}
});
}
 
/**
* Right-align all columns
*
* @return Lines, terminated by "\n" of columns, separated by "|"
*/

public String alignRight() {
return align(new AlignFunction() {
@Override
public String align(String s, int length) {
return StringUtils.leftPad(s, length);
}
});
}
 
/**
* Center-align all columns
*
* @return Lines, terminated by "\n" of columns, separated by "|"
*/

public String alignCenter() {
return align(new AlignFunction() {
@Override
public String align(String s, int length) {
return StringUtils.center(s, length);
}
});
}
 
private String align(AlignFunction a) {
StringBuilder result = new StringBuilder();
for (String[] lineWords : words) {
for (int i = 0; i < lineWords.length; i++) {
String word = lineWords[i];
if (i == 0) {
result.append("|");
}
result.append(a.align(word, columnWidths.get(i)) + "|");
}
result.append("\n");
}
return result.toString();
}
 
public static void main(String args[]) throws IOException {
if (args.length < 1) {
System.out.println("Usage: ColumnAligner file [left|right|center]");
return;
}
String filePath = args[0];
String alignment = "left";
if (args.length >= 2) {
alignment = args[1];
}
ColumnAligner ca = new ColumnAligner(Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8));
switch (alignment) {
case "left":
System.out.print(ca.alignLeft());
break;
case "right":
System.out.print(ca.alignRight());
break;
case "center":
System.out.print(ca.alignCenter());
break;
default:
System.err.println(String.format("Error! Unknown alignment: '%s'", alignment));
break;
}
}
}

[edit] JavaScript

 
var justification="center",
input=["Given$a$text$file$of$many$lines,$where$fields$within$a$line$",
"are$delineated$by$a$single$'dollar'$character,$write$a$program",
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$",
"column$are$separated$by$at$least$one$space.",
"Further,$allow$for$each$word$in$a$column$to$be$either$left$",
"justified,$right$justified,$or$center$justified$within$its$column."],
x,y,cols,max,cols=0,diff,left,right
 
String.prototype.repeat=function(n){return new Array(1 + parseInt(n)).join(this);}
 
for(x=0;x<input.length;x++) {
input[x]=input[x].split("$");
if(input[x].length>cols) cols=input[x].length;
}
for(x=0;x<cols;x++) {
max=0;
for(y=0;y<input.length;y++) if(input[y][x]&&max<input[y][x].length) max=input[y][x].length;
for(y=0;y<input.length;y++)
if(input[y][x]) {
diff=(max-input[y][x].length)/2;
left=" ".repeat(Math.floor(diff));
right=" ".repeat(Math.ceil(diff));
if(justification=="left") {right+=left;left=""}
if(justification=="right") {left+=right;right=""}
input[y][x]=left+input[y][x]+right;
}
}
for(x=0;x<input.length;x++) input[x]=input[x].join(" ");
input=input.join("\n");
document.write(input);

[edit] jq

Works with: jq version 1.4

The key to the following implementation is the filter named "transpose", which is defined to work on a possibly jagged matrix.

# transpose a possibly jagged matrix
def transpose:
if . == [] then []
else (.[1:] | transpose) as $t
| .[0] as $row
| reduce range(0; [($t|length), (.[0]|length)] | max) as $i
([]; . + [ [ $row[$i] ] + $t[$i] ])
end;
 
# left/right/center justification of strings:
def ljust(width): . + " " * (width - length);
 
def rjust(width): " " * (width - length) + .;
 
def center(width):
(width - length) as $pad
| if $pad <= 0 then .
else ($pad / 2 | floor) as $half
| $half * " " + . + ($pad-$half) * " "
end ;
 
# input: a single string, which includes newlines to separate lines, and $ to separate phrases;
# method must be "left" "right" or anything else for central justification.
def format(method):
def justify(width):
if method == "left" then ljust(width)
elif method == "right" then rjust(width)
else center(width)
end;
 
# max_widths: input: an array of strings, each with "$" as phrase-separator;
# return the appropriate column-wise maximum lengths
def max_widths:
map(split("$") | map(length))
| transpose | map(max) ;
 
split("\n") as $input
| $input
| (max_widths | map(.+1)) as $widths
| map( split("$") | . as $line | reduce range(0; length) as $i
(""; . + ($line[$i]|justify($widths[$i])) ))
| join("\n")
;

Example:

"Center:", format("center"), "",
"Left:", format("left"), "",
"Right:", format("right")
Output:
$ jq -M -R -r -s -f Align_columns.jq Align_columns.txt
Center:
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 
Left:
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 
Right:
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 

[edit] Julia

Translation of: Python
txt = """Given\$a\$txt\$file\$of\$many\$lines,\$where\$fields\$within\$a\$line\$
are\$delineated\$by\$a\$single\$'dollar'\$character,\$write\$a\$program
that\$aligns\$each\$column\$of\$fields\$by\$ensuring\$that\$words\$in\$each\$
column\$are\$separated\$by\$at\$least\$one\$space.
Further,\$allow\$for\$each\$word\$in\$a\$column\$to\$be\$either\$left\$
justified,\$right\$justified,\$or\$center\$justified\$within\$its\$column."""
 
# left/right/center justification of strings:
ljust(s, width) = s * " "^max(0, width - length(s))
rjust(s, width) = " "^max(0, width - length(s)) * s
function center(s, width)
pad = width - length(s)
if pad <= 0
return s
else
pad2 = div(pad, 2)
return " "^pad2 * s * " "^(pad - pad2)
end
end
 
parts = [split(rstrip(line, '$'), '$') for line in split(txt, '\n')]
 
max_widths = zeros(Int, maximum(length, parts))
for line in parts
for (i, word) in enumerate(line)
max_widths[i] = max(max_widths[i], length(word))
end
end
max_widths += 1 # separate cols by at least one space
 
for (label, justify) in (("Left", ljust), ("Right",rjust), ("Center",center))
println(label, " column-aligned output:")
for line in parts
for (j, word) in enumerate(line)
print(justify(word, max_widths[j]))
end
println()
end
println("-"^sum(max_widths))
end

Output:

Left column-aligned output:
Given      a          txt        file   of     many      lines,     where    fields  within  a      line 
are        delineated by         a      single 'dollar'  character, write    a       program 
that       aligns     each       column of     fields    by         ensuring that    words   in     each 
column     are        separated  by     at     least     one        space.   
Further,   allow      for        each   word   in        a          column   to      be      either left 
justified, right      justified, or     center justified within     its      column. 
---------------------------------------------------------------------------------------------------------
Right column-aligned output:
      Given          a        txt   file     of      many     lines,    where  fields  within      a line
        are delineated         by      a single  'dollar' character,    write       a program
       that     aligns       each column     of    fields         by ensuring    that   words     in each
     column        are  separated     by     at     least        one   space.
   Further,      allow        for   each   word        in          a   column      to      be either left
 justified,      right justified,     or center justified     within      its column.
---------------------------------------------------------------------------------------------------------
Center column-aligned output:
   Given        a         txt     file    of      many     lines,     where   fields  within    a   line 
    are    delineated     by        a   single  'dollar' character,   write     a    program 
   that      aligns      each    column   of     fields      by     ensuring   that   words    in   each 
  column       are     separated   by     at     least       one     space.  
 Further,     allow       for     each   word      in         a      column     to      be   either left 
justified,    right   justified,   or   center justified   within      its   column. 
---------------------------------------------------------------------------------------------------------

[edit] Lasso

#!/usr/bin/lasso9
 
local(text = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
")
 
 
define go_left(text::array, width::integer) => {
local(output = string)
with row in #text do {
with word in #row do {
#output -> append(string(#word) -> padtrailing(#width + 1)&)
}
#output -> append('\n')
}
return #output
}
 
define go_right(text::array, width::integer) => {
local(output = string)
with row in #text do {
with word in #row do {
#output -> append(string(#word) -> padleading(#width + 1)&)
}
#output -> append('\n')
}
return #output
}
 
define go_center(text::array, width::integer) => {
local(output = string)
with row in #text do {
with word in #row do {
local(
padlength = (#width + 1 - #word -> size),
padleft = (' ' * (#padlength / 2)),
padright = (' ' * (#padlength - #padleft -> size))
)
#output -> append(#padleft + string(#word) + #padright)
}
#output -> append('\n')
}
return #output
}
 
define prepcols(text::string) => {
local(
result = array,
maxwidth = 0
)
with row in #text -> split('\n') do {
#row -> removetrailing('$')
#result -> insert(#row -> split('$'))
}
with word in delve(#result) do {
#word -> size > #maxwidth ? #maxwidth = #word -> size
}
stdoutnl('Left aligned result: \n' + go_left(#result, #maxwidth))
stdoutnl('Right aligned result: \n' + go_right(#result, #maxwidth))
stdoutnl('Centered result: \n' + go_center(#result, #maxwidth))
}
 
prepcols(#text)

Output:

Left aligned result: 
Given      a          text       file       of         many       lines,     where      fields     within     a          line       
are        delineated by         a          single     'dollar'   character, write      a          program    
that       aligns     each       column     of         fields     by         ensuring   that       words      in         each       
column     are        separated  by         at         least      one        space.     
Further,   allow      for        each       word       in         a          column     to         be         either     left       
justified, right      justified, or         center     justified  within     its        column.    


Right aligned result: 
      Given          a       text       file         of       many     lines,      where     fields     within          a       line
        are delineated         by          a     single   'dollar' character,      write          a    program
       that     aligns       each     column         of     fields         by   ensuring       that      words         in       each
     column        are  separated         by         at      least        one     space.
   Further,      allow        for       each       word         in          a     column         to         be     either       left
 justified,      right justified,         or     center  justified     within        its    column.


Centered result: 
   Given        a        text       file        of        many      lines,      where     fields     within        a        line    
    are    delineated     by          a       single    'dollar'  character,    write        a       program  
   that      aligns      each      column       of       fields       by      ensuring     that       words       in        each    
  column       are     separated     by         at        least       one      space.   
 Further,     allow       for       each       word        in          a       column       to         be       either      left    
justified,    right   justified,     or       center    justified   within       its      column.  

[edit] Liberty BASIC

mainwin 140 32
 
CRLF$ =chr$( 13)
maxlen =0
 
read y
 
Dim txt$( y)
 
For i =1 To y
Read i$
print i$
if right$( i$, 1) <>"$" then i$ =i$ +"$"
txt$( i) =i$
x =max( CountDollars( txt$( i)), x)
Next i
 
print x
 
Dim matrix$( x, y)
 
Print CRLF$; " ---- Left ----"
For yy =1 To y
For xx =1 To x
matrix$( xx, yy) =word$( txt$( yy), xx, "$")
print matrix$( xx, yy), "|";
maxlen =max( maxlen, Len( matrix$( xx, yy)))
Next xx
print ""
Next yy
 
Print CRLF$; " ---- Right ----"
For yy =1 To y
For xx =1 To x
Print right$( " " +matrix$( xx, yy), maxlen +1); "|";
' will truncate column words longer than 20. Change to use maxlen....
Next xx
Print ""
Next yy
 
Print CRLF$ +" ---- Center ----"
For yy =1 to y
For xx =1 to x
wordLen =Len( matrix$( xx, yy))
padNeeded =maxlen -wordLen +4
LeftSpaces =padNeeded /2
 
if LeftSpaces =int( LeftSpaces) then
RightSpaces =LeftSpaces
else
RightSpaces =LeftSpaces -1
end if
 
Print space$( LeftSpaces); matrix$( xx, yy); space$( RightSpaces); "|";
Next xx
Print ""
Next yy
 
wait
 
Data 6
 
Data "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
Data "are$delineated$by$a$single$'dollar'$character,$write$a$program"
Data "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
Data "column$are$separated$by$at$least$one$space."
Data "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
Data "justified,$right$justified,$or$center$justified$within$its$column."
 
function CountDollars( src$)
c =0
for j =1 to len( src$)
if mid$( src$, j, 1) ="$" then c =c +1
next j
CountDollars =c
end function
 
end

[edit] Lua

Works with: Lua version 5.1
 
local tWord = {} -- word table
local tColLen = {} -- maximum word length in a column
local rowCount = 0 -- row counter
--store maximum column lengths at 'tColLen'; save words into 'tWord' table
local function readInput(pStr)
for line in pStr:gmatch("([^\n]+)[\n]-") do -- read until '\n' character
rowCount = rowCount + 1
tWord[rowCount] = {} -- create new row
local colCount = 0
for word in line:gmatch("[^$]+") do -- read non '$' character
colCount = colCount + 1
tColLen[colCount] = math.max((tColLen[colCount] or 0), #word) -- store column length
tWord[rowCount][colCount] = word -- store words
end--for word
end--for line
end--readInput
--repeat space to align the words in the same column
local align = {
["left"] = function (pWord, pColLen)
local n = (pColLen or 0) - #pWord + 1
return pWord .. (" "):rep(n)
end;--["left"]
["right"] = function (pWord, pColLen)
local n = (pColLen or 0) - #pWord + 1
return (" "):rep(n) .. pWord
end;--["right"]
["center"] = function (pWord, pColLen)
local n = (pColLen or 0) - #pWord + 1
local n1 = math.floor(n/2)
return (" "):rep(n1) .. pWord .. (" "):rep(n-n1)
end;--["center"]
}
--word table padder
local function padWordTable(pAlignment)
local alignFunc = align[pAlignment] -- selecting the spacer function
for rowCount, tRow in ipairs(tWord) do
for colCount, word in ipairs(tRow) do
tRow[colCount] = alignFunc(word, tColLen[colCount]) -- save the padded words into the word table
end--for colCount, word
end--for rowCount, tRow
end--padWordTable
--main interface
--------------------------------------------------[]
function alignColumn(pStr, pAlignment, pFileName)
--------------------------------------------------[]
readInput(pStr) -- store column lengths and words
padWordTable(pAlignment or "left") -- pad the stored words
local output = ""
for rowCount, tRow in ipairs(tWord) do
local line = table.concat(tRow) -- concatenate words in one row
print(line) -- print the line
output = output .. line .. "\n" -- concatenate the line for output, add line break
end--for rowCount, tRow
if (type(pFileName) == "string") then
local file = io.open(pFileName, "w+")
file:write(output) -- write output to file
file:close()
end--if type(pFileName)
return output
end--alignColumn
 

Usage Example:

 
input =
[[Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.]]
 
 
outputLeft = alignColumn(input)
outputRight = alignColumn(input, "right")
alignColumn(input, "center", "output.txt")
 

[edit] Maple

Assign the sample data.

 
txt :=
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$\n"
"are$delineated$by$a$single$'dollar'$character,$write$a$program\n"
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$\n"
"column$are$separated$by$at$least$one$space.\n"
"Further,$allow$for$each$word$in$a$column$to$be$either$left$\n"
"justified,$right$justified,$or$center$justified$within$its$column.\n":
 

The following procedure solves the problem. It takes the string to be operated on as input, and an optional alignment parameter, which defaults to centred alignment. The aligned text is returned, as a string, which can then be printed.

 
AlignColumns := proc( txt, align :: { "left", "right", "centre" } := "centre" )
uses StringTools;
 
# Get a list of lists of fields
local A := map( Split, Split( txt ), "$" );
 
# Calculate the column width
local width := 1 + max( map( L -> max( map( length, L ) ), A ) );
 
# Add spacing according to the requested type of alignment
if align = "left" then
local J := map( line -> map( PadRight, line, width ), A )
elif align = "right" then
J := map( line -> map( PadLeft, line, width ), A )
else
J := map( line -> map( Center, line, width ), A )
end if;
 
# Join up the fields in each line.
J := map( cat@op, J );
 
# Re-assemble the lines into a single string.
Join( J, "\n" )
end proc:
 

For the sample text, we get the following results.

 
> printf( "%s\n", AlignColumns( txt ) ):
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
> printf( "%s\n", AlignColumns( txt, "center" ) ): # same as above
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
> printf( "%s\n", AlignColumns( txt, "left" ) ):
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
> printf( "%s\n", AlignColumns( txt, "right" ) ):
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 

Alternatively, this could be printed to a file (using fprintf instead of printf).


[edit] Mathematica

TableForm[StringSplit[StringSplit[a,"\n"],"$"],TableAlignments -> Center]

Output with example text : Centeredtext.png

[edit] ML/I

In this example, ML/I reads its macros first, then switches input to the file containing the data to be formatted. Output is to 'standard output' or similar. Note the presetting of P102 to indicate the alignment required.

MCSKIP "WITH" NL
"" Align columns - assumes macros on input stream 1, data on stream 2
MCPVAR 102
"" Set P102 to alignment required:
"" 1 = centre
"" 2 = left
"" 3 = right
MCSET P102 = 1
MCSKIP MT,<>
MCINS %.
MCSKIP SL WITH *
"" Assume no more than 100 columns - P101 used for max number of fields
"" Set P variables 1-101 to 0
MCDEF ZEROPS WITHS NL AS <MCSET T1=1
%L1.MCSET PT1=0
MCSET T1=T1+1
MCGO L1 UNLESS T1 EN 102
>
ZEROPS
"" First pass - macro to accumulate max columns, and max widths
MCDEF SL N1 OPT $ N1 OR $ WITHS NL OR SPACE WITHS NL OR NL ALL
AS <MCGO L3 UNLESS T1 GR P101
MCSET P101=T1
%L3.MCSET T2=1
%L1.MCGO L0 IF T2 GR T1
MCSET T3=MCLENG(%WBT2.)
MCGO L2 UNLESS T3 GR PT2
MCSET PT2=T3
%L2.MCSET T2=T2+1
MCGO L1
>
MCSET S1=1
*MCSET S10=2
*MCSET S1=0
MCSET S4=1
""MCNOTE Max field is %P101.
""MCDEF REP NL AS <MCSET T1=1
""%L1.%PT1. MCSET T1=T1+1
""MCGO L1 UNLESS T1 GR P101
"">
""REP
MCDEF SL N1 OPT $ N1 OR $ WITHS NL OR SPACE WITHS NL OR NL ALL
AS <MCSET T2=1
%L5.MCGO L6 IF T2 GR T1
MCGO LP102
%L1.MCSET T3=%%%PT2.-MCLENG(%WBT2.)./2.
MCGO L7 IF T3 EN 0
MCSUB(< >,1,T3)%L7.%WBT2.""
MCSUB(< >,1,PT2-T3-MCLENG(%WBT2.)+1)MCGO L4
%L2.MCSUB(%WBT2.< >,1,PT2)MCGO L4
%L3.MCSUB(< >%WBT2.,1-PT2,0)""
%L4. MCSET T2=T2+1
MCGO L5
%L6.
>
MCSET S1=1
*MCSET S10=102

[edit] MUMPS

columns(how)	; how = "Left", "Center" or "Right"
New col,half,ii,max,spaces,word
Set ii=0
Set ii=ii+1,line(ii)="Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
Set ii=ii+1,line(ii)="are$delineated$by$a$single$'dollar'$character,$write$a$program"
Set ii=ii+1,line(ii)="that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
Set ii=ii+1,line(ii)="column$are$separated$by$at$least$one$space."
Set ii=ii+1,line(ii)="Further,$allow$for$each$word$in$a$column$to$be$either$left$"
Set ii=ii+1,line(ii)="justified,$right$justified,$or$center$justified$within$its$column."
Set ii="" For Set ii=$Order(line(ii)) Quit:ii="" Do
. For col=1:1:$Length(line(ii),"$") Do
. . Set max=$Length($Piece(line(ii),"$",col))
. . Set:max>$Get(max(col)) max(col)=max
. . Quit
. Quit
Set ii="" For Set ii=$Order(line(ii)) Quit:ii="" Do
. Write ! For col=1:1:$Length(line(ii),"$") Do:$Get(max(col))
. . Set word=$Piece(line(ii),"$",col)
. . Set spaces=$Justify("",max(col)-$Length(word))
. . If how="Left" Write word,spaces," " Quit
. . If how="Right" Write spaces,word," " Quit
. . Set half=$Length(spaces)\2
. . Write $Extract(spaces,1,half),word,$Extract(spaces,half+1,$Length(spaces))," "
. . Quit
. Quit
Write !
Quit
Do columns("Left")
 
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 
Do columns("Center")
 
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 
Do columns("Right")
 
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.

[edit] Nimrod

import strutils, sequtils, strfmt
 
let textinfile = """Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column."""
 
var words = textinfile.splitLines.mapIt(seq[string], it.split '$')
var maxs = newSeq[int](max words.mapIt(int, it.len))
 
for l in words:
for j,w in l:
maxs[j] = max(maxs[j], w.len+1)
 
for i, align in ["<",">","^"]:
echo(["Left", "Right", "Center"][i], " column-aligned output:")
for l in words:
for j,w in l:
stdout.write w.format align & $maxs[j]
stdout.write "\n"

Output:

Left column-aligned output:
Given      a          text       file   of     many      lines,     where    fields  within  a      line  
are        delineated by         a      single 'dollar'  character, write    a       program 
that       aligns     each       column of     fields    by         ensuring that    words   in     each  
column     are        separated  by     at     least     one        space.   
Further,   allow      for        each   word   in        a          column   to      be      either left  
justified, right      justified, or     center justified within     its      column. 
Right column-aligned output:
      Given          a       text   file     of      many     lines,    where  fields  within      a line 
        are delineated         by      a single  'dollar' character,    write       a program
       that     aligns       each column     of    fields         by ensuring    that   words     in each 
     column        are  separated     by     at     least        one   space.
   Further,      allow        for   each   word        in          a   column      to      be either left 
 justified,      right justified,     or center justified     within      its column.
Center column-aligned output:
   Given        a        text     file    of      many     lines,     where   fields  within    a   line  
    are    delineated     by        a   single  'dollar' character,   write     a    program 
   that      aligns      each    column   of     fields      by     ensuring   that   words    in   each  
  column       are     separated   by     at     least       one     space.  
 Further,     allow       for     each   word      in         a      column     to      be   either left  
justified,    right   justified,   or   center justified   within      its   column. 

[edit] OCaml

#load "str.cma"
open Str
 
let input = "\
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column."

 
let () =
let lines = split (regexp_string "\n") input in
let fields_l = List.map (split (regexp_string "$")) lines in
let fields_l = List.map Array.of_list fields_l in
let n = (* number of columns *)
List.fold_left
(fun n fields -> max n (Array.length fields))
0 fields_l
in
let pads = Array.make n 0 in
List.iter (
(* calculate the max padding for each column *)
Array.iteri
(fun i word -> pads.(i) <- max pads.(i) (String.length word))
) fields_l;
 
let print f =
List.iter (fun fields ->
Array.iteri (fun i word ->
f word (pads.(i) - (String.length word))
) fields;
print_newline()
) fields_l;
in
 
(* left column-aligned output *)
print (fun word pad ->
let spaces = String.make pad ' ' in
Printf.printf "%s%s " word spaces);
 
(* right column-aligned output *)
print (fun word pad ->
let spaces = String.make pad ' ' in
Printf.printf "%s%s " spaces word);
 
(* center column-aligned output *)
print (fun word pad ->
let pad1 = pad / 2 in
let pad2 = pad - pad1 in
let sp1 = String.make pad1 ' ' in
let sp2 = String.make pad2 ' ' in
Printf.printf "%s%s%s " sp1 word sp2);
;;

[edit] ooRexx

 
text = .array~of("Given$a$text$file$of$many$lines,$where$fields$within$a$line$", -
"are$delineated$by$a$single$'dollar'$character,$write$a$program", -
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$", -
"column$are$separated$by$at$least$one$space.", -
"Further,$allow$for$each$word$in$a$column$to$be$either$left$", -
"justified,$right$justified,$or$center$justified$within$its$column.")
 
columns = 0
parsedText = .array~new
-- split each line of text into words and figure out how many columns we need
loop line over text
parsedLine = line~makearray("$")
parsedText~append(parsedLine)
columns = max(columns, parsedLine~items)
end
 
-- now figure out how wide we need to make each column
columnWidths = .array~new(columns)
linelength = 0
loop i = 1 to columns
width = 0
loop line over parsedText
word = line[i]
if word \= .nil then width = max(width, word~length)
end
columnWidths[i] = width
-- keep track of the total width, including space for a separator
linelength += width + 1
end
 
say "align left:"
say
out = .mutableBuffer~new(linelength)
loop line over parsedText
-- mutable buffers are more efficient than repeated string concats
-- reset the working buffer to zero
out~setbuffersize(0)
loop col = 1 to line~items
word = line[col]
if word == .nil then word = ''
out~append(word~left(columnwidths[col] + 1))
end
say out~string
end
say
say "align right:"
say
 
loop line over parsedText
-- mutable buffers are more efficient than repeated string concats
-- reset the working buffer to zero
out~setbuffersize(0)
loop col = 1 to line~items
word = line[col]
if word == .nil then word = ''
out~append(word~right(columnwidths[col] + 1))
end
say out~string
end
say
say "align center:"
say
 
loop line over parsedText
-- mutable buffers are more efficient than repeated string concats
-- reset the working buffer to zero
out~setbuffersize(0)
loop col = 1 to line~items
word = line[col]
if word == .nil then word = ''
out~append(word~center(columnwidths[col] + 1))
end
say out~string
end
 
align left:

Given      a          text       file   of     many      lines,     where    fields  within  a      line
are        delineated by         a      single 'dollar'  character, write    a       program
that       aligns     each       column of     fields    by         ensuring that    words   in     each
column     are        separated  by     at     least     one        space.
Further,   allow      for        each   word   in        a          column   to      be      either left
justified, right      justified, or     center justified within     its      column.

align right:

      Given          a       text   file     of      many     lines,    where  fields  within      a line
        are delineated         by      a single  'dollar' character,    write       a program
       that     aligns       each column     of    fields         by ensuring    that   words     in each
     column        are  separated     by     at     least        one   space. 
   Further,      allow        for   each   word        in          a   column      to      be either left
 justified,      right justified,     or center justified     within      its column.

align center:

   Given        a        text     file    of      many     lines,     where   fields  within    a   line
    are    delineated     by        a   single  'dollar' character,   write     a    program
   that      aligns      each    column   of     fields      by     ensuring  that    words    in   each
  column       are     separated   by     at     least       one     space.
 Further,     allow       for     each   word      in         a      column     to      be   either left
justified,    right   justified,   or   center justified   within      its   column.

[edit] OpenEdge/Progress

FUNCTION alignColumns RETURNS CHAR (
i_c AS CHAR,
i_calign AS CHAR
):
 
DEF VAR ipass AS INT.
DEF VAR iline AS INT.
DEF VAR icol AS INT.
DEF VAR iwidth AS INT EXTENT.
DEF VAR cword AS CHAR.
DEF VAR cspace AS CHAR.
DEF VAR cresult AS CHAR.
 
EXTENT( iwidth ) = NUM-ENTRIES( ENTRY( 1, i_c, "~n" ), "$" ).
 
DO ipass = 0 TO 1:
DO iline = 1 TO NUM-ENTRIES( i_c, "~n" ):
DO icol = 1 TO NUM-ENTRIES( ENTRY( iline, i_c, "~n" ), "$" ):
cword = ENTRY( icol, ENTRY( iline, i_c, "~n" ), "$" ).
IF ipass = 0 THEN
iwidth = MAXIMUM( LENGTH( cword ), iwidth[ icol ] ).
ELSE DO:
cspace = FILL( " ", iwidth[ icol ] - LENGTH( cword ) ).
CASE i_calign:
WHEN "left" THEN cresult = cresult + cword + cspace.
WHEN "right" THEN cresult = cresult + cspace + cword.
WHEN "center" THEN DO:
cword = FILL( " ", INTEGER( LENGTH( cspace ) / 2 ) ) + cword.
cresult = cresult + cword + FILL( " ", iwidth[icol] - LENGTH( cword ) ).
END.
END CASE. /* i_calign */
cresult = cresult + " ".
END.
END. /* DO icol = 1 TO ... */
IF ipass = 1 THEN
cresult = cresult + "~n".
END. /* DO iline = 1 TO ... */
END. /* DO ipass = 0 TO 1 */
 
RETURN cresult.
 
END FUNCTION.
 
DEF VAR cc AS CHAR.
 
cc = SUBSTITUTE(
"&1~n&2~n&3~n&4~n&5~n&6",
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$",
"are$delineated$by$a$single$'dollar'$character,$write$a$program",
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$",
"column$are$separated$by$at$least$one$space.",
"Further,$allow$for$each$word$in$a$column$to$be$either$left$",
"justified,$right$justified,$or$center$justified$within$its$column."
).
 
MESSAGE
alignColumns( cc, "left" ) SKIP
alignColumns( cc, "right" ) SKIP
alignColumns( cc, "center" )
VIEW-AS ALERT-BOX.

Output:

---------------------------
Message
---------------------------
Given      a          text       file       of         many       lines,     where      fields     within     a          line                  
are        delineated by         a          single     'dollar'   character, write      a          program    
that       aligns     each       column     of         fields     by         ensuring   that       words      in         each                  
column     are        separated  by         at         least      one        space.     
Further,   allow      for        each       word       in         a          column     to         be         either     left                  
justified, right      justified, or         center     justified  within     its        column.    

     Given          a       text       file         of       many     lines,      where     fields     within          a       line            
       are delineated         by          a     single   'dollar' character,      write          a    program 
      that     aligns       each     column         of     fields         by   ensuring       that      words         in       each            
    column        are  separated         by         at      least        one     space. 
  Further,      allow        for       each       word         in          a     column         to         be     either       left            
justified,      right justified,         or     center  justified     within        its    column. 

   Given        a        text       file        of        many      lines,      where     fields     within        a        line               
    are    delineated     by          a       single    'dollar'  character,    write        a       program  
   that      aligns      each      column       of       fields       by      ensuring     that       words       in        each               
  column       are     separated     by         at        least       one      space.   
 Further,     allow       for       each       word        in          a       column       to         be       either      left               
justified,    right   justified,     or       center    justified   within       its      column.  
---------------------------
OK   
---------------------------

[edit] OxygenBasic




'================
Class AlignedText
'================

indexbase 1

string  buf, bufo, cr, tab, jus
sys     Cols, Rows, ColWidth[200], TotWidth, ColPad

method SetText(string s)
cr=chr(13)+chr(10)
tab=chr(9)
jus=string 200,"L"
buf=s
measure
end method


method measure()
sys a, b, wa, wb, cm, c, cw
a=1 : b=1
Cols=0 : Rows=0 : ColPad=3
do
  wb=b
  a=instr b,buf,cr
  if a=0 then exit do
  cm=0
  c++
  do
    wa=instr wb,buf,"$"
    if wa=0 or wa>a then exit do
    cm++
    if cm>cols then cols=cm
    cw=wa-wb
    if cw > ColWidth[cm] then ColWidth[cm]=cw
    wb=wa+1
  end do
  b=a+len cr
end do
rows=c
'
c=0
for i=1 to cols
  ColWidth[ i ]+=ColPad
  c+=ColWidth[ i ]
next
TotWidth=c+len cr
'print ShowMetrics
end method


method ShowMetrics() as string
pr="METRICS:" cr cr
pr+=rows tab cols tab totwidth cr cr
pr+="column" tab "spacing" cr
for i=1 to cols
  pr+=i tab ColWidth[ i ] cr
next
return pr
end method


method justify(string j)
mid jus,1,j
end method


method layout() as string
sys a, b, wa, wb, wl, cm, lpos, cpos
bufo=space Rows*TotWidth
a=1 : b=1
do
  wb=b
  a=instr(b,buf,cr)
  if a=0 then exit do
  cm=0
  cpos=1
  do
    wa=instr(wb,buf,"$")
    if wa=0 or wa>a then exit do
    '
    cm++
    '
    'JUSTIFICATION
    '
    wl=wa-wb
    p=lpos+cpos 'default "L" LEFT ALIGN
    '
    select case asc(jus,cm)
      case "R" : p=lpos+cpos+ColWidth[cm]-wl-Colpad
      case "C" : p=lpos+cpos+( ColWidth[cm]-wl-Colpad )*.5
    end select
    '
    mid bufo,p, mid buf,wb,wl
    cpos+=colwidth[cm]
    wb=wa+1
  end do
  b=a+len cr
  lpos+=TotWidth
  if lpos<len(bufo) then mid bufo,lpos-1,cr
end do
return bufo
end method

end class

'#recordof AlignedText

'====
'TEST
'====

AlignedText tt
tt.SetText quote
"""
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
"""
'print tt.ShowMetrics
tt.justify "LLLLCCCRRRRR"
putfile "t.txt", tt.layout

[edit] Oz

declare
%% Lines: list of strings
%% Alignment: function like fun {Left Txt ExtraSpace} ... end
%% Returns: list of aligned (virtual) strings
fun {Align Lines Alignment}
ParsedLines = {Map Lines ParseLine}
NumColumns = {Maximum {Map ParsedLines Record.width}}
%% maps column index to column width:
WidthOfColumn = {Record.map {TupleRange NumColumns}
fun {$ ColumnIndex}
fun {LengthOfThisColumn ParsedLine}
{Length {CondSelect ParsedLine ColumnIndex nil}}
end
in
{Maximum {Map ParsedLines LengthOfThisColumn}}
end}
in
{Map ParsedLines
fun {$ Columns}
{Record.mapInd Columns
fun {$ ColumnIndex ColumnText}
Extra = WidthOfColumn.ColumnIndex - {Length ColumnText}
in
{Alignment ColumnText Extra}#" "
end}
end}
end
 
%% A parsed line is a tuple of columns.
%% "a$b$c" -> '#'(1:"a" 2:"b" 3:"c")
fun {ParseLine Line}
{List.toTuple '#' {String.tokens Line &$}}
end
 
%% possible alignments:
 
fun {Left Txt Extra}
Txt#{Spaces Extra}
end
 
fun {Right Txt Extra}
{Spaces Extra}#Txt
end
 
fun {Center Txt Extra}
Half = Extra div 2
in
{Spaces Half}#Txt#{Spaces Half + Extra mod 2}
end
 
%% helpers:
 
%% 3 -> unit(1 2 3)
fun {TupleRange Max}
{List.toTuple unit {List.number 1 Max 1}}
end
 
fun {Maximum X|Xr}
{FoldL Xr Value.max X}
end
 
fun {Spaces N}
case N of 0 then nil
else & |{Spaces N-1}
end
end
 
Lines = ["Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
"are$delineated$by$a$single$'dollar'$character,$write$a$program"
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
"column$are$separated$by$at$least$one$space."
"Further,$allow$for$each$word$in$a$column$to$be$either$left$"
"justified,$right$justified,$or$center$justified$within$its$column."]
in
{ForAll {Align Lines Left} System.showInfo}

[edit] Pascal

See Delphi

[edit] Perl

#/usr/bin/perl -w
use strict ;
 
die "Call : perl columnaligner.pl <inputfile> <printorientation>!\n" unless
@ARGV == 2 ; #$ARGV[ 0 ] contains example file , $ARGV[1] any of 'left' , 'right' or 'center'
die "last argument must be one of center, left or right!\n" unless
$ARGV[ 1 ] =~ /center|left|right/ ;
sub printLines( $$$ ) ;
open INFILE , "<" , "$ARGV[ 0 ]" or die "Can't open $ARGV[ 0 ]!\n" ;
my @lines = <INFILE> ;
close INFILE ;
chomp @lines ;
my @fieldwidths = map length, split /\$/ , $lines[ 0 ] ;
foreach my $i ( 1..$#lines ) {
my @words = split /\$/ , $lines[ $i ] ;
foreach my $j ( 0..$#words ) {
if ( $j <= $#fieldwidths ) {
if ( length $words[ $j ] > $fieldwidths[ $j ] ) {
$fieldwidths[ $j ] = length $words[ $j ] ;
}
}
else {
push @fieldwidths, length $words[ $j ] ;
}
}
}
printLine( $_ , $ARGV[ 1 ] , \@fieldwidths ) foreach @lines ;
################################################################## ####
sub printLine {
my $line = shift ;
my $orientation = shift ;
my $widthref = shift ;
my @words = split /\$/, $line ;
foreach my $k ( 0..$#words ) {
my $printwidth = $widthref->[ $k ] + 1 ;
if ( $orientation eq 'center' ) {
$printwidth++ ;
}
if ( $orientation eq 'left' ) {
print $words[ $k ] ;
print " " x ( $printwidth - length $words[ $k ] ) ;
}
elsif ( $orientation eq 'right' ) {
print " " x ( $printwidth - length $words[ $k ] ) ;
print $words[ $k ] ;
}
elsif ( $orientation eq 'center' ) {
my $left = int( ( $printwidth - length $words[ $k ] ) / 2 ) ;
my $right = $printwidth - length( $words[ $k ] ) - $left ;
print " " x $left ;
print $words[ $k ] ;
print " " x $right ;
}
}
print "\n" ;
}

a shorter solution

use List::Util qw(max);
 
sub columns {
my @lines = map [split /\$/] => split /\n/ => shift;
my $pos = {qw/left 0 center 1 right 2/}->{+shift};
for my $col (0 .. max map {$#$_} @lines) {
my $max = max my @widths = map {length $_->[$col]} @lines;
for my $row (0 .. $#lines) {
my @pad = map {' ' x $_, ' ' x ($_ + 0.5)} ($max - $widths[$row]) / 2;
for ($lines[$row][$col])
{$_ = join '' => @pad[0 .. $pos-1], $_, @pad[$pos .. $#pad]}
}
}
join '' => map {"@$_\n"} @lines
}
 
print columns <<'END', $_ for qw(left right center);
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
END

[edit] Perl 6

###to be called with perl6 columnaligner.pl <orientation>(left, center , right )
###with left as default
my $fh = open "example.txt" , :r or die "Can't read text file!\n" ;
my @filelines = $fh.lines ;
close $fh ;
my @maxcolwidths ; #array of the longest words per column
#########fill the array with values#####################
for @filelines -> $line {
my @words = $line.split( "\$" ) ;
for 0..@words.elems - 1 -> $i {
if @maxcolwidths[ $i ] {
if @words[ $i ].chars > @maxcolwidths[$i] {
@maxcolwidths[ $i ] = @words[ $i ].chars ;
}
}
else {
@maxcolwidths.push( @words[ $i ].chars ) ;
}
}
}
my $justification = @*ARGS[ 0 ] || "left" ;
##print lines , $gap holds the number of spaces, 1 to be added
##to allow for space preceding or following longest word
for @filelines -> $line {
my @words = $line.split( "\$" ) ;
for 0 ..^ @words -> $i {
my $gap = @maxcolwidths[$i] - @words[$i].chars + 1 ;
if $justification eq "left" {
print @words[ $i ] ~ " " x $gap ;
} elsif $justification eq "right" {
print " " x $gap ~ @words[$i] ;
} elsif $justification eq "center" {
$gap = ( @maxcolwidths[ $i ] + 2 - @words[$i].chars ) div 2 ;
print " " x $gap ~ @words[$i] ~ " " x $gap ;
}
}
say ''; #for the newline
}

Or another way. To be called exactly as the first script.

my @lines = slurp("example.txt").lines;
my @widths;
 
for @lines { for .split('$').kv { @widths[$^key] max= $^word.chars; } }
for @lines { say .split('$').kv.map: { (align @widths[$^key], $^word) ~ " "; } }
 
sub align($column_width, $word, $aligment = @*ARGS[0]) {
my $lr = $column_width - $word.chars;
my $c = $lr / 2;
given ($aligment) {
when "center" { " " x $c.ceiling ~ $word ~ " " x $c.floor }
when "right" { " " x $lr ~ $word }
default { $word ~ " " x $lr }
}
}

[edit] PHP

<?php
$j2justtype = array('L' => STR_PAD_RIGHT,
'R' => STR_PAD_LEFT,
'C' => STR_PAD_BOTH);
 
/**
Justify columns of textual tabular input where the record separator is the newline
and the field separator is a 'dollar' character.
justification can be L, R, or C; (Left, Right, or Centered).
 
Return the justified output as a string
*/

function aligner($str, $justification = 'L') {
global $j2justtype;
assert(array_key_exists($justification, $j2justtype));
$justtype = $j2justtype[$justification];
 
$fieldsbyrow = array();
foreach (explode("\n", $str) as $line)
$fieldsbyrow[] = explode('$', $line);
$maxfields = max(array_map('count', $fieldsbyrow));
 
foreach (range(0, $maxfields-1) as $col) {
$maxwidth = 0;
foreach ($fieldsbyrow as $fields)
$maxwidth = max($maxwidth, strlen($fields[$col]));
foreach ($fieldsbyrow as &$fields)
$fields[$col] = str_pad($fields[$col], $maxwidth, ' ', $justtype);
unset($fields); // see http://bugs.php.net/29992
}
$result = '';
foreach ($fieldsbyrow as $fields)
$result .= implode(' ', $fields) . "\n";
return $result;
}
 
$textinfile = 'Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$\'dollar\'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.'
;
 
foreach (array('L', 'R', 'C') as $j)
echo aligner($textinfile, $j);
 
?>

[edit] PicoLisp

(let Sizes NIL                         # Build a list of sizes
(let Lines # and of lines
(make
(in "input.txt" # Reading input file
(while (split (line) "$") # delimited by '$'
(let (L (link (mapcar pack @)) S Sizes)
(setq Sizes # Maintain sizes
(make
(while (or L S)
(link
(max
(inc (length (pop 'L)))
(pop 'S) ) ) ) ) ) ) ) ) )
(for L Lines # Print lines
(prinl (apply align L (mapcar - Sizes))) ) # left aligned
(prinl)
(for L Lines
(prinl (apply align L Sizes)) ) # right aligned
(prinl)
(for L Lines
(prinl (apply center L Sizes)) ) ) ) # and centered

Output:

Given      a          text       file   of     many      lines,     where    fields  within  a      line  
are        delineated by         a      single 'dollar'  character, write    a       program              
that       aligns     each       column of     fields    by         ensuring that    words   in     each  
column     are        separated  by     at     least     one        space.                                
Further,   allow      for        each   word   in        a          column   to      be      either left  
justified, right      justified, or     center justified within     its      column.                      

      Given          a       text   file     of      many     lines,    where  fields  within      a line 
        are delineated         by      a single  'dollar' character,    write       a program             
       that     aligns       each column     of    fields         by ensuring    that   words     in each 
     column        are  separated     by     at     least        one   space.                             
   Further,      allow        for   each   word        in          a   column      to      be either left 
 justified,      right justified,     or center justified     within      its column.                     

   Given        a        text     file    of      many     lines,     where   fields  within    a   line 
    are    delineated     by        a   single  'dollar' character,   write     a    program             
   that      aligns      each    column   of     fields      by     ensuring   that   words    in   each 
  column       are     separated   by     at     least       one     space.                              
 Further,     allow       for     each   word      in         a      column     to      be   either left 
justified,    right   justified,   or   center justified   within      its   column.                     

[edit] PL/I

 
declare text character (300) varying;
declare word character (20) varying;
declare justification character (1);
declare k fixed binary;
declare input file, output file output;
 
open file (input) title ( '/CENTER.DAT,type(text),recsize(1000)' );
open file (output) title ( '/OUT.TXT,type(text),recsize(1000)' );
on endfile (input) stop;
 
display ('Specify whether justification is left, centered, or right');
display ('Reply with a single letter: L, C, or R');
get edit (justification) (A(1));
 
do forever;
get file (input) edit (text) (L);
put skip list (text);
text = trim(text, '$', '$');
do until (k = 0);
k = index(text, '$');
if k = 0 then /* last word in line */
word = text;
else
do;
word = substr(text, 1, k-1);
text = substr(text, k);
text = trim(text, '$');
end;
select (justification);
when ('C', 'c') word = center(word, maxlength(word));
when ('R', 'r') word = right (word, maxlength(word));
otherwise ; /* The default is left adjusted. */
end;
put file (output) edit (word) (a(maxlength(word)));
end;
put file (output) skip;
end;
 


[edit] Prolog

Works with SWI-Prolog.

aligner :-
L ="Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.",
 
% read the lines and the words
% compute the length of the longuest word.
% LP is the list of lines,
% each line is a list of words
parse(L, 0, N, LP, []),
 
% we need to add 1 to aligned
N1 is N+1,
% words will be left aligned
sformat(AL, '~~w~~t~~~w|', [N1]),
% words will be centered
sformat(AC, '~~t~~w~~t~~~w|', [N1]),
% words will be right aligned
sformat(AR, '~~t~~w~~~w|', [N1]),
 
write('Left justified :'), nl,
maplist(affiche(AL), LP), nl,
write('Centered justified :'), nl,
maplist(affiche(AC), LP), nl,
write('Right justified :'), nl,
maplist(affiche(AR), LP), nl.
 
affiche(F, L) :-
maplist(my_format(F), L),
nl.
 
my_format(_F, [13]) :-
nl.
 
my_format(F, W) :-
string_to_atom(W,AW),
sformat(AF, F, [AW]),
write(AF).
 
 
parse([], Max, Max) --> [].
 
parse(T, N, Max) -->
{ parse_line(T, 0, N1, T1, L, []),
( N1 > N -> N2 = N1; N2 = N)},
[L],
parse(T1, N2, Max).
 
parse_line([], NF, NF, []) --> [].
 
parse_line([H|TF], NF, NF, TF) -->
{code_type(H, end_of_line), !},
[].
 
 
parse_line(T, N, NF, TF) -->
{ parse_word(T, 0, N1, T1, W, []),
( N1 > N -> N2 = N1; N2 = N)},
[W],
parse_line(T1, N2, NF, TF).
 
% 36 is the code of '$'
parse_word([36|T], N, N, T) -->
{!},
[].
 
parse_word([H|T], N, N, [H|T]) -->
{code_type(H, end_of_line), !},
[].
 
parse_word([], N, N, []) --> [].
 
parse_word([H|T], N1, NF, TF) -->
[H],
{N2 is N1 + 1},
parse_word(T, N2, NF, TF).
 

Output :

 ?- aligner.
Left justified :
Given      a          text       file       of         many       lines,     where      fields     within     a          line       
are        delineated by         a          single     'dollar'   character, write      a          program    
that       aligns     each       column     of         fields     by         ensuring   that       words      in         each       
column     are        separated  by         at         least      one        space.     
Further,   allow      for        each       word       in         a          column     to         be         either     left       
justified, right      justified, or         center     justified  within     its        column.    

Centered justified :
   Given        a        text       file        of        many      lines,      where     fields     within        a        line    
    are    delineated     by          a       single    'dollar'  character,    write        a       program  
   that      aligns      each      column       of       fields       by      ensuring     that       words       in        each    
  column       are     separated     by         at        least       one      space.   
 Further,     allow       for       each       word        in          a       column       to         be       either      left    
justified,    right   justified,     or       center    justified   within       its      column.  

Right justified :
      Given          a       text       file         of       many     lines,      where     fields     within          a       line
        are delineated         by          a     single   'dollar' character,      write          a    program
       that     aligns       each     column         of     fields         by   ensuring       that      words         in       each
     column        are  separated         by         at      least        one     space.
   Further,      allow        for       each       word         in          a     column         to         be     either       left
 justified,      right justified,         or     center  justified     within        its    column.

true .

[edit] PureBasic

Works with: PureBasic version 4.41
Declare max(a,b)
 
If OpenConsole()
Define a, i, x, y, maxlen
Dim txt.s(0)
Restore lines ; Get address of the first data block
Read.i a
ReDim txt(a)
For i=0 To a ; Read the raw data lines
Read.s txt(i)
txt(i)=Trim(txt(i),"$") ; Remove any bad '$' that may be useless in the end...
x=max(CountString(txt(i),"$"),x)
Next
y=a
Dim matrix.s(x,y) ; Set up a nice matrix to work with, each word cleanly separated
For x=0 To ArraySize(matrix(),1)
For y=0 To ArraySize(matrix(),2)
matrix(x,y)=StringField(txt(y),x+1,"$")
maxlen=max(maxlen,Len(matrix(x,y)))
Next
Next
If maxlen%2
maxlen+1 ; Just to make sure that 'centered' output looks nice....
EndIf
 
PrintN(#CRLF$+"---- Right ----")
For y=0 To ArraySize(matrix(),2)
For x=0 To ArraySize(matrix(),1)
Print(RSet(matrix(x,y),maxlen+1))
Next
PrintN("")
Next
 
PrintN(#CRLF$+"---- Left ----")
For y=0 To ArraySize(matrix(),2)
For x=0 To ArraySize(matrix(),1)
Print(LSet(matrix(x,y),maxlen+1))
Next
PrintN("")
Next
 
PrintN(#CRLF$+"---- Center ----")
For y=0 To ArraySize(matrix(),2)
For x=0 To ArraySize(matrix(),1)
a=maxlen-Len(matrix(x,y))
Print(LSet(RSet(matrix(x,y),maxlen-a/2),maxlen))
Next
PrintN("")
Next
 
PrintN(#CRLF$+#CRLF$+"Press ENTER to quit."): Input()
CloseConsole()
EndIf
 
 
Procedure max(x,y)
If x>=y
ProcedureReturn x
Else
ProcedureReturn y
EndIf
EndProcedure
 
 
DataSection
lines:
Data.i 5 ; e.g. 6-1 since first line is equal to 'zero'.
text:
Data.s "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
Data.s "are$delineated$by$a$single$'dollar'$character,$write$a$program"
Data.s "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
Data.s "column$are$separated$by$at$least$one$space."
Data.s "Further,$allow$for$each$word$in$a$column$oo$be$either$left$"
Data.s "justified,$right$justified,$or$center$justified$within$its$column."
EndDataSection

[edit] Python

from StringIO import StringIO
 
textinfile = '''Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.'''

 
j2justifier = dict(L=str.ljust, R=str.rjust, C=str.center)
 
def aligner(infile, justification = 'L'):
''' \
Justify columns of textual tabular input where the row separator is the newline
and the field separator is a 'dollar' character.
justification can be L, R, or C; (Left, Right, or Centered).
 
Return the justified output as a string
'''

assert justification in j2justifier, "justification can be L, R, or C; (Left, Right, or Centered)."
justifier = j2justifier[justification]
 
fieldsbyrow= [line.strip().split('$') for line in infile]
# pad to same number of fields per row
maxfields = max(len(row) for row in fieldsbyrow)
fieldsbyrow = [fields + ['']*(maxfields - len(fields))
for fields in fieldsbyrow]
# rotate
fieldsbycolumn = zip(*fieldsbyrow)
# calculate max fieldwidth per column
colwidths = [max(len(field) for field in column)
for column in fieldsbycolumn]
# pad fields in columns to colwidth with spaces
fieldsbycolumn = [ [justifier(field, width) for field in column]
for width, column in zip(colwidths, fieldsbycolumn) ]
# rotate again
fieldsbyrow = zip(*fieldsbycolumn)
 
return "\n".join( " ".join(row) for row in fieldsbyrow)
 
 
for align in 'Left Right Center'.split():
infile = StringIO(textinfile)
print "\n# %s Column-aligned output:" % align
print aligner(infile, align[0])

Example output:

# Left Column-aligned output:
Given      a          text       file   of     many      lines,     where    fields  within  a      line 
are        delineated by         a      single 'dollar'  character, write    a       program             
that       aligns     each       column of     fields    by         ensuring that    words   in     each 
column     are        separated  by     at     least     one        space.                               
Further,   allow      for        each   word   in        a          column   to      be      either left 
justified, right      justified, or     center justified within     its      column.                     

# Right Column-aligned output:
     Given          a       text   file     of      many     lines,    where  fields  within      a line 
       are delineated         by      a single  'dollar' character,    write       a program             
      that     aligns       each column     of    fields         by ensuring    that   words     in each 
    column        are  separated     by     at     least        one   space.                             
  Further,      allow        for   each   word        in          a   column      to      be either left 
justified,      right justified,     or center justified     within      its column.                     

# Center Column-aligned output:
  Given        a         text     file    of      many     lines,    where    fields  within   a    line 
   are     delineated     by       a    single  'dollar' character,  write      a    program             
   that      aligns      each    column   of     fields      by     ensuring   that   words    in   each 
  column      are     separated    by     at     least      one      space.                              
 Further,    allow       for      each   word      in        a       column     to      be   either left 
justified,   right    justified,   or   center justified   within     its    column.                     

[edit] Alternative version

Translation of: D
txt = """Given$a$txt$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column."""

 
parts = [line.rstrip("$").split("$") for line in txt.splitlines()]
 
max_widths = {}
for line in parts:
for i, word in enumerate(line):
max_widths[i] = max(max_widths.get(i, 0), len(word))
 
for i, justify in enumerate([str.ljust, str.center, str.rjust]):
print ["Left", "Center", "Right"][i], " column-aligned output:\n"
for line in parts:
for j, word in enumerate(line):
print justify(word, max_widths[j]),
print
print "- " * 52

[edit] R

# Read in text
lines <- readLines(tc <- textConnection("Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.")); close(tc)
 
#Split words by the dollar
words <- strsplit(lines, "\\$")
 
#Reformat
maxlen <- max(sapply(words, length))
words <- lapply(words, function(x) {length(x) <- maxlen; x})
block <- matrix(unlist(words), byrow=TRUE, ncol=maxlen)
block[is.na(block)] <- ""
leftjust <- format(block)
rightjust <- format(block, justify="right")
centrejust <- format(block, justify="centre")
 
# Print
print0 <- function(x) invisible(apply(x, 1, function(x) cat(x, "\n")))
print0(leftjust)
print0(rightjust)
print0(centrejust)

Right justified output shown.

     Given          a       text       file         of       many     lines,      where     fields     within          a       line 
       are delineated         by          a     single   'dollar' character,      write          a    program                       
      that     aligns       each     column         of     fields         by   ensuring       that      words         in       each 
    column        are  separated         by         at      least        one     space.                                             
  Further,      allow        for       each       word         in          a     column         to         be     either       left 
justified,      right justified,         or     center  justified     within        its    column.                                  

[edit] Racket

 
#lang racket
 
(define (display-aligned text #:justify [justify 'left])
(define lines
(for/list ([line (regexp-split #rx"\n" text)])
(regexp-split #rx"\\$" line)))
(define width
(add1 (for*/fold ([m 0]) ([line lines] [word line])
(max m (string-length word)))))
(define spaces (make-string width #\space))
(for ([line lines])
(for* ([word line]
[strs (let ([spc (substring spaces (string-length word))])
(case justify
[(left) (list word spc)]
[(right) (list spc word)]
[(center) (let ([i (quotient (string-length spc) 2)])
(list (substring spc i)
word
(substring spc 0 i)))]))])
(display strs))
(newline)))
 
(define text
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.")
 
(display-aligned text)
(display-aligned #:justify 'right text)
(display-aligned #:justify 'center text)
 

[edit] REBOL

rebol [
Title: "Align Columns"
Author: oofoe
Date: 2010-09-29
URL: http://rosettacode.org/wiki/Align_columns
]

 
specimen: {Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.}
 
; Parse specimen into data grid.
 
data: copy []
foreach line parse specimen to-string lf [ ; Break into lines.
append/only data parse line "$" ; Break into columns.
]
 
; Compute independent widths for each column.
 
widths: copy [] insert/dup widths 0 length? data/1
foreach line data [
forall line [
i: index? line
widths/:i: max widths/:i length? line/1
]
]
 
pad: func [n /local x][x: copy "" insert/dup x " " n x]
 
; These formatting functions are passed as arguments to entable.
 
right: func [n s][rejoin [pad n - length? s s]]
 
left: func [n s][rejoin [s pad n - length? s]]
 
centre: func [n s /local h][
h: round/down (n - length? s) / 2
rejoin [pad h s pad n - h - length? s]
]
 
; Display data as table.
 
entable: func [data format] [
foreach line data [
forall line [
prin rejoin [format pick widths index? line line/1 " "]
]
print ""
]
]
 
; Format data table.
 
foreach i [left centre right] [
print ["^/Align" i "...^/"] entable data get i]
 

Sample output:

Align left ...

Given      a          text       file   of     many      lines,     where    fields  within  a      line
are        delineated by         a      single 'dollar'  character, write    a       program
that       aligns     each       column of     fields    by         ensuring that    words   in     each
column     are        separated  by     at     least     one        space.
Further,   allow      for        each   word   in        a          column   to      be      either left
justified, right      justified, or     center justified within     its      column.

Align centre ...

  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column.

Align right ...

     Given          a       text   file     of      many     lines,    where  fields  within      a line
       are delineated         by      a single  'dollar' character,    write       a program
      that     aligns       each column     of    fields         by ensuring    that   words     in each
    column        are  separated     by     at     least        one   space.
  Further,      allow        for   each   word        in          a   column      to      be either left
justified,      right justified,     or center justified     within      its column.

[edit] REXX

[edit] (no output)

/*REXX*/
z.1 = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
z.2 = "are$delineated$by$a$single$'dollar'$character,$write$a$program"
z.3 = "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
z.4 = "column$are$separated$by$at$least$one$space."
z.5 = "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
z.6 = "justified,$right$justified,$or$center$justified$within$its$column."
 
word. = ""
width. = 0
maxcol = 0
do row = 1 to 6
line = z.row
do col = 1 by 1 until length(line) = 0
parse var line word.row.col "$" line
if length(word.row.col) > width.col then width.col = length(word.row.col)
end
if col > maxcol then maxcol = col
end
 
say "align left:"
say
do row = 1 to 6
out = ""
do col = 1 to maxcol
out = out || left(word.row.col,width.col+1)
end
say out
end
say
say "align right:"
say
do row = 1 to 6
out = ""
do col = 1 to maxcol
out = out || right(word.row.col,width.col+1)
end
say out
end
say
say "align center:"
say
do row = 1 to 6
out = ""
do col = 1 to maxcol
out = out || center(word.row.col,width.col+1)
end
say out
end

[edit] (with output)

/*REXX program displays  various alignments  for words in a text string.*/
cols=0; size=0; wid.=0; t.=; @.= /*zero|nullify some variables*/
/* [↓] some "text" lines. */
t.1 = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
t.2 = "are$delineated$by$a$single$'dollar'$character,$write$a$program"
t.3 = "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
t.4 = "column$are$separated$by$at$least$one$space."
t.5 = "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
t.6 = "justified,$right$justified,$or$center$justified$within$its$column."
/* [↑] a null line is the end*/
do r=1 while t.r\=='' /* [↓] process all text lines*/
_=strip(t.r,,'$') /*strip leading & trailing $.*/
do c=1 until _=='' /* [↓] process each word. */
parse var _ @.r.c '$' _
wid.c=max(wid.c, length(@.r.c)) /*max word width.*/
end /*c*/
cols=max(cols,c) /*use the maximum COLS found.*/
end /*r*/
 
do k=1 for cols; size=size+wid.k; end /*find width of biggest line.*/
rows=r-1 /*adjust ROWS because of DO.*/
do j=1 for 3; say; say /*show 2 blank lines for sep.*/
say center(word('left right center', j) "aligned", size+cols-1, "═")
 
do r=1 for rows; _= /*build row by row*/
do c=1 for cols; x=@.r.c /* " col " col*/
if j==1 then _=_ left(x, wid.c) /*justified left.*/
if j==2 then _=_ right(x, wid.c) /* " right.*/
if j==3 then _=_ centre(x, wid.c) /* " center.*/
end /*c*/
say substr(_,2) /*ignore the leading extra blank.*/
end /*r*/
end /*j*/
/*stick a fork in it, we're done.*/

output

══════════════════════════════════════════════left aligned══════════════════════════════════════════════
Given      a          text       file   of     many      lines,     where    fields  within  a      line
are        delineated by         a      single 'dollar'  character, write    a       program
that       aligns     each       column of     fields    by         ensuring that    words   in     each
column     are        separated  by     at     least     one        space.
Further,   allow      for        each   word   in        a          column   to      be      either left
justified, right      justified, or     center justified within     its      column.


═════════════════════════════════════════════right aligned══════════════════════════════════════════════
     Given          a       text   file     of      many     lines,    where  fields  within      a line
       are delineated         by      a single  'dollar' character,    write       a program
      that     aligns       each column     of    fields         by ensuring    that   words     in each
    column        are  separated     by     at     least        one   space.
  Further,      allow        for   each   word        in          a   column      to      be either left
justified,      right justified,     or center justified     within      its column.


═════════════════════════════════════════════center aligned═════════════════════════════════════════════
  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column.

[edit] (boxed output)

Note: This version boxes each column of output to better show the columns.

/*REXX program displays  various alignments  for words in a text string.*/
cols=0; size=0; wid.=0; t.=; @.= /*zero|nullify some variables*/
/* [↓] some "text" lines. */
t.1 = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
t.2 = "are$delineated$by$a$single$'dollar'$character,$write$a$program"
t.3 = "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
t.4 = "column$are$separated$by$at$least$one$space."
t.5 = "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
t.6 = "justified,$right$justified,$or$center$justified$within$its$column."
/* [↑] a null line is the end*/
do r=1 while t.r\=='' /* [↓] process all text lines*/
_=strip(t.r,,'$') /*strip leading & trailing $.*/
do c=1 until _=='' /* [↓] process each word. */
parse var _ @.r.c '$' _
wid.c=max(wid.c, length(@.r.c)) /*max word width.*/
end /*c*/
cols=max(cols,c) /*use the maximum COLS found.*/
end /*r*/
 
do k=1 for cols; size=size+wid.k; end /*find width of biggest line.*/
rows=r-1 /*adjust ROWS because of DO.*/
do j=1 for 3; say; say /*show 2 blank lines for sep.*/
say center(word('left right center', j) "aligned", size+cols+1, "═")
 
do r=0 to rows; _=;  !='│'; if r==0 then !='┬'
do c=1 for cols; x=@.r.c
if r==0 then x=copies("─",wid.c+1)
if j==1 then _=_ || ! || left(x,wid.c)
if j==2 then _=_ || ! || right(x,wid.c)
if j==3 then _=_ || ! || centre(x,wid.c)
end /*c*/
if r==0 then do; _= '┌'substr(_,2,length(_)-1)"┐"
bot= '└'substr(_,2,length(_)-2)"┘"
end
else _=_ || !
say _
end /*r*/
/* [↑] shows words in boxes.*/
say translate(bot,'┴',"┬")
end /*j*/

output

═══════════════════════════════════════════════left aligned═══════════════════════════════════════════════
┌──────────┬──────────┬──────────┬──────┬──────┬─────────┬──────────┬────────┬───────┬───────┬──────┬────┐
│Given     │a         │text      │file  │of    │many     │lines,    │where   │fields │within │a     │line│
│are       │delineated│by        │a     │single│'dollar' │character,│write   │a      │program│      │    │
│that      │aligns    │each      │column│of    │fields   │by        │ensuring│that   │words  │in    │each│
│column    │are       │separated │by    │at    │least    │one       │space.  │       │       │      │    │
│Further,  │allow     │for       │each  │word  │in       │a         │column  │to     │be     │either│left│
│justified,│right     │justified,│or    │center│justified│within    │its     │column.│       │      │    │
└──────────┴──────────┴──────────┴──────┴──────┴─────────┴──────────┴────────┴───────┴───────┴──────┴────┘


══════════════════════════════════════════════right aligned═══════════════════════════════════════════════
┌──────────┬──────────┬──────────┬──────┬──────┬─────────┬──────────┬────────┬───────┬───────┬──────┬────┐
│     Given│         a│      text│  file│    of│     many│    lines,│   where│ fields│ within│     a│line│
│       are│delineated│        by│     a│single│ 'dollar'│character,│   write│      a│program│      │    │
│      that│    aligns│      each│column│    of│   fields│        by│ensuring│   that│  words│    in│each│
│    column│       are│ separated│    by│    at│    least│       one│  space.│       │       │      │    │
│  Further,│     allow│       for│  each│  word│       in│         a│  column│     to│     be│either│left│
│justified,│     right│justified,│    or│center│justified│    within│     its│column.│       │      │    │
└──────────┴──────────┴──────────┴──────┴──────┴─────────┴──────────┴────────┴───────┴───────┴──────┴────┘


══════════════════════════════════════════════center aligned══════════════════════════════════════════════
┌──────────┬──────────┬──────────┬──────┬──────┬─────────┬──────────┬────────┬───────┬───────┬──────┬────┐
│  Given   │    a     │   text   │ file │  of  │  many   │  lines,  │ where  │fields │within │  a   │line│
│   are    │delineated│    by    │  a   │single│'dollar' │character,│ write  │   a   │program│      │    │
│   that   │  aligns  │   each   │column│  of  │ fields  │    by    │ensuring│ that  │ words │  in  │each│
│  column  │   are    │separated │  by  │  at  │  least  │   one    │ space. │       │       │      │    │
│ Further, │  allow   │   for    │ each │ word │   in    │    a     │ column │  to   │  be   │either│left│
│justified,│  right   │justified,│  or  │center│justified│  within  │  its   │column.│       │      │    │
└──────────┴──────────┴──────────┴──────┴──────┴─────────┴──────────┴────────┴───────┴───────┴──────┴────┘

[edit] Ruby

J2justifier = {'L' => :ljust,
'R' => :rjust,
'C' => :center}
 
=begin
Justify columns of textual tabular input where the record separator is the newline
and the field separator is a 'dollar' character.
justification can be L, R, or C; (Left, Right, or Centered).
 
Return the justified output as a string
=end

def aligner(infile, justification = 'L')
fieldsbyrow = infile.map {|line| line.strip.split('$')}
# pad to same number of fields per record
maxfields = fieldsbyrow.map(&:length).max
fieldsbyrow.map! {|row| row + ['']*(maxfields - row.length)}
# calculate max fieldwidth per column
colwidths = fieldsbyrow.transpose.map {|column|
column.map(&:length).max
}
# pad fields in columns to colwidth with spaces
justifier = J2justifier[justification]
fieldsbyrow.map {|row|
row.zip(colwidths).map {|field, width|
field.send(justifier, width)
}.join(" ")
}.join("\n")
end
 
require 'stringio'
 
textinfile = <<END
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
END

 
for align in %w{Left Right Center}
infile = StringIO.new(textinfile)
puts "\n# %s Column-aligned output:" % align
puts aligner(infile, align[0..0])
end

Example output:

# Left Column-aligned output:
Given      a          text       file   of     many      lines,     where    fields  within  a      line
are        delineated by         a      single 'dollar'  character, write    a       program            
that       aligns     each       column of     fields    by         ensuring that    words   in     each
column     are        separated  by     at     least     one        space.                              
Further,   allow      for        each   word   in        a          column   to      be      either left
justified, right      justified, or     center justified within     its      column.                    

# Right Column-aligned output:
     Given          a       text   file     of      many     lines,    where  fields  within      a line
       are delineated         by      a single  'dollar' character,    write       a program            
      that     aligns       each column     of    fields         by ensuring    that   words     in each
    column        are  separated     by     at     least        one   space.                            
  Further,      allow        for   each   word        in          a   column      to      be either left
justified,      right justified,     or center justified     within      its column.                    

# Center Column-aligned output:
  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program            
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.                             
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column.                    

[edit] Run BASIC

theString$ = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" _
+ "are$delineated$by$a$single$'dollar'$character,$write$a$program" _
+ "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"_
+ "column$are$separated$by$at$least$one$space." _
+ "Further,$allow$for$each$word$in$a$column$to$be$either$left$" _
+ "justified,$right$justified,$or$center$justified$within$its$column."
 
x = shoTable(theString$,"left",6)
x = shoTable(theString$,"right",6)
x = shoTable(theString$,"center",6)
end
 
FUNCTION shoTable(theString$,align$,across)
print "------------ align:";align$;" -- across:";across;" ------------"
dim siz(across)
b$ = " "
while word$(theString$,i+1,"$") <> ""
siz(i mod across) = max(siz(i mod across),len(word$(theString$,i + 1,"$")))
i = i + 1
wend
for i = 0 to across - 1
siz(i) = siz(i) + 1
if siz(i) and 1 then siz(i) = siz(i) + 1
next i
 
i = 0
a$ = word$(theString$,i+1,"$")
while a$ <> ""
s = siz(i mod across) - len(a$)
if align$ = "right" then a$ = left$(b$,s);a$
if align$ = "left" then a$ = a$;left$(b$,s)
if align$ = "center" then a$ = left$(b$,int(s / 2));a$;left$(b$,int(s / 2) + (s and 1))
print "|";a$;
i = i + 1
if i mod across = 0 then print "|"
a$ = word$(theString$,i+1,"$")
wend
print
end function
Output:
------------ align:left -- across:6 ------------
|Given       |a           |text    |file        |of              |many      |
|lines,      |where       |fields  |within      |a               |line      |
|are         |delineated  |by      |a           |single          |'dollar'  |
|character,  |write       |a       |programthat |aligns          |each      |
|column      |of          |fields  |by          |ensuring        |that      |
|words       |in          |each    |column      |are             |separated |
|by          |at          |least   |one         |space.Further,  |allow     |
|for         |each        |word    |in          |a               |column    |
|to          |be          |either  |left        |justified,      |right     |
|justified,  |or          |center  |justified   |within          |its       |
|column.     
------------ align:right -- across:6 ------------
|       Given|           a|    text|        file|              of|      many|
|      lines,|       where|  fields|      within|               a|      line|
|         are|  delineated|      by|           a|          single|  'dollar'|
|  character,|       write|       a| programthat|          aligns|      each|
|      column|          of|  fields|          by|        ensuring|      that|
|       words|          in|    each|      column|             are| separated|
|          by|          at|   least|         one|  space.Further,|     allow|
|         for|        each|    word|          in|               a|    column|
|          to|          be|  either|        left|      justified,|     right|
|  justified,|          or|  center|   justified|          within|       its|
|     column.
------------ align:center -- across:6 ------------
|   Given    |     a      |  text  |    file    |       of       |   many   |
|   lines,   |   where    | fields |   within   |       a        |   line   |
|    are     | delineated |   by   |     a      |     single     | 'dollar' |
| character, |   write    |   a    |programthat |     aligns     |   each   |
|   column   |     of     | fields |     by     |    ensuring    |   that   |
|   words    |     in     |  each  |   column   |      are       |separated |
|     by     |     at     | least  |    one     | space.Further, |  allow   |
|    for     |    each    |  word  |     in     |       a        |  column  |
|     to     |     be     | either |    left    |   justified,   |  right   |
| justified, |     or     | center | justified  |     within     |   its    |
|  column.   

[edit] Scala

Works with: scala version 2.8.0.r18997-b20091009021954

For Scala 2.7, change from fromPath to fromFile, and remove the extra parameter to Source's getLines.

object ColumnAligner {
val eol = System.getProperty("line.separator")
def getLines(filename: String) = scala.io.Source.fromPath(filename).getLines(eol)
def splitter(line: String) = line split '$'
def getTable(filename: String) = getLines(filename) map splitter
def fieldWidths(fields: Array[String]) = fields map (_ length)
def columnWidths(txt: Iterator[Array[String]]) = (txt map fieldWidths).toList.transpose map (_ max)
 
def alignField(alignment: Char)(width: Int)(field: String) = alignment match {
case 'l' | 'L' => "%-"+width+"s" format field
case 'r' | 'R' => "%"+width+"s" format field
case 'c' | 'C' => val padding = (width - field.length) / 2; " "*padding+"%-"+(width-padding)+"s" format field
case _ => throw new IllegalArgumentException
}
 
def align(aligners: List[String => String])(fields: Array[String]) =
aligners zip fields map Function.tupled(_ apply _)
 
def alignFile(filename: String, alignment: Char) = {
def table = getTable(filename)
val aligners = columnWidths(table) map alignField(alignment)
table map align(aligners) map (_ mkString " ")
}
 
def printAlignedFile(filename: String, alignment: Char) {
alignFile(filename, alignment) foreach println
}
}

Another take:

def pad(s:String, i:Int, d:String) = {
val padsize = (i-s.length).max(0)
d match {
case "left" => s+" "*padsize
case "right" => " "*padsize+s
case "center" => " "*(padsize/2) + s + " "*(padsize-padsize/2)
}
}
 
val lines = scala.io.Source.fromFile("c:\\text.txt").getLines.map(_.trim())
val words = lines.map(_.split("\\$").toList).toList
val lens = words.map(l => l.map(_.length)).toList
 
var maxlens = Map[Int,Int]() withDefaultValue 0
lens foreach (l =>
for(i <- (0 until l.length)){
maxlens += i -> l(i).max(maxlens(i))
}
)
 
val padded = words map ( _.zipWithIndex.map{case(s,i)=>pad(s,maxlens(i),"center")+" "} )
padded map (_.reduceLeft(_ + _)) foreach println

[edit] sed

The code allows to left (by default) or right justify colums. Centering is not supported. Requires about 2x<size of input> bytes of memory (each line duplicated).

 
#!/bin/sed -nrf
# Format: <master-pattern>\n<line1>\n<line1-as-pattern>\n<line2>\n<line2-as-pattern>...
# After reading whole file <master-pattern> contains max number of fields of max width each.
 
# If no $ at start or end of a line -- add them
/^\$/! s/^/$/
/\$$/! s/$/$/
 
# First line saved as three lines in hold space:
# <line1-as-pattern>\n<line1>\n<line1-as-pattern>
1{
h
s/[^$]/ /g
H
G
x
# Restart -- go to next line
b
}
 
# For lines 2,3,...
H
# Current line -> pattern
# (each character replaced by constant symbol (e.g. space) so that we can count them)
s/[^$]/ /g
H
G
# Add two markers
s/\$/1$/
s/(\n[^$]*)\$/\12$/
 
# Compare patterns
:cmp
s/(1\$([^$\n]*)([^$\n]*)[^2]*2\$\2)/\1\3/
/1\$\n/ bout
# Advance markers
s/1(\$[^12$\n]*)/\11/
s/2(\$[^12$\n]*)/\12/
# Add one more field
/^[^2]*2\$\n/{ s/^([^2]*)2\$\n/\12$$\n/; }
bcmp
:out
# Remove first line
s/[^\n]*\n//
# Remove 2$-marker
s/2\$/$/
x
 
${
# We are on the last line -- start printing
x;
# Add a line for aligned string
s/^/\n/
:nextline
# Add marker again (only one this time)
s/\$/1$/
:align
# 1. look up missing spaces,
# 2. put first word of 2nd line before first newline adding missing spaces
# 3. cut first word of 2nd and 3rd lines.
# Replace \5\3 by \3\5 for RIGHT ALIGNMENT
s/(\n[^\n]*)1\$([^$\n]*)([^$\n]*)\$([^\n]*\n)\$([^$\n]*)([^\n]*\n)\$\2\$/\5\3 \1$\2\31$\4\6$/
talign
# We ate 2nd and 3rd lines completely, except newlines -- remove them
s/\$\n\$\n\$\n/$\n/
# Print the first line in pattern space
P
# ... and remove it
s/^[^\n]*//
# Remove marker
s/1\$/$/
# If no more lines -- exit
/\$\n\$$/q
bnextline
}
 

Example:

$ cat align.txt 
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
$ ./align-columns.sed align.txt 
Given      a          text       file   of     many      lines,     where    fields  within  a      line 
are        delineated by         a      single 'dollar'  character, write    a       program 
that       aligns     each       column of     fields    by         ensuring that    words   in     each 
column     are        separated  by     at     least     one        space.   
Further,   allow      for        each   word   in        a          column   to      be      either left 
justified, right      justified, or     center justified within     its      column. 

[edit] Seed7

$ include "seed7_05.s7i";
 
const array string: inputLines is [] (
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$",
"are$delineated$by$a$single$'dollar'$character,$write$a$program",
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$",
"column$are$separated$by$at$least$one$space.",
"Further,$allow$for$each$word$in$a$column$to$be$either$left$",
"justified,$right$justified,$or$center$justified$within$its$column.");
 
const func array integer: computeColumnWidths (in array string: inputLines) is func
result
var array integer: columnWidths is 0 times 0;
local
var string: line is "";
var array string: lineFields is 0 times "";
var integer: index is 0;
begin
for line range inputLines do
lineFields := split(line, "$");
if length(lineFields) > length(columnWidths) then
columnWidths &:= (length(lineFields) - length(columnWidths)) times 0;
end if;
for index range 1 to length(lineFields) do
if length(lineFields[index]) > columnWidths[index] then
columnWidths[index] := length(lineFields[index]);
end if;
end for;
end for;
end func;
 
const func string: center (in string: stri, in integer: length) is
return ("" lpad (length - length(stri)) div 2 <& stri) rpad length;
 
const proc: main is func
local
var array integer: columnWidths is 0 times 0;
var string: line is "";
var array string: lineFields is 0 times "";
var integer: index is 0;
begin
columnWidths := computeColumnWidths(inputLines);
for line range inputLines do
lineFields := split(line, "$");
for index range 1 to length(lineFields) do
# write(lineFields[index] rpad columnWidths[index] <& " "); # Left justify
# write(lineFields[index] lpad columnWidths[index] <& " "); # Right justify
write(center(lineFields[index], columnWidths[index]) <& " ");
end for;
writeln;
end for;
end func;

Output:

  Given        a         text     file    of     many      lines,    where   fields  within    a    line  
   are     delineated     by       a    single 'dollar'  character,  write      a    program 
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each  
  column      are     separated    by     at     least      one      space.  
 Further,    allow       for      each   word     in         a       column    to      be    either left  
justified,   right    justified,   or   center justified   within     its    column. 

[edit] Shiny

text: 'Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$\'dollar\'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.'
 
align: action text; position;
 
# split text into 2D array of lines and words
lines : { for text.split ~\$?\r?\n~ { for a.split '$' a end } end }
 
# calculate max required width for each column
widths: { for lines for a here[b]: a.length.max here[b]? ends }
 
spaces: action out ("%%%ds" in).format '' end
 
# formatting functions
left: action word; width;
pad: width-word.length
print "%s%s " word spaces pad
end
right: action word; width;
pad: width-word.length
print "%s%s " spaces pad word
end
center: action word; width;
pad: (width-word.length)/2
print "%s%s%s " spaces pad.floor word spaces pad.ceil
end
 
if position.match ~^(left|center|right)$~ for lines
for a local[position] a widths[b] end say ''
ends say ''
end
 
align text 'left'
align text 'center'
align text 'right'
Given      a          text       file   of     many      lines,     where    fields  within  a      line 
are        delineated by         a      single 'dollar'  character, write    a       program 
that       aligns     each       column of     fields    by         ensuring that    words   in     each 
column     are        separated  by     at     least     one        space.   
Further,   allow      for        each   word   in        a          column   to      be      either left 
justified, right      justified, or     center justified within     its      column. 

  Given        a         text     file    of     many      lines,    where   fields  within    a    line 
   are     delineated     by       a    single 'dollar'  character,  write      a    program 
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each 
  column      are     separated    by     at     least      one      space.  
 Further,    allow       for      each   word     in         a       column    to      be    either left 
justified,   right    justified,   or   center justified   within     its    column. 

     Given          a       text   file     of      many     lines,    where  fields  within      a line 
       are delineated         by      a single  'dollar' character,    write       a program 
      that     aligns       each column     of    fields         by ensuring    that   words     in each 
    column        are  separated     by     at     least        one   space. 
  Further,      allow        for   each   word        in          a   column      to      be either left 
justified,      right justified,     or center justified     within      its column.

[edit] Sidef

class Format(text, width) {
method output(j) {
self.text.each { |row|
row.pairs.each { |i, word|
'%-*s '.printf(self.width[i],
'%*s' % (word.len + (self.width[i]-word.len * j/2), word)
);
};
''.say;
};
''.say;
}
}
 
class Formatter(input) {
method new {
var textArr = [];
var widthArr = [];
 
self.input.each_line {
var words = .split('$');
textArr.append(words);
 
words.pairs.each { |i, word|
if (i == widthArr.len) {
widthArr.append(word.len);
}
elsif (word.len > widthArr[i]) {
widthArr[i] = word.len;
}
}
}
 
return main::Format(textArr, widthArr);
}
}
 
{
enum |left, middle, right|;
const text = <<'EOT';
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
EOT
 
var f = Formatter(text);
 
f.output(left);
f.output(middle);
f.output(right);
}.exec;

[edit] Tcl

package require Tcl 8.5
 
set text {Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.}
 
array set max {}
foreach line [split $text \n] {
set col 0
set thisline [split $line \$]
lappend words $thisline
foreach word $thisline {
set max([incr col]) [expr {[info exists max($col)]
? max($max($col), [string length $word])
 : [string length $word]
}]
}
}
 
proc justify {word position width} {
switch -exact -- $position {
left {
return [format "%-*s" $width $word]
}
center {
set lpadw [expr {($width - [string length $word])/2}]
return [format "%s%-*s" [string repeat " " $lpadw] [incr width -$lpadw] $word]
}
right {
return [format "%*s" $width $word]
}
}
}
 
foreach position {left center right} {
foreach thisline $words {
set col 0
set line ""
foreach word $thisline {
append line [justify $word $position $max([incr col])] " "
}
puts [string trimright $line]
}
puts ""
}

Output:

Given      a          text       file   of     many      lines,     where    fields  within  a      line
are        delineated by         a      single 'dollar'  character, write    a       program
that       aligns     each       column of     fields    by         ensuring that    words   in     each
column     are        separated  by     at     least     one        space.
Further,   allow      for        each   word   in        a          column   to      be      either left
justified, right      justified, or     center justified within     its      column.

  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column.

     Given          a       text   file     of      many     lines,    where  fields  within      a line
       are delineated         by      a single  'dollar' character,    write       a program
      that     aligns       each column     of    fields         by ensuring    that   words     in each
    column        are  separated     by     at     least        one   space.
  Further,      allow        for   each   word        in          a   column      to      be either left
justified,      right justified,     or center justified     within      its column.

[edit] TUSCRIPT

 
$$ MODE TUSCRIPT
MODE DATA
$$ SET exampletext=*
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
$$ MODE TUSCRIPT
SET nix=SPLIT (exampletext,":$:",c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12)
LOOP l1=1,12
SET colum=CONCAT ("c",l1)
SET newcolum=CONCAT ("new",l1)
SET @newcolum="", length=MAX LENGTH (@colum), space=length+2
LOOP n,l2=@colum
SET newcell=CENTER (l2,space)
SET @newcolum=APPEND (@newcolum,"~",newcell)
ENDLOOP
SET @newcolum=SPLIT (@newcolum,":~:")
ENDLOOP
SET exampletext=JOIN(new1,"$",new2,new3,new4,new5,new6,new7,new8,new9,new10,new11,new12)
 

Output:

   Given    $     a      $    text    $  file  $   of   $   many    $   lines,   $  where   $ fields  $ within  $   a    $ line$ 
    are     $ delineated $     by     $   a    $ single $ 'dollar'  $ character, $  write   $    a    $ program $        $       
    that    $   aligns   $    each    $ column $   of   $  fields   $     by     $ ensuring $  that   $  words  $   in   $ each$ 
   column   $    are     $ separated  $   by   $   at   $   least   $    one     $  space.  $         $         $        $       
  Further,  $   allow    $    for     $  each  $  word  $    in     $     a      $  column  $   to    $   be    $ either $ left$ 
 justified, $   right    $ justified, $   or   $ center $ justified $   within   $   its    $ column. $         $        $       

[edit] TXR

@(collect)
@ (coll)@{item /[^$]+/}@(end)
@(end)
@; nc = number of columns
@; pi = padded items (data with row lengths equalized with empty strings)
@; cw = vector of max column widths
@; ce = center padding
@(bind nc @[apply max [mapcar length item]])
@(bind pi @(mapcar (op append @1 (repeat '("") (- nc (length @1)))) item))
@(bind cw @(vector-list
(mapcar (op apply max [mapcar length @1])
 ;; matrix transpose trick cols become rows:
[apply mapcar [cons list pi]])))
@(bind ns "")
@(output)
@ (repeat)
@ (rep :counter i)@{pi @[cw i]} @(end)
@ (end)
@ (repeat)
@ (rep :counter i)@{pi @(- [cw i])} @(end)
@ (end)
@ (repeat)
@ (rep :counter i)@\
@{ns @(trunc (- [cw i] (length pi)) 2)}@\
@{pi @(- [cw i] (trunc (- [cw i] (length pi)) 2))} @(end)
@ (end)
@(end)
$ txr align-columns.txr align-columns.dat 
Given      a          text       file   of     many      lines,     where    fields  within  a      line 
are        delineated by         a      single 'dollar'  character, write    a       program             
that       aligns     each       column of     fields    by         ensuring that    words   in     each 
column     are        separated  by     at     least     one        space.                               
Further,   allow      for        each   word   in        a          column   to      be      either left 
justified, right      justified, or     center justified within     its      column.                     
     Given          a       text   file     of      many     lines,    where  fields  within      a line 
       are delineated         by      a single  'dollar' character,    write       a program             
      that     aligns       each column     of    fields         by ensuring    that   words     in each 
    column        are  separated     by     at     least        one   space.                             
  Further,      allow        for   each   word        in          a   column      to      be either left 
justified,      right justified,     or center justified     within      its column.                     
  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.     
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column.

[edit] UNIX Shell

This is a draft implementation of the "align columns" problem using Unix shell commands. The key tool for left and right justified text is the "rs" command. Centered text is a little more complex, since this is not a feature currently in "rs" (The centered solution will be added later.)

 
cat <<EOF_OUTER > just-nocenter.sh
#!/bin/sh
 
td() {
cat <<'EOF'
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
EOF

}
 
rows=$( td | wc -l )
 
# get the number of fields
fields=$(td | rs -c'$' -g1 -h | awk '{print $2}')
 
# get the max of the value widths
cwidth=$(td | rs -c'$' -g1 -w1 2>/dev/null | awk 'BEGIN{w=0}{if(length>w){w=length}}END{print w}')
 
# compute the minimum line width for the columns
lwidth=$(( (1 + cwidth) * fields ))
 
# left adjusted columns
td | rs -c'$' -g1 -zn -w$lwidth
 
echo ""
 
# right adjusted columns
td | rs -c'$' -g1 -znj -w$lwidth
 
echo ""
 
exit
EOF_OUTER
 

Output:

 
$ ./just-nocenter.sh
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 
Given a text file of many lines, where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
 

The centered output will be added later, when I've more time. I did this in about 10 minutes.

[edit] Ursala

The algorithm is to lex the text to a list of lists of strings assuming $ as a separator, then pad the lists out to the length of the maximum length list, transpose, do the same with each column, and transpose again. For left justification, nothing further but concatenation is needed. For right justification, each word's string of trailing blanks is moved to the beginning, and for center justification, the trailing blanks are divided equally between the beginning and end of each word.

#import std
 
text =
 
-[Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.]-
 
pad = sep`$*; @FS ~&rSSSK7+ (zipp` ^*D\~& leql$^)*rSSK7+ zipp0^*D/leql$^ ~&
 
just_left = mat` *+ pad
just_right = mat` *+ pad; ==` ~-rlT**
just_center = mat` *+ pad; ==` ~-rK30PlrK31PTT**
 
#show+
 
main = mat0 <.just_left,just_center,just_right> text

output:

Given      a          text       file   of     many      lines,     where    fields  within  a      line
are        delineated by         a      single 'dollar'  character, write    a       program            
that       aligns     each       column of     fields    by         ensuring that    words   in     each
column     are        separated  by     at     least     one        space.                              
Further,   allow      for        each   word   in        a          column   to      be      either left
justified, right      justified, or     center justified within     its      column.                    

  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program            
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.                             
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column.                    

     Given          a       text   file     of      many     lines,    where  fields  within      a line
       are delineated         by      a single  'dollar' character,    write       a program            
      that     aligns       each column     of    fields         by ensuring    that   words     in each
    column        are  separated     by     at     least        one   space.                            
  Further,      allow        for   each   word        in          a   column      to      be either left
justified,      right justified,     or center justified     within      its column.                    

[edit] VBA

Call subroutine "TestSplit" with arguments align (one of: "left", "right", "center") and spacing (an integer) between columns. Both arguments are optional and default to "left" and 1 respectively.

 
Public Sub TestSplit(Optional align As String = "left", Optional spacing As Integer = 1)
Dim word() As String
Dim colwidth() As Integer
Dim ncols As Integer
Dim lines(6) As String
Dim nlines As Integer
 
'check arguments
If Not (align = "left" Or align = "right" Or align = "center") Then
MsgBox "TestSplit: wrong argument 'align': " & align
Exit Sub
End If
If spacing < 0 Then
MsgBox "TestSplit: wrong argument: 'spacing' cannot be negative."
Exit Sub
End If
 
' Sample Input (should be from a file)
nlines = 6
lines(1) = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
lines(2) = "are$delineated$by$a$single$'dollar'$character,$write$a$program"
lines(3) = "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
lines(4) = "column$are$separated$by$at$least$one$space."
lines(5) = "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
lines(6) = "justified,$right$justified,$or$center$justified$within$its$column."
 
'first pass: count columns and column widths
'the words are not kept in memory
ncols = -1
For l = 1 To nlines
word = Split(RTrim(lines(l)), "$")
If UBound(word) > ncols Then
ncols = UBound(word)
ReDim Preserve colwidth(ncols)
End If
For i = 0 To UBound(word)
If Len(word(i)) > colwidth(i) Then colwidth(i) = Len(word(i))
Next i
Next l
 
'discard possibly empty columns at the right
'(this assumes there is at least one non-empty column)
While colwidth(ncols) = 0
ncols = ncols - 1
Wend
 
'second pass: print in columns
For l = 1 To nlines
word = Split(RTrim(lines(l)), "$")
For i = 0 To UBound(word)
a = word(i)
w = colwidth(i)
If align = "left" Then
Debug.Print a + String$(w - Len(a), " ");
ElseIf align = "right" Then
Debug.Print String$(w - Len(a), " ") + a;
ElseIf align = "center" Then
d = Int((w - Len(a)) / 2)
Debug.Print String$(d, " ") + a + String$(w - (d + Len(a)), " ");
End If
If i < ncols Then Debug.Print Spc(spacing);
Next i
Debug.Print
Next l
End Sub
 

Sample Output:

testsplit , 4 'default alignment, non-default spacing
Given         a             text          file      of        many         lines,        where       fields     within     a         line
are           delineated    by            a         single    'dollar'     character,    write       a          program    
that          aligns        each          column    of        fields       by            ensuring    that       words      in        each
column        are           separated     by        at        least        one           space.      
Further,      allow         for           each      word      in           a             column      to         be         either    left
justified,    right         justified,    or        center    justified    within        its         column.    


testsplit "center" 'non-default alignment, default spacing
  Given        a         text     file    of     many      lines,    where   fields  within    a    line
   are     delineated     by       a    single 'dollar'  character,  write      a    program 
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each
  column      are     separated    by     at     least      one      space.  
 Further,    allow       for      each   word     in         a       column    to      be    either left
justified,   right    justified,   or   center justified   within     its    column. 

[edit] Vedit macro language

This implementation converts the file currently being edited. The file can then be saved with different filename if required.

RS(10, "$")		// Field separator
#11 = 1 // Align: 1 = left, 2 = center, 3 = right
 
// Reset column widths. Max 50 columns
for (#1=40; #1<90; #1++) { #@1 = 0 }
 
// Find max width of each column
BOF
Repeat(ALL) {
for (#1=40; #1<90; #1++) {
Match(@10, ADVANCE) // skip field separator if any
#2 = Cur_Pos
Search("|{|@(10),|N}", NOERR) // field separator or end of line
#3 = Cur_Pos - #2 // width of text
if (#3 > #@1) { #@1 = #3 }
if (At_EOL) { Break }
}
Line(1, ERRBREAK)
}
 
// Convert lines
BOF
Repeat(ALL) {
for (#1=40; #1<90; #1++) {
#2 = Cur_Pos
Search("|{|@(10),|N}", NOERR)
if (At_EOL==0) { Del_Char(Chars_Matched) }
#3 = #@1 - Cur_Pos + #2 // number of spaces to insert
#4 = 0
if (#11 == 2) { #4 = #3/2; #3 -= #4 } // Center
if (#11 == 3) { #4 = #3; #3 = 0 } // Right justify
Set_Marker(1, Cur_Pos)
Goto_Pos(#2)
Ins_Char(' ', COUNT, #4) // add spaces before the word
Goto_Pos(Marker(1))
Ins_Char(' ', COUNT, #3+1) // add spaces after the word
if (At_EOL) { Break }
}
Line(1, ERRBREAK)
}

Example output:

-- Left:
Given      a          text       file   of     many      lines,     where    fields  within  a      line 
are        delineated by         a      single 'dollar'  character, write    a       program 
that       aligns     each       column of     fields    by         ensuring that    words   in     each 
column     are        separated  by     at     least     one        space.   
Further,   allow      for        each   word   in        a          column   to      be      either left 
justified, right      justified, or     center justified within     its      column. 

-- Center:
  Given        a         text     file    of     many      lines,    where   fields  within    a    line 
   are     delineated     by       a    single 'dollar'  character,  write      a    program 
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each 
  column      are     separated    by     at     least      one      space.  
 Further,    allow       for      each   word     in         a       column    to      be    either left 
justified,   right    justified,   or   center justified   within     its    column. 

-- Right:
     Given          a       text   file     of      many     lines,    where  fields  within      a line 
       are delineated         by      a single  'dollar' character,    write       a program 
      that     aligns       each column     of    fields         by ensuring    that   words     in each 
    column        are  separated     by     at     least        one   space. 
  Further,      allow        for   each   word        in          a   column      to      be either left 
justified,      right justified,     or center justified     within      its column.

[edit] Visual Basic .NET

 
Module Module1
 
 
Private Delegate Function Justification(s As String, width As Integer) As String
 
Private Function AlignColumns(lines As String(), justification As Justification) As String()
Const Separator As Char = "$"c
' build input container table and calculate columns count
Dim containerTbl As String()() = New String(lines.Length - 1)() {}
Dim columns As Integer = 0
For i As Integer = 0 To lines.Length - 1
Dim row As String() = lines(i).TrimEnd(Separator).Split(Separator)
If columns < row.Length Then
columns = row.Length
End If
containerTbl(i) = row
Next
' create formatted container table
Dim formattedTable As String()() = New String(containerTbl.Length - 1)() {}
For i As Integer = 0 To formattedTable.Length - 1
formattedTable(i) = New String(columns - 1) {}
Next
For j As Integer = 0 To columns - 1
' get max column width
Dim columnWidth As Integer = 0
For i As Integer = 0 To containerTbl.Length - 1
If j < containerTbl(i).Length AndAlso columnWidth < containerTbl(i)(j).Length Then
columnWidth = containerTbl(i)(j).Length
End If
Next
' justify column cells
For i As Integer = 0 To formattedTable.Length - 1
If j < containerTbl(i).Length Then
formattedTable(i)(j) = justification(containerTbl(i)(j), columnWidth)
Else
formattedTable(i)(j) = New [String](" "c, columnWidth)
End If
Next
Next
' create result
Dim result As String() = New String(formattedTable.Length - 1) {}
For i As Integer = 0 To result.Length - 1
result(i) = [String].Join(" ", formattedTable(i))
Next
Return result
End Function
 
Private Function JustifyLeft(s As String, width As Integer) As String
Return s.PadRight(width)
End Function
Private Function JustifyRight(s As String, width As Integer) As String
Return s.PadLeft(width)
End Function
Private Function JustifyCenter(s As String, width As Integer) As String
Return s.PadLeft((width + s.Length) / 2).PadRight(width)
End Function
 
Sub Main()
Dim input As String() = {"Given$a$text$file$of$many$lines,$where$fields$within$a$line$", "are$delineated$by$a$single$'dollar'$character,$write$a$program", "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$", "column$are$separated$by$at$least$one$space.", "Further,$allow$for$each$word$in$a$column$to$be$either$left$", "justified,$right$justified,$or$center$justified$within$its$column."}
 
For Each line As String In AlignColumns(input, AddressOf JustifyLeft)
Console.WriteLine(line)
Next
Console.ReadLine()
End Sub
 
End Module
 
 

Example output:

-- Left:
Given      a          text       file   of     many      lines,     where    fields  within  a      line 
are        delineated by         a      single 'dollar'  character, write    a       program 
that       aligns     each       column of     fields    by         ensuring that    words   in     each 
column     are        separated  by     at     least     one        space.   
Further,   allow      for        each   word   in        a          column   to      be      either left 
justified, right      justified, or     center justified within     its      column. 

-- Center:
  Given        a         text     file    of     many      lines,    where   fields  within    a    line 
   are     delineated     by       a    single 'dollar'  character,  write      a    program 
   that      aligns      each    column   of    fields       by     ensuring  that    words    in   each 
  column      are     separated    by     at     least      one      space.  
 Further,    allow       for      each   word     in         a       column    to      be    either left 
justified,   right    justified,   or   center justified   within     its    column. 

-- Right:
     Given          a       text   file     of      many     lines,    where  fields  within      a line 
       are delineated         by      a single  'dollar' character,    write       a program 
      that     aligns       each column     of    fields         by ensuring    that   words     in each 
    column        are  separated     by     at     least        one   space. 
  Further,      allow        for   each   word        in          a   column      to      be either left 
justified,      right justified,     or center justified     within      its column.

[edit] zkl

text:=
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$\n"
"are$delineated$by$a$single$'dollar'$character,$write$a$program\n"
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$\n"
"column$are$separated$by$at$least$one$space.\n"
"Further,$allow$for$each$word$in$a$column$to$be$either$left$\n"
"justified,$right$justified,$or$center$justified$within$its$column.\n";
 
fcn format(text,how){
words:=text.split("$").apply("split").flatten();
max:=words.reduce(fcn(p,n){n=n.len(); n>p and n or p},0);
wordsPerCol:=80/(max+1);
fmt:=(switch(how){
case(-1){"%%-%ds ".fmt(max).fmt}
case(0) {fcn(max,w){
a:=(max-w.len())/2; b:=max-w.len()-a; String(" "*a,w," "*b);
}.fp(max)
}
case(1){"%%%ds ".fmt(max).fmt}
});
w:=words.walker(); d:=Data(0,Int);
do{w.pump(wordsPerCol,d,fmt).append("\n");} while(not w.atEnd);
d.text;
}
 
format(text,-1).print();
format(text, 0).print();
format(text, 1).print();

Blow apart the text into a list of words, find max len of any word, calc how many words will fit on a 80 col line, format all words into a bit bucket line at a time. Formatting is "%-ms" or "%ms" for left & right justify (m is field width), calculated for center. fmt is the string format method or center calc function, depending. Where string formatting can be used, it would be better to format all words in a line in one go but the code would be longer.

Output:
Given      a          text       file       of         many       lines,     
where      fields     within     a          line       are        delineated 
by         a          single     'dollar'   character, write      a          
program    that       aligns     each       column     of         fields     
by         ensuring   that       words      in         each       column     
are        separated  by         at         least      one        space.     
Further,   allow      for        each       word       in         a          
column     to         be         either     left       justified, right      
justified, or         center     justified  within     its        column.    

  Given       a        text      file       of       many     lines,  
  where     fields    within      a        line      are    delineated
    by        a       single   'dollar' character,  write       a     
 program     that     aligns     each     column      of      fields  
    by     ensuring    that     words       in       each     column  
   are    separated     by        at      least      one      space.  
 Further,   allow      for       each      word       in        a     
  column      to        be      either     left   justified,  right   
justified,    or      center  justified   within     its     column.  

     Given          a       text       file         of       many     lines, 
     where     fields     within          a       line        are delineated 
        by          a     single   'dollar' character,      write          a 
   program       that     aligns       each     column         of     fields 
        by   ensuring       that      words         in       each     column 
       are  separated         by         at      least        one     space. 
  Further,      allow        for       each       word         in          a 
    column         to         be     either       left justified,      right 
justified,         or     center  justified     within        its    column. 
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox