Align columns: Difference between revisions
No edit summary |
(C (one way...)) |
||
Line 112: | Line 112: | ||
</pre> |
</pre> |
||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
<lang algol> |
|||
<pre> |
|||
STRING nl = REPR 10; |
STRING nl = REPR 10; |
||
STRING text in list := "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"+nl+ |
STRING text in list := "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"+nl+ |
||
Line 178: | Line 178: | ||
aligner(page, align OF aligners[index]) |
aligner(page, align OF aligners[index]) |
||
OD |
OD |
||
END</ |
END</lang> |
||
=={{header|C}}== |
|||
<lang c>#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
struct linelement { |
|||
char **wordlist; |
|||
int longest; |
|||
struct linelement *next; |
|||
}; |
|||
typedef struct linelement line_t; |
|||
char *trim(char *s, int *len) |
|||
{ |
|||
char *b; |
|||
int l; |
|||
while( (*s == ' ') || (*s == '\t') ) s++; |
|||
b = s; |
|||
l = strlen(b); |
|||
s += l; s--; |
|||
while( (*s == ' ') || (*s == '\t') ) s--; |
|||
s++; *s = 0; |
|||
if ( l > *len ) *len = l; |
|||
return b; |
|||
} |
|||
char **split(char *l, int c, int *longest) |
|||
{ |
|||
int howmany, i; |
|||
char **arr; |
|||
char *n; |
|||
if ( (n = strchr(l, 10)) != NULL ) *n = 0; |
|||
if ( (n = strchr(l, 13)) != NULL ) *n = 0; |
|||
for(howmany=1, i=0; l[i] != 0 ; i++) |
|||
if ( (l[i]==c) && ((i+1) < strlen(l))) howmany++; |
|||
arr = malloc(sizeof(char *) * (howmany+1)); |
|||
arr[0] = NULL; |
|||
if ( arr != NULL ) { |
|||
n = l; |
|||
for(i=0; i < howmany; i++) { |
|||
arr[i] = n; |
|||
n = strchr(n, c); |
|||
if ( n == NULL ) { break; } |
|||
*n = 0; n++; |
|||
arr[i] = trim(arr[i], longest); |
|||
} |
|||
} |
|||
arr[howmany] = NULL; |
|||
return arr; |
|||
} |
|||
#define MAXLINELEN 1024 |
|||
#define FILLCHAR ' ' |
|||
/* decide the alignment */ |
|||
enum textalign { |
|||
LEFT_ALIGNED, RIGHT_ALIGNED, CENTER_ALIGNED |
|||
}; |
|||
const int alignment = CENTER_ALIGNED; |
|||
int main() |
|||
{ |
|||
char buf[MAXLINELEN]; |
|||
line_t *head, *cur; |
|||
char *lb; |
|||
int reallongest, i, len, ipos; |
|||
head = malloc(sizeof(line_t)); |
|||
memset(head, 0, sizeof(line_t)); |
|||
/* for each line, split it ($-separated words) */ |
|||
cur = head; |
|||
while ( fgets(buf, MAXLINELEN, stdin) != NULL ) { |
|||
lb = malloc(strlen(buf)); |
|||
strncpy(lb, buf, strlen(buf)); |
|||
cur->wordlist = split(lb, '$', &(cur->longest)); |
|||
cur->next = malloc(sizeof(line_t)); |
|||
memset(cur->next, 0, sizeof(line_t)); |
|||
cur = cur->next; |
|||
} |
|||
cur->next = NULL; /* last node is a end-marker */ |
|||
/* each line holds the longest word length; find the |
|||
longest among all lines; this determines the width |
|||
of all columns */ |
|||
reallongest = head->longest; |
|||
cur = head; |
|||
while( cur->next != NULL ) { |
|||
if ( cur->longest > reallongest ) |
|||
reallongest = cur->longest; |
|||
cur = cur->next; |
|||
} |
|||
reallongest++; |
|||
buf[reallongest] = 0; /* no bounds check... */ |
|||
/* print the columns */ |
|||
cur = head; |
|||
while( cur->next != NULL ) { |
|||
for(i=0; cur->wordlist[i] != NULL; i++) { |
|||
len = strlen(cur->wordlist[i]); |
|||
switch(alignment) { |
|||
case LEFT_ALIGNED: |
|||
ipos = 0; |
|||
break; |
|||
case RIGHT_ALIGNED: |
|||
ipos = reallongest - len; |
|||
break; |
|||
case CENTER_ALIGNED: |
|||
ipos = (reallongest - len)/2; |
|||
break; |
|||
} |
|||
memset(buf, FILLCHAR, reallongest); |
|||
memcpy(buf+ipos, cur->wordlist[i], len); |
|||
printf("%s ", buf); |
|||
} |
|||
printf("\n"); |
|||
cur = cur->next; |
|||
} |
|||
}</lang> |
|||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
<lang haskell> |
|||
<pre> |
|||
import Data.List |
import Data.List |
||
import Control.Monad |
import Control.Monad |
||
Line 211: | Line 339: | ||
| odd dl = (hdl,hdl+1) |
| odd dl = (hdl,hdl+1) |
||
| otherwise = (hdl,hdl) |
| otherwise = (hdl,hdl) |
||
</ |
</lang> |
||
output example: |
output example: |
||
<pre> |
<pre> |
Revision as of 22:21, 2 March 2009
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:
- The example input texts lines may, or may not, have trailing dollar characters.
- All columns should share the same alignment.
- Consecutive space characters produced adjacent to the end of lines are insignificant for the purposes of the task.
- Output text will be viewed in a mono-spaced font.
Ada
<lang 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; </lang> 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.
ALGOL 68
<lang algol> 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</lang>
C
<lang c>#include <stdio.h>
- include <stdlib.h>
- include <string.h>
struct linelement {
char **wordlist; int longest; struct linelement *next;
};
typedef struct linelement line_t;
char *trim(char *s, int *len) {
char *b; int l;
while( (*s == ' ') || (*s == '\t') ) s++; b = s; l = strlen(b); s += l; s--; while( (*s == ' ') || (*s == '\t') ) s--; s++; *s = 0; if ( l > *len ) *len = l; return b;
}
char **split(char *l, int c, int *longest) {
int howmany, i; char **arr; char *n;
if ( (n = strchr(l, 10)) != NULL ) *n = 0; if ( (n = strchr(l, 13)) != NULL ) *n = 0;
for(howmany=1, i=0; l[i] != 0 ; i++) if ( (l[i]==c) && ((i+1) < strlen(l))) howmany++; arr = malloc(sizeof(char *) * (howmany+1)); arr[0] = NULL; if ( arr != NULL ) { n = l; for(i=0; i < howmany; i++) { arr[i] = n; n = strchr(n, c); if ( n == NULL ) { break; } *n = 0; n++; arr[i] = trim(arr[i], longest); } } arr[howmany] = NULL; return arr;
}
- define MAXLINELEN 1024
- define FILLCHAR ' '
/* decide the alignment */ enum textalign {
LEFT_ALIGNED, RIGHT_ALIGNED, CENTER_ALIGNED
}; const int alignment = CENTER_ALIGNED;
int main()
{
char buf[MAXLINELEN]; line_t *head, *cur; char *lb; int reallongest, i, len, ipos;
head = malloc(sizeof(line_t)); memset(head, 0, sizeof(line_t));
/* for each line, split it ($-separated words) */ cur = head; while ( fgets(buf, MAXLINELEN, stdin) != NULL ) { lb = malloc(strlen(buf)); strncpy(lb, buf, strlen(buf)); cur->wordlist = split(lb, '$', &(cur->longest)); cur->next = malloc(sizeof(line_t)); memset(cur->next, 0, sizeof(line_t)); cur = cur->next; } cur->next = NULL; /* last node is a end-marker */
/* each line holds the longest word length; find the longest among all lines; this determines the width of all columns */ reallongest = head->longest; cur = head; while( cur->next != NULL ) { if ( cur->longest > reallongest ) reallongest = cur->longest; cur = cur->next; }
reallongest++; buf[reallongest] = 0; /* no bounds check... */
/* print the columns */ cur = head; while( cur->next != NULL ) { for(i=0; cur->wordlist[i] != NULL; i++) { len = strlen(cur->wordlist[i]); switch(alignment) { case LEFT_ALIGNED:
ipos = 0; break;
case RIGHT_ALIGNED:
ipos = reallongest - len; break;
case CENTER_ALIGNED:
ipos = (reallongest - len)/2; break;
} memset(buf, FILLCHAR, reallongest); memcpy(buf+ipos, cur->wordlist[i], len); printf("%s ", buf); } printf("\n"); cur = cur->next; }
}</lang>
Haskell
<lang 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 = unfoldr (\xs -> if null xs then Nothing else Just (second (drop 1) (span ('$'/=) xs)) ) spas = repeat ' '
format j ls = map (concat. zipWith align colw) rows
where rows = map brkdwn $ lines ls colw = map (maximum. map length) . transpose $ rows align cw w = case j of 'c' -> (take l spas) ++ w ++ (take (succ r) spas) 'r' -> (take dl spas)++w++" " 'l' -> w ++ (take (succ dl) spas) where dl = cw-length w hdl = dl `div` 2 (l,r) | odd dl = (hdl,hdl+1) | otherwise = (hdl,hdl)
</lang> 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.
J
Solution, using 'LEFT CENTER RIGHT'=:i.3 to specify justification:
_2 {:\ ": <;._2@:,~&>/ '$';LF;text [ 9!:17 ,~ CENTER [ 9!:7 ' '$~11
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. ) _2 {:\ ": <;._2@:,~&>/'$';LF;text [ 9!:17 ,~ CENTER [ 9!:7 ' '$~11 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.
OCaml
<lang 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);
- </lang>
Perl
<lang 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[ 0 ] =~ /center|left|right/ ; sub printLines( $$$ ) ; open ( INFILE , "<" , "$ARGV[ 0 ]" ) or die "Can't open $ARGV[ 0 ]!\n" ; my @lines = <INFILE> ; close ( INFILE ) ; map { chomp $_ } @lines ; my @fieldwidths = ( ) ; map { push @fieldwidths , 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 ] ) ; } } } map { printLine( $_ , $ARGV[ 1 ] , \@fieldwidths ) } @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 ] ; for ( my $i = 0 ; $i < $printwidth - length( $words[ $k ] ) ; $i++ ) { print " " ; } } if ( $orientation eq 'right' ) { for ( my $i = 0 ; $i < $printwidth - length( $words[ $k ] ) ; $i++ ) { print " " ; } print $words[ $k ] ; } if ( $orientation eq 'center' ) { my $left = int( ( $printwidth - length( $words[ $k ] ) ) / 2 ) ; my $right = $printwidth - length( $words[ $k ] ) - $left ; if ( $left == 1 ) { print " " ; } if ( $left > 1 ) { for ( my $i = 0 ; $i < $left ; $i++ ) { print " " ; } } print $words[ $k ] ; if ( $right == 1 ) { print " " ; } if ( $right > 1 ) { for ( my $i = 0 ; $i < $right ; $i++ ) { print " " ; } } } } print "\n" ; }
</lang>
Python
<lang 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 'LRC', "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])</lang>
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.
Ruby
<lang ruby>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
J2justifier = {'L' => String.instance_method(:ljust),
'R' => String.instance_method(:rjust), 'C' => String.instance_method(: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')
justifier = J2justifier[justification] fieldsbyrow = infile.map {|line| line.strip.split('$')} # pad to same number of fields per record maxfields = fieldsbyrow.map {|row| row.length}.max fieldsbyrow.map! {|row| row + []*(maxfields - row.length) } # calculate max fieldwidth per column colwidths = fieldsbyrow.transpose.map {|column| column.map {|field| field.length}.max } # pad fields in columns to colwidth with spaces fieldsbyrow.map! {|row| row.zip(colwidths).map {|field, width| justifier.bind(field)[width] } } fieldsbyrow.map {|row| row.join(" ")}.join("\n")
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</lang>
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.
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.