Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -1,22 +1,22 @@
import std.stdio, std.string, std.algorithm, std.range, std.typetuple;
void main() {
auto data =
import std.stdio, std.string, std.algorithm, std.range, std.typetuple;
immutable 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("$"));
.split.map!(r => r.chomp("$").split("$")).array;
int[int] maxWidths;
size_t[size_t] 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)
foreach (immutable just; TypeTuple!(leftJustify, center, rightJustify))
foreach (immutable line; data)
writefln("%-(%s %)", line.length.iota
.map!(i => just(line[i], maxWidths[i], ' ')));
}

View file

@ -0,0 +1,48 @@
//break up each string by '$'. The assumption is that the user wants the trailing $.
var 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."
].map(function (str) { return str.split('$'); })
//boilerplate: get longest array or string in array
var getLongest = function (arr) {
return arr.reduce(function (acc, item) { return acc.length > item.length ? acc : item; }, 0);
};
//boilerplate: this function would normally be in a library like underscore, lodash, or ramda
var zip = function (items, toInsert) {
toInsert = (toInsert === undefined) ? null : toInsert;
var longestItem = getLongest(items);
return longestItem.map(function (_unused, index) {
return items.map(function (item) {
return item[index] === undefined ? toInsert : item[index];
});
});
};
//here's the part that's not boilerplate
var makeColumns = function (formatting, data) {
var zipData = zip(data, '');
var makeSpaces = function (num) { return new Array(num + 1).join(' '); };
var formattedCols = zipData.map(function (column) {
var maxLen = getLongest(column).length;//find the maximum word length
if (formatting === 'left') {
return column.map(function (word) { return word + makeSpaces(maxLen - word.length); });
} else if (formatting === 'right') {
return column.map(function (word) { return makeSpaces(maxLen - word.length) + word; });
} else {
return column.map(function (word) {
var spaces = maxLen - word.length,
first = ~~(spaces / 2),
last = spaces - first;
return makeSpaces(first) + word + makeSpaces(last);
});
}
});
return zip(formattedCols).map(function (row) { return row.join(' '); }).join('\n');
};

View file

@ -0,0 +1,107 @@
MODULE Columns;
IMPORT
NPCT:Tools,
Object,
Out;
TYPE
Parts = ARRAY 32 OF STRING;
Formatter = PROCEDURE (s: STRING; len: LONGINT): STRING;
VAR
lines: ARRAY 6 OF STRING;
words: ARRAY 6 OF Parts;
columnWidth: ARRAY 128 OF INTEGER;
lineIdx: INTEGER;
(*
* Size: returns de number of words in a line
*)
PROCEDURE Size(p: Parts): INTEGER;
VAR
i: INTEGER;
BEGIN
i := 0;
WHILE (i < LEN(p)) & (p[i] # NIL) DO
INC(i);
END;
RETURN i
END Size;
(*
* Max: returns maximum number of words in the lines
*)
PROCEDURE Max(w: ARRAY OF Parts): INTEGER;
VAR
i, max, resp: INTEGER;
BEGIN
i := 0;resp := 0;
WHILE (i < LEN(w)) DO
max := Size(w[i]);
IF (max > resp) THEN resp := max END;
INC(i)
END;
RETURN resp;
END Max;
(*
* MaxColumnWidth: returns the maximum width of a column
*)
PROCEDURE MaxColumnWidth(w: ARRAY OF Parts;column: INTEGER): INTEGER;
VAR
line,max: LONGINT;
BEGIN
line := 0;
max := MIN(INTEGER);
WHILE (line < LEN(w)) DO;
IF (w[line,column] # NIL) & (w[line,column](Object.String8).length > max) THEN max := w[line,column](Object.String8).length END;
INC(line)
END;
RETURN SHORT(max)
END MaxColumnWidth;
(*
* PrintWords: prints the words in 'w' using the formatter passed in 'format'
*)
PROCEDURE PrintWords(w: ARRAY OF Parts; format: Formatter);
VAR
i,j: INTEGER;
BEGIN
i := 0;
WHILE (i < LEN(words)) DO
j := 0;
WHILE (j < Max(words)) & (words[i,j] # NIL) DO
Out.Object(format(words[i,j],columnWidth[j] + 1));
INC(j)
END;
Out.Ln;
INC(i)
END;
Out.Ln
END PrintWords;
BEGIN
lines[0] := "Given$a$text$file$of$many$lines,$where$fields$within$a$line$";
lines[1] := "are$delineated$by$a$single$'dollar'$character,$write$a$program";
lines[2] := "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$";
lines[3] := "column$are$separated$by$at$least$one$space.";
lines[4] := "Further,$allow$for$each$word$in$a$column$to$be$either$left$";
lines[5] := "justified,$right$justified,$or$center$justified$within$its$column.";
(* Split line in words *)
lineIdx := 0;
WHILE lineIdx < LEN(lines) DO
Tools.Split(lines[lineIdx],"$",words[lineIdx]);
INC(lineIdx)
END;
(* Calculate width of the column *)
lineIdx := 0;
WHILE (lineIdx < Max(words)) DO
columnWidth[lineIdx] := MaxColumnWidth(words,lineIdx);
INC(lineIdx)
END;
(* Print Results *)
PrintWords(words,Tools.AdjustLeft);
PrintWords(words,Tools.AdjustCenter);
PrintWords(words,Tools.AdjustRight);
END Columns.

View file

@ -1,35 +1,34 @@
/*REXX program to display various alignments. */
cols=0; size=0; wid.=0; t.=; @.=
/*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."
do r=1 while t.r\==''
_=strip(t.r,,'$')
do c=1 until _==''
parse var _ @.r.c '$' _
wid.c=max(wid.c,length(@.r.c))
end /*c*/
cols=max(cols,c)
/* [↑] 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*/
rows=r-1 /*adjust ROWS, it's 1 too big*/
do k=1 for cols; size=size+wid.k; end /*find width of biggest line.*/
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 j=1 for 3; say
say center(word('left right center',j) "aligned",size+cols-1,"=")
do r=1 for rows; _=
do c=1 for cols; x=@.r.c
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*/
say substr(_,2)
end /*r*/
say
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.*/

View file

@ -1,43 +1,40 @@
/*REXX program to display various alignments. */
cols=0; parse var cols size 1 wid. t. /*initializations.*/
/*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 r=1 while t.r\==''
t.r=translate(t.r,,'$')
do c=1 until word(t.r,c)==''
wid.c=max(wid.c,length(word(t.r,c)))
end /*c*/
cols=max(cols,c)
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, "")
rows=r-1 /*adjust ROWS, it's 1 too big*/
do k=1 for cols; size=size+wid.k; end /*find width of biggest line.*/
do j=1 for 3; say
say center(word('left right center',j) "aligned",size+cols,"="); say
do r=0 to rows; _=; !=''; if r==0 then !=''
do c=1 for cols; x=word(t.r,c)
if r==0 then x=copies("",wid.c+1)
else x=word(t.r,c)
if j==1 then _=_ || ! || left(x,wid.c)
if j==2 then _=_ || ! || right(x,wid.c)
if j==3 then _=_ || ! || centre(x,wid.c)
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(_)-2)""
bot=''substr(_,2,length(_)-2)""
if r==0 then do; _= ''substr(_,2,length(_)-1)""
bot= ''substr(_,2,length(_)-2)""
end
else _=_ || !
say _
end /*r*/
say translate(bot,'',""); say; say
/* [↑] shows words in boxes.*/
say translate(bot,'',"")
end /*j*/

View file

@ -0,0 +1,41 @@
Dim MText as QMemorystream
MText.WriteLine "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
MText.WriteLine "are$delineated$by$a$single$'dollar'$character,$write$a$program"
MText.WriteLine "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
MText.WriteLine "column$are$separated$by$at$least$one$space."
MText.WriteLine "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
MText.WriteLine "justified,$right$justified,$or$center$justified$within$its$column."
DefStr TextLeft, TextRight, TextCenter
DefStr MLine, LWord, Newline = chr$(13)+chr$(10)
DefInt ColWidth(100), ColCount
DefSng NrSpaces
'Find column widths
MText.position = 0
for x = 0 to MText.linecount -1
MLine = MText.ReadLine
for y = 0 to Tally(MLine, "$")
LWord = Field$(MLine, "$", y+1)
ColWidth(y) = iif (ColWidth(y) < len(LWord), len(LWord), ColWidth(y))
next
next
'Create aligned wordlists
MText.position = 0
for x = 0 to MText.linecount -1
MLine = MText.ReadLine
for y = 0 to Tally(MLine, "$")
LWord = Field$(MLine, "$", y+1)
NrSpaces = ColWidth(y) - len(LWord)
'left align
TextLeft = TextLeft + LWord + Space$(NrSpaces+1)
'Right align
TextRight = TextRight + Space$(NrSpaces+1) + LWord
'Center
TextCenter = TextCenter + Space$(floor((NrSpaces)/2)+1) + LWord + Space$(Ceil((NrSpaces)/2))
next
TextLeft = TextLeft + Newline
TextRight = TextRight + Newline
TextCenter = TextCenter + Newline
next

View file

@ -1,3 +1,32 @@
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
@ -9,40 +38,6 @@ 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

View file

@ -0,0 +1,62 @@
#![feature(core)]
extern crate core;
use core::iter::repeat;
use core::str::StrExt;
use std::iter::Extend;
enum AlignmentType { Left, Center, Right }
fn get_column_widths(text: &str) -> Vec<usize> {
let mut widths = Vec::new();
for line in text.lines().map(|s| s.trim_matches(' ').trim_right_matches('$')) {
let mut lens = line.split('$').map(|s| s.char_len());
let mut idx = 0;
for len in lens {
if idx < widths.len() {
widths[idx] = std::cmp::max(widths[idx], len);
}
else {
widths.push(len);
}
idx += 1;
}
}
widths
}
fn align_columns(text: &str, alignment: AlignmentType) -> String {
let widths = get_column_widths(text);
let mut result = String::new();
for line in text.lines().map(|s| s.trim_matches(' ').trim_right_matches('$')) {
for (s, w) in line.split('$').zip(widths.iter()) {
let blank_count = w - s.char_len();
let (pre, post) = match alignment {
AlignmentType::Left => (0, blank_count),
AlignmentType::Center => (blank_count / 2, (blank_count + 1) / 2),
AlignmentType::Right => (blank_count, 0),
};
result.extend(repeat(' ').take(pre));
result.push_str(s);
result.extend(repeat(' ').take(post));
result.push(' ');
}
result.push_str("\n");
}
result
}
fn main() {
let text = r#"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!("{}", align_columns(text, AlignmentType::Left));
println!("{}", repeat('-').take(110).collect::<String>());
println!("{}", align_columns(text, AlignmentType::Center));
println!("{}", repeat('-').take(110).collect::<String>());
println!("{}", align_columns(text, AlignmentType::Right));
}

View file

@ -0,0 +1,67 @@
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

View file

@ -0,0 +1,16 @@
Sub AlignCols(Lines, Optional Align As AlignmentConstants, Optional Sep$ = "$", Optional Sp% = 1)
Dim i&, j&, D&, L&, R&: ReDim W(UBound(Lines)): ReDim C&(0)
For j = 0 To UBound(W)
W(j) = Split(Lines(j), Sep)
If UBound(W(j)) > UBound(C) Then ReDim Preserve C(UBound(W(j)))
For i = 0 To UBound(W(j)): If Len(W(j)(i)) > C(i) Then C(i) = Len(W(j)(i))
Next i, j
For j = 0 To UBound(W): For i = 0 To UBound(W(j))
D = C(i) - Len(W(j)(i))
L = Choose(Align + 1, 0, D, D \ 2)
R = Choose(Align + 1, D, 0, D - L) + Sp
Debug.Print Space(L); W(j)(i); Space(R); IIf(i < UBound(W(j)), "", vbLf);
Next i, j
End Sub

View file

@ -0,0 +1,12 @@
Sub Main() 'usage of the above
Const Text$ = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" & vbLf & _
"are$delineated$by$a$single$'dollar'$character,$write$a$program" & vbLf & _
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" & vbLf & _
"column$are$separated$by$at$least$one$space." & vbLf & _
"Further,$allow$for$each$word$in$a$column$to$be$either$left$" & vbLf & _
"justified,$right$justified,$or$center$justified$within$its$column."
Debug.Print vbLf; "-- Left:": AlignCols Split(Text, vbLf), vbLeftJustify
Debug.Print vbLf; "-- Center:": AlignCols Split(Text, vbLf), vbCenter
Debug.Print vbLf; "-- Right:": AlignCols Split(Text, vbLf), vbRightJustify
End Sub