2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,34 +1,41 @@
|
|||
# syntax: GAWK -f ALIGN_COLUMNS.AWK ALIGN_COLUMNS.TXT
|
||||
BEGIN {
|
||||
FS="$"
|
||||
lcounter = 1
|
||||
maxfield = 0
|
||||
# justification; pick one
|
||||
#justify = "left"
|
||||
justify = "center"
|
||||
#justify = "right"
|
||||
colsep = " " # separator between columns
|
||||
report("raw data")
|
||||
}
|
||||
{
|
||||
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++
|
||||
{ printf("%s\n",$0)
|
||||
arr[NR] = $0
|
||||
n = split($0,tmp_arr,"$")
|
||||
for (j=1; j<=n; j++) {
|
||||
width = max(width,length(tmp_arr[j]))
|
||||
}
|
||||
}
|
||||
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 ""
|
||||
}
|
||||
report("left justified")
|
||||
report("right justified")
|
||||
report("center justified")
|
||||
exit(0)
|
||||
}
|
||||
function report(text, diff,i,j,l,n,r,tmp_arr) {
|
||||
printf("\nreport: %s\n",text)
|
||||
for (i=1; i<=NR; i++) {
|
||||
n = split(arr[i],tmp_arr,"$")
|
||||
if (tmp_arr[n] == "") { n-- }
|
||||
for (j=1; j<=n; j++) {
|
||||
if (text ~ /^[Ll]/) { # left
|
||||
printf("%-*s%s",width,tmp_arr[j],colsep)
|
||||
}
|
||||
else if (text ~ /^[Rr]/) { # right
|
||||
printf("%*s%s",width,tmp_arr[j],colsep)
|
||||
}
|
||||
else if (text ~ /^[Cc]/) { # center
|
||||
diff = width - length(tmp_arr[j])
|
||||
l = r = int(diff / 2)
|
||||
if (diff != l + r) { r++ }
|
||||
printf("%*s%s%*s%s",l,"",tmp_arr[j],r,"",colsep)
|
||||
}
|
||||
}
|
||||
printf("\n")
|
||||
}
|
||||
}
|
||||
function max(x,y) { return((x > y) ? x : y) }
|
||||
|
|
|
|||
55
Task/Align-columns/Aime/align-columns.aime
Normal file
55
Task/Align-columns/Aime/align-columns.aime
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
data b;
|
||||
file f;
|
||||
list c, r, s;
|
||||
integer a, i, j, k, m, w;
|
||||
|
||||
b_cast(b, "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.");
|
||||
|
||||
f_b_affix(f, b);
|
||||
|
||||
m = 0;
|
||||
|
||||
while (f_news(f, r, 0, 0, "$") ^ -1) {
|
||||
l_append(c, r);
|
||||
m = max(m, l_length(r));
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < m) {
|
||||
w = 0;
|
||||
j = 0;
|
||||
while (j < l_length(c)) {
|
||||
r = c[j];
|
||||
if (i < l_length(r)) {
|
||||
w = max(w, length(r[i]));
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
l_append(s, w + 1);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
k = 3;
|
||||
while (k) {
|
||||
k -= 1;
|
||||
o_plan(l_effect("right", "center", "left")[k], " justified", "\n");
|
||||
j = 0;
|
||||
while (j < l_length(c)) {
|
||||
i = 0;
|
||||
r = c[j];
|
||||
while (i < l_length(r)) {
|
||||
w = s[i];
|
||||
m = w - length(r[i]);
|
||||
o_form("/w~3/~/w~1/", a = k * m >> 1, "", m - a, "", r[i]);
|
||||
i += 1;
|
||||
}
|
||||
o_newline();
|
||||
j += 1;
|
||||
}
|
||||
o_newline();
|
||||
}
|
||||
216
Task/Align-columns/AppleScript/align-columns.applescript
Normal file
216
Task/Align-columns/AppleScript/align-columns.applescript
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
property pstrLines : ¬
|
||||
"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."
|
||||
|
||||
property eLeft : -1
|
||||
property eCenter : 0
|
||||
property eRight : 1
|
||||
|
||||
on run
|
||||
set lstCols to lineColumns("$", pstrLines)
|
||||
|
||||
script testAlignment
|
||||
on lambda(eAlign)
|
||||
columnsAligned(eAlign, lstCols)
|
||||
end lambda
|
||||
end script
|
||||
|
||||
intercalate(return & return, ¬
|
||||
map(testAlignment, {eLeft, eRight, eCenter}))
|
||||
end run
|
||||
|
||||
|
||||
-- columnsAligned :: EnumValue -> [[String]] -> String
|
||||
on columnsAligned(eAlign, lstCols)
|
||||
-- padwords :: Int -> [String] -> [[String]]
|
||||
script padwords
|
||||
on lambda(n, lstWords)
|
||||
|
||||
-- pad :: String -> String
|
||||
script pad
|
||||
on lambda(str)
|
||||
set lngPad to n - (length of str)
|
||||
if eAlign = my eCenter then
|
||||
set lngHalf to lngPad div 2
|
||||
{replicate(lngHalf, space), str, ¬
|
||||
replicate(lngPad - lngHalf, space)}
|
||||
else
|
||||
if eAlign = my eLeft then
|
||||
{"", str, replicate(lngPad, space)}
|
||||
else
|
||||
{replicate(lngPad, space), str, ""}
|
||||
end if
|
||||
end if
|
||||
end lambda
|
||||
end script
|
||||
|
||||
map(pad, lstWords)
|
||||
end lambda
|
||||
end script
|
||||
|
||||
unlines(map(my unwords, ¬
|
||||
transpose(zipWith(padwords, ¬
|
||||
map(my widest, lstCols), lstCols))))
|
||||
end columnsAligned
|
||||
|
||||
-- lineColumns :: String -> String -> String
|
||||
on lineColumns(strColDelim, strText)
|
||||
-- _words :: Text -> [Text]
|
||||
script _words
|
||||
on lambda(str)
|
||||
splitOn(strColDelim, str)
|
||||
end lambda
|
||||
end script
|
||||
|
||||
set lstRows to map(_words, splitOn(linefeed, pstrLines))
|
||||
set nCols to widest(lstRows)
|
||||
|
||||
-- fullRow :: [[a]] -> [[a]]
|
||||
script fullRow
|
||||
on lambda(lst)
|
||||
lst & replicate(nCols - (length of lst), {""})
|
||||
end lambda
|
||||
end script
|
||||
|
||||
transpose(map(fullRow, lstRows))
|
||||
end lineColumns
|
||||
|
||||
-- widest [a] -> Int
|
||||
on widest(xs)
|
||||
script maxLen
|
||||
on lambda(a, x)
|
||||
set lng to length of x
|
||||
cond(lng > a, lng, a)
|
||||
end lambda
|
||||
end script
|
||||
|
||||
foldl(maxLen, 0, xs)
|
||||
end widest
|
||||
|
||||
|
||||
|
||||
-- GENERIC LIBRARY FUNCTIONS
|
||||
|
||||
-- Text -> [Text] -> Text
|
||||
on intercalate(strText, lstText)
|
||||
set {dlm, my text item delimiters} to {my text item delimiters, strText}
|
||||
set strJoined to lstText as text
|
||||
set my text item delimiters to dlm
|
||||
return strJoined
|
||||
end intercalate
|
||||
|
||||
-- Text -> Text -> [Text]
|
||||
on splitOn(strDelim, strMain)
|
||||
set {dlm, my text item delimiters} to {my text item delimiters, strDelim}
|
||||
set lstParts to text items of strMain
|
||||
set my text item delimiters to dlm
|
||||
return lstParts
|
||||
end splitOn
|
||||
|
||||
-- [Text] -> Text
|
||||
on unlines(lstLines)
|
||||
intercalate(linefeed, lstLines)
|
||||
end unlines
|
||||
|
||||
-- [Text] -> Text
|
||||
on unwords(lstWords)
|
||||
intercalate(" ", lstWords)
|
||||
end unwords
|
||||
|
||||
-- transpose :: [[a]] -> [[a]]
|
||||
on transpose(xss)
|
||||
script column
|
||||
on lambda(_, iCol)
|
||||
script row
|
||||
on lambda(xs)
|
||||
item iCol of xs
|
||||
end lambda
|
||||
end script
|
||||
|
||||
map(row, xss)
|
||||
end lambda
|
||||
end script
|
||||
|
||||
map(column, item 1 of xss)
|
||||
end transpose
|
||||
|
||||
-- foldl :: (a -> b -> a) -> a -> [b] -> a
|
||||
on foldl(f, startValue, xs)
|
||||
tell mReturn(f)
|
||||
set v to startValue
|
||||
set lng to length of xs
|
||||
repeat with i from 1 to lng
|
||||
set v to lambda(v, item i of xs, i, xs)
|
||||
end repeat
|
||||
return v
|
||||
end tell
|
||||
end foldl
|
||||
|
||||
-- map :: (a -> b) -> [a] -> [b]
|
||||
on map(f, xs)
|
||||
tell mReturn(f)
|
||||
set lng to length of xs
|
||||
set lst to {}
|
||||
repeat with i from 1 to lng
|
||||
set end of lst to lambda(item i of xs, i, xs)
|
||||
end repeat
|
||||
return lst
|
||||
end tell
|
||||
end map
|
||||
|
||||
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
on zipWith(f, xs, ys)
|
||||
set lng to length of xs
|
||||
if lng is not length of ys then return missing value
|
||||
|
||||
tell mReturn(f)
|
||||
set lst to {}
|
||||
repeat with i from 1 to lng
|
||||
set end of lst to lambda(item i of xs, item i of ys)
|
||||
end repeat
|
||||
return lst
|
||||
end tell
|
||||
end zipWith
|
||||
|
||||
-- cond :: Bool -> a -> a -> a
|
||||
on cond(bool, f, g)
|
||||
if bool then
|
||||
f
|
||||
else
|
||||
g
|
||||
end if
|
||||
end cond
|
||||
|
||||
-- Egyptian multiplication - progressively doubling a list, appending
|
||||
-- stages of doubling to an accumulator where needed for binary
|
||||
-- assembly of a target length
|
||||
|
||||
-- replicate :: Int -> a -> [a]
|
||||
on replicate(n, a)
|
||||
set out to cond(class of a is string, "", {})
|
||||
if n < 1 then return out
|
||||
set dbl to a
|
||||
|
||||
repeat while (n > 1)
|
||||
if (n mod 2) > 0 then set out to out & dbl
|
||||
set n to (n div 2)
|
||||
set dbl to (dbl & dbl)
|
||||
end repeat
|
||||
return out & dbl
|
||||
end replicate
|
||||
|
||||
-- Lift 2nd class handler function into 1st class script wrapper
|
||||
-- mReturn :: Handler -> Script
|
||||
on mReturn(f)
|
||||
if class of f is script then
|
||||
f
|
||||
else
|
||||
script
|
||||
property lambda : f
|
||||
end script
|
||||
end if
|
||||
end mReturn
|
||||
84
Task/Align-columns/Batch-File/align-columns.bat
Normal file
84
Task/Align-columns/Batch-File/align-columns.bat
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
mode con cols=103
|
||||
|
||||
echo Given$a$text$file$of$many$lines,$where$fields$within$a$line$ >file.txt
|
||||
echo are$delineated$by$a$single$'dollar'$character,$write$a$program! >>file.txt
|
||||
echo that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$>>file.txt
|
||||
echo column$are$separated$by$at$least$one$space.>>file.txt
|
||||
echo Further,$allow$for$each$word$in$a$column$to$be$either$left$>>file.txt
|
||||
echo justified,$right$justified,$or$center$justified$within$its$column.>>file.txt
|
||||
|
||||
for /f "tokens=1-13 delims=$" %%a in ('type file.txt') do (
|
||||
call:maxlen %%a %%b %%c %%d %%e %%f %%g %%h %%i %%j %%k %%l %%m )
|
||||
echo.
|
||||
for /f "tokens=1-13 delims=$" %%a in ('type file.txt') do (
|
||||
call:align 1 %%a %%b %%c %%d %%e %%f %%g %%h %%i %%j %%k %%l %%m )
|
||||
echo.
|
||||
for /f "tokens=1-13 delims=$" %%a in ('type file.txt') do (
|
||||
call:align 2 %%a %%b %%c %%d %%e %%f %%g %%h %%i %%j %%k %%l %%m )
|
||||
echo.
|
||||
for /f "tokens=1-13 delims=$" %%a in ('type file.txt') do (
|
||||
call:align 3 %%a %%b %%c %%d %%e %%f %%g %%h %%i %%j %%k %%l %%m )
|
||||
|
||||
exit /B
|
||||
|
||||
:maxlen &::sets variables len1 to len13
|
||||
set "cnt=1"
|
||||
:loop1
|
||||
if "%1"=="" exit /b
|
||||
call:strlen %1 length
|
||||
if !len%cnt%! lss !length! set len%cnt%=!length!
|
||||
set /a cnt+=1
|
||||
shift
|
||||
goto loop1
|
||||
|
||||
:align
|
||||
setlocal
|
||||
set cnt=1
|
||||
set print=
|
||||
:loop2
|
||||
if "%2"=="" echo(%print%&endlocal & exit /b
|
||||
set /a width=len%cnt%,cnt+=1
|
||||
set arr=%2
|
||||
if %1 equ 1 call:left %width% arr
|
||||
if %1 equ 2 call:right %width% arr
|
||||
if %1 equ 3 call:center %width% arr
|
||||
set "print=%print%%arr% "
|
||||
shift /2
|
||||
goto loop2
|
||||
|
||||
:left %num% &string
|
||||
setlocal
|
||||
set "arr=!%2! "
|
||||
set arr=!arr:~0,%1!
|
||||
endlocal & set %2=%arr%
|
||||
exit /b
|
||||
|
||||
:right %num% &string
|
||||
setlocal
|
||||
set "arr= !%2!"
|
||||
set arr=!arr:~-%1!
|
||||
endlocal & set %2=%arr%
|
||||
exit /b
|
||||
|
||||
:center %num% &string
|
||||
setlocal
|
||||
set /a width=%1-1
|
||||
set arr=!%2!
|
||||
:loop3
|
||||
if "!arr:~%width%,1!"=="" set "arr=%arr% "
|
||||
if "!arr:~%width%,1!"=="" set "arr= %arr%"
|
||||
if "!arr:~%width%,1!"=="" goto loop3
|
||||
endlocal & set %2=%arr%
|
||||
exit /b
|
||||
|
||||
:strlen StrVar &RtnVar
|
||||
setlocal EnableDelayedExpansion
|
||||
set "s=#%~1"
|
||||
set "len=0"
|
||||
for %%N in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
|
||||
if "!s:~%%N,1!" neq "" set /a "len+=%%N" & set "s=!s:~%%N!"
|
||||
)
|
||||
endlocal & set %~2=%len%
|
||||
exit /b
|
||||
94
Task/Align-columns/Fortran/align-columns.f
Normal file
94
Task/Align-columns/Fortran/align-columns.f
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
SUBROUTINE RAKE(IN,M,X,WAY) !Casts forth text in fixed-width columns.
|
||||
Collates column widths so that each column is wide enough for its widest member.
|
||||
INTEGER IN !Fingers the input file.
|
||||
INTEGER M !Maximum record length thereof.
|
||||
CHARACTER*1 X !The delimiter, possibly a comma.
|
||||
INTEGER WAY !Alignment style.
|
||||
INTEGER W(M + 1) !If every character were X in the maximum-length record,
|
||||
INTEGER C(0:M + 1) !Then M + 1 would be the maximum number of fields possible.
|
||||
CHARACTER*(M) ACARD !A scratchpad big enough for the biggest.
|
||||
CHARACTER*(28 + 4*M) FORMAT !Guess. Allow for "Ann," per field.
|
||||
INTEGER I !A stepper.
|
||||
INTEGER L,LF !Text fingers.
|
||||
INTEGER NF,MF !Field counts.
|
||||
CHARACTER*6 WAYNESS(-1:+1) !Some annotation may be helpful.
|
||||
PARAMETER (WAYNESS = (/"Left","Centre","Right"/)) !Using normal language.
|
||||
INTEGER LINPR !The mouthpiece.
|
||||
COMMON LINPR !Used all over.
|
||||
W = 0 !Maximum field widths so far seen.
|
||||
MF = 0 !Maximum number of fields to a record.
|
||||
C(0) = 0 !Syncopation for the first field's predecessor.
|
||||
WRITE (LINPR,*) !Some separation.
|
||||
WRITE (LINPR,*) "Align ",WAYNESS(MIN(MAX(WAY,-1),+1)) !Explain, cautiously.
|
||||
|
||||
Chase through the file assessing the lengths of each field.
|
||||
10 READ (IN,11,END = 20) L,ACARD(1:L) !Grab a record.
|
||||
11 FORMAT (Q,A) !Working only up to its end.
|
||||
CALL LIZZIEBORDEN !Find the chop points.
|
||||
W(1:NF) = MAX(W(1:NF),C(1:NF) - C(0:NF - 1) - 1) !Thereby the lengths between.
|
||||
MF = MAX(MF,NF) !Also want to know the most number of chops.
|
||||
GO TO 10 !Get the next record.
|
||||
|
||||
Concoct a FORMAT based on the maximum size of each field. Plus one.
|
||||
20 REWIND(IN) !Back to the beginning.
|
||||
WRITE (FORMAT,21) W(1:MF) + 1 !Add one to meet the specified at least one space between columns.
|
||||
21 FORMAT ("(",<MF>("A",I0,",")) !Generates a sequence of An, items.
|
||||
LF = INDEX(FORMAT,", ") !The last one has a trailing comma.
|
||||
IF (LF.LE.0) STOP "Format trouble!" !Or, maybe not!
|
||||
FORMAT(LF:LF) = ")" !Convert it to the closing bracket.
|
||||
WRITE (LINPR,*) "Format",FORMAT(1:LF) !Present it.
|
||||
|
||||
Chug afresh, this time knowing the maximum length of each field.
|
||||
30 READ (IN,11,END = 40) L,ACARD(1:L) !Place just the record's content.
|
||||
CALL LIZZIEBORDEN !Find the chop points.
|
||||
SELECT CASE(WAY) !What is to be done?
|
||||
CASE(-1) !Shove leftwards by appending spaces.
|
||||
WRITE (LINPR,FORMAT) (ACARD(C(I - 1) + 1:C(I) - 1)// !The chopped text.
|
||||
1 REPEAT(" ",W(I) - C(I) + C(I - 1) + 1),I = 1,NF) !Some spaces.
|
||||
CASE( 0) !Centre by appending half as many spaces.
|
||||
WRITE (LINPR,FORMAT) (ACARD(C(I - 1) + 1:C(I) - 1)// !The chopped text.
|
||||
1 REPEAT(" ",(W(I) - C(I) + C(I - 1) + 1)/2),I = 1,NF) !Some spaces.
|
||||
CASE(+1) !Align rightwards is the default style.
|
||||
WRITE (LINPR,FORMAT) (ACARD(C(I - 1) + 1:C(I) - 1),I = 1,NF) !So, just the texts.
|
||||
CASE DEFAULT !This shouldn't happen.
|
||||
WRITE (LINPR,*) "Huh? WAY=",WAY !But if it does,
|
||||
STOP "Unanticipated value for WAY!" !Explain.
|
||||
END SELECT !So much for that record.
|
||||
GO TO 30 !Go for another.
|
||||
Closedown
|
||||
40 REWIND(IN) !Be polite.
|
||||
CONTAINS !This also marks the end of source for RAKE...
|
||||
SUBROUTINE LIZZIEBORDEN !Take an axe to ACARD, chopping at X.
|
||||
NF = 0 !No strokes so far.
|
||||
DO I = 1,L !So, step away.
|
||||
IF (ICHAR(ACARD(I:I)).EQ.ICHAR(X)) THEN !Here?
|
||||
NF = NF + 1 !Yes!
|
||||
C(NF) = I !The place!
|
||||
END IF !So much for that.
|
||||
END DO !On to the next.
|
||||
NF = NF + 1 !And the end of ACARD is also a chop point.
|
||||
C(NF) = L + 1 !As if here.
|
||||
END SUBROUTINE LIZZIEBORDEN !She was aquitted.
|
||||
END SUBROUTINE RAKE !So much raking over.
|
||||
|
||||
INTEGER L,M,N !To be determined the hard way.
|
||||
INTEGER LINPR,IN !I/O unit numbers.
|
||||
COMMON LINPR !Some of general note.
|
||||
LINPR = 6 !Standard output via this unit number.
|
||||
IN = 10 !Some unit number for the input file.
|
||||
OPEN (IN,FILE="Rake.txt",STATUS="OLD",ACTION="READ") !For formatted input.
|
||||
N = 0 !No records read.
|
||||
M = 0 !Longest record so far.
|
||||
|
||||
1 READ (IN,2,END = 10) L !How long is this record?
|
||||
2 FORMAT (Q) !Obviously, Q specifies the length, not a content field.
|
||||
N = N + 1 !Anyway, another record has been read.
|
||||
M = MAX(M,L) !And this is the longest so far.
|
||||
GO TO 1 !Go back for more.
|
||||
|
||||
10 REWIND (IN) !We're ready now.
|
||||
WRITE (LINPR,*) N,"Recs, longest rec. length is ",M
|
||||
CALL RAKE(IN,M,"$",-1) !Align left.
|
||||
CALL RAKE(IN,M,"$", 0) !Centre.
|
||||
CALL RAKE(IN,M,"$",+1) !Align right.
|
||||
END !That's all.
|
||||
|
|
@ -1,63 +1,133 @@
|
|||
(function (lines) {
|
||||
(function (strText) {
|
||||
'use strict';
|
||||
|
||||
var LEFT = 0,
|
||||
CENTRE = 1,
|
||||
RIGHT = 2;
|
||||
// [[a]] -> [[a]]
|
||||
function transpose(lst) {
|
||||
return lst[0].map(function (_, iCol) {
|
||||
return lst.map(function (row) {
|
||||
return row[iCol];
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
return alignedTable(
|
||||
lines.map(function (s) {
|
||||
return s.split('$');
|
||||
// (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
function zipWith(f, xs, ys) {
|
||||
return xs.length === ys.length ? (
|
||||
xs.map(function (x, i) {
|
||||
return f(x, ys[i]);
|
||||
})
|
||||
) : undefined;
|
||||
}
|
||||
|
||||
// (a -> a -> Ordering) -> [a] -> a
|
||||
function maximumBy(f, xs) {
|
||||
return xs.reduce(function (a, x) {
|
||||
return a === undefined ? x : (
|
||||
f(x) > f(a) ? x : a
|
||||
);
|
||||
}, undefined)
|
||||
}
|
||||
|
||||
// [String] -> String
|
||||
function widest(lst) {
|
||||
return maximumBy(length, lst)
|
||||
.length;
|
||||
}
|
||||
|
||||
// [[a]] -> [[a]]
|
||||
function fullRow(lst, n) {
|
||||
return lst.concat(Array.apply(null, Array(n - lst.length))
|
||||
.map(function () {
|
||||
return ''
|
||||
}));
|
||||
}
|
||||
|
||||
// String -> Int -> String
|
||||
function nreps(s, n) {
|
||||
var o = '';
|
||||
if (n < 1) return o;
|
||||
while (n > 1) {
|
||||
if (n & 1) o += s;
|
||||
n >>= 1;
|
||||
s += s;
|
||||
}
|
||||
return o + s;
|
||||
}
|
||||
|
||||
// [String] -> String
|
||||
function unwords(xs) {
|
||||
return xs.join(' ');
|
||||
}
|
||||
|
||||
// [String] -> String
|
||||
function unlines(xs) {
|
||||
return xs.join('\n');
|
||||
}
|
||||
|
||||
// [a] -> Int
|
||||
function length(xs) {
|
||||
return xs.length;
|
||||
}
|
||||
|
||||
// -- Int -> [String] -> [[String]]
|
||||
function padWords(n, lstWords, eAlign) {
|
||||
return lstWords.map(function (w) {
|
||||
var lngPad = n - w.length;
|
||||
|
||||
return (
|
||||
(eAlign === eCenter) ? (function () {
|
||||
var lngHalf = Math.floor(lngPad / 2);
|
||||
|
||||
return [
|
||||
nreps(' ', lngHalf), w,
|
||||
nreps(' ', lngPad - lngHalf)
|
||||
];
|
||||
})() : (eAlign === eLeft) ?
|
||||
['', w, nreps(' ', lngPad)] :
|
||||
[nreps(' ', lngPad), w, '']
|
||||
)
|
||||
.join('');
|
||||
});
|
||||
}
|
||||
|
||||
// MAIN
|
||||
|
||||
var eLeft = -1,
|
||||
eCenter = 0,
|
||||
eRight = 1;
|
||||
|
||||
var lstRows = strText.split('\n')
|
||||
.map(function (x) {
|
||||
return x.split('$');
|
||||
}),
|
||||
2, // minimum gap between cols
|
||||
LEFT // [LEFT|CENTRE|RIGHT] or [0|1|2]
|
||||
)
|
||||
|
||||
// TABULATION OF RESULTS IN SPACED AND ALIGNED COLUMNS
|
||||
// [s] -> n -> enum -> s
|
||||
function alignedTable(lstRows, lngPad, iAlignment) {
|
||||
lngCols = widest(lstRows),
|
||||
lstCols = transpose(lstRows.map(function (r) {
|
||||
return fullRow(r, lngCols)
|
||||
})),
|
||||
lstColWidths = lstCols.map(widest);
|
||||
|
||||
// Max width of each column
|
||||
var lstColWidths = range(0, lstRows.reduce(function (a, x) {
|
||||
return x.length > a ? x.length : a;
|
||||
}, 0) - 1).map(function (iCol) {
|
||||
return lstRows.reduce(function (a, lst) {
|
||||
var w = lst[iCol] ? lst[iCol].toString().length : 0;
|
||||
return (w > a) ? w : a;
|
||||
}, 0);
|
||||
});
|
||||
// THREE PARAGRAPHS, WITH VARIOUS WORD COLUMN ALIGNMENTS:
|
||||
|
||||
// Rows padded to equal width
|
||||
return lstRows.map(function (lstRow) {
|
||||
return lstRow.map(function (v, i) {
|
||||
return align(v, lstColWidths[i] + lngPad, iAlignment);
|
||||
}).join('')
|
||||
}).join('\n');
|
||||
}
|
||||
return [eLeft, eRight, eCenter]
|
||||
.map(function (eAlign) {
|
||||
var fPad = function (n, lstWords) {
|
||||
return padWords(n, lstWords, eAlign);
|
||||
};
|
||||
|
||||
// Text padded to left and/or right: aligned (left|centre|right)
|
||||
// String, number of characters, alignment 0|1|2
|
||||
// s -> n -> enum -> s
|
||||
function align(s, n, a) {
|
||||
var mid = (1 === a),
|
||||
gap = n - s.length,
|
||||
pad = Array(Math.floor((gap + 1) / (mid ? 2 : 1))).join(' ');
|
||||
return transpose(
|
||||
zipWith(fPad, lstColWidths, lstCols)
|
||||
)
|
||||
.map(unwords);
|
||||
})
|
||||
.map(unlines)
|
||||
.join('\n\n');
|
||||
|
||||
return (a ? pad + (!mid || gap % 2 ? '' : ' ') : '') + s +
|
||||
(2 > a ? pad + (mid ? ' ' : '') : '');
|
||||
}
|
||||
|
||||
// [m..n]
|
||||
function range(m, n) {
|
||||
return Array.apply(null, Array(n - m + 1)).map(function (x, i) {
|
||||
return m + i;
|
||||
});
|
||||
}
|
||||
|
||||
})([
|
||||
"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$\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."
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,17 +5,11 @@ import java.nio.file.Files
|
|||
import java.nio.file.Paths
|
||||
|
||||
enum class Align_function {
|
||||
LEFT {
|
||||
override fun invoke(s: String, length: Int) = ("%-" + length + 's').format(("%" + s.length() + 's').format(s))
|
||||
},
|
||||
RIGHT {
|
||||
override fun invoke(s: String, length: Int) = ("%-" + length + 's').format(("%" + length + 's').format(s))
|
||||
},
|
||||
CENTER {
|
||||
override fun invoke(s: String, length: Int) = ("%-" + length + 's').format(("%" + ((length + s.length()) / 2) + 's').format(s))
|
||||
};
|
||||
LEFT { override fun invoke(s: String, l: Int) = ("%-" + l + 's').format(("%" + s.length + 's').format(s)) },
|
||||
RIGHT { override fun invoke(s: String, l: Int) = ("%-" + l + 's').format(("%" + l + 's').format(s)) },
|
||||
CENTER { override fun invoke(s: String, l: Int) = ("%-" + l + 's').format(("%" + ((l + s.length) / 2) + 's').format(s)) };
|
||||
|
||||
abstract operator fun invoke(s: String, length: Int): String
|
||||
abstract operator fun invoke(s: String, l: Int): String
|
||||
}
|
||||
|
||||
/** Aligns fields into columns, separated by "|".
|
||||
|
|
@ -23,42 +17,42 @@ enum class Align_function {
|
|||
* @property lines Lines in a single string. Empty string does form a column.
|
||||
*/
|
||||
class Column_aligner(val lines: List<String>) {
|
||||
operator fun invoke(a: Align_function): String {
|
||||
val result = StringBuilder()
|
||||
operator fun invoke(a: Align_function) : String {
|
||||
var result = ""
|
||||
for (lineWords in words) {
|
||||
for (i in lineWords.indices) {
|
||||
if (i == 0)
|
||||
result.append('|')
|
||||
result.append(a(lineWords[i], column_widths[i]))
|
||||
result.append('|')
|
||||
result += '|'
|
||||
result += a(lineWords[i], column_widths[i])
|
||||
result += '|'
|
||||
}
|
||||
result.append('\n')
|
||||
result += '\n'
|
||||
}
|
||||
return result.toString()
|
||||
return result
|
||||
}
|
||||
|
||||
private val words = arrayListOf<Array<String>>()
|
||||
private val column_widths = arrayListOf<Int>()
|
||||
|
||||
init {
|
||||
lines forEach {
|
||||
lines.forEach {
|
||||
val lineWords = java.lang.String(it).split("\\$")
|
||||
words += lineWords
|
||||
for (i in lineWords.indices)
|
||||
if (i >= column_widths.size())
|
||||
column_widths += lineWords[i].length()
|
||||
if (i >= column_widths.size)
|
||||
column_widths += lineWords[i].length
|
||||
else
|
||||
column_widths[i] = Math.max(column_widths[i], lineWords[i].length())
|
||||
column_widths[i] = Math.max(column_widths[i], lineWords[i].length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
if (args.size() < 1)
|
||||
if (args.size < 1)
|
||||
println("Usage: ColumnAligner file [L|R|C]")
|
||||
else {
|
||||
val ca = Column_aligner(Files.readAllLines(Paths.get(args[0]), StandardCharsets.UTF_8))
|
||||
val alignment = if (args.size() >= 2) args[1] else "L"
|
||||
val alignment = if (args.size >= 2) args[1] else "L"
|
||||
when (alignment) {
|
||||
"L" -> print(ca(Align_function.LEFT))
|
||||
"R" -> print(ca(Align_function.RIGHT))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ 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) ~ " "; } }
|
||||
for @lines { say |.split('$').kv.map: { (align @widths[$^key], $^word) ~ " "; } }
|
||||
|
||||
sub align($column_width, $word, $aligment = @*ARGS[0]) {
|
||||
my $lr = $column_width - $word.chars;
|
||||
|
|
|
|||
7
Task/Align-columns/Perl-6/align-columns-3.pl6
Normal file
7
Task/Align-columns/Perl-6/align-columns-3.pl6
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
sub MAIN ($alignment where 'left'|'right', $file) {
|
||||
my @lines := $file.IO.lines.map(*.split: '$').List;
|
||||
my @widths = roundrobin(|@lines).map(*».chars.max);
|
||||
my $align = {left=>'-', right=>''}{$alignment};
|
||||
my $format = @widths.map({ "%{++$}\${$align}{$_}s" }).join(" ") ~ "\n";
|
||||
printf $format, |$_ for @lines;
|
||||
}
|
||||
22
Task/Align-columns/PowerShell/align-columns.psh
Normal file
22
Task/Align-columns/PowerShell/align-columns.psh
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
$file =
|
||||
@'
|
||||
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("`n")
|
||||
|
||||
$arr = @()
|
||||
$file | foreach {
|
||||
$line = $_
|
||||
$i = 0
|
||||
$hash = [ordered]@{}
|
||||
$line.split('$') | foreach{
|
||||
$hash["$i"] = "$_"
|
||||
$i++
|
||||
}
|
||||
$arr += @([pscustomobject]$hash)
|
||||
}
|
||||
$arr | Format-Table -HideTableHeaders -Wrap *
|
||||
47
Task/Align-columns/ZX-Spectrum-Basic/align-columns.zx
Normal file
47
Task/Align-columns/ZX-Spectrum-Basic/align-columns.zx
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
5 BORDER 2
|
||||
10 DATA 6
|
||||
20 DATA "The$problem$of$Speccy$"
|
||||
30 DATA "is$the$screen.$"
|
||||
40 DATA "Need$adapt$text$sample$"
|
||||
50 DATA "for$show$the$result$"
|
||||
60 DATA "without$problem$,right?$"
|
||||
70 DATA "But$see$the$code.$"
|
||||
80 REM First find the maximum length of a 'word'
|
||||
90 LET max=0: LET d$="$"
|
||||
100 READ nlines
|
||||
110 FOR l=1 TO nlines
|
||||
120 READ t$
|
||||
130 GO SUB 1000
|
||||
150 NEXT l
|
||||
155 LET s$=" "( TO max)
|
||||
160 REM Now display the aligned text:
|
||||
170 LET m$="l": GO SUB 2000: PRINT
|
||||
180 LET m$="r": GO SUB 2000: PRINT
|
||||
190 LET m$="c": GO SUB 2000
|
||||
200 STOP
|
||||
1000 REM Maximum length of a word
|
||||
1010 LET lt=LEN t$: LET p=1: LET lw=0
|
||||
1020 FOR i=1 TO lt
|
||||
1030 IF t$(i)=d$ THEN LET lw=i-p: LET p=i: IF lw>max THEN LET max=lw
|
||||
1040 NEXT i
|
||||
1050 RETURN
|
||||
2000 REM Show aligned text
|
||||
2010 RESTORE 20
|
||||
2020 FOR l=1 TO nlines
|
||||
2030 READ t$
|
||||
2040 GO SUB 3000
|
||||
2050 NEXT l
|
||||
2060 RETURN
|
||||
3000 REM Show words
|
||||
3010 LET lt=LEN t$: LET p=1: LET lw=0
|
||||
3020 FOR i=1 TO lt
|
||||
3030 IF t$(i)<>d$ THEN GO TO 3090
|
||||
3035 LET lw=i-p
|
||||
3040 LET p$=t$(p TO i-1): LET p=i+1: LET z$=s$
|
||||
3050 IF m$="l" THEN LET z$( TO lw)=p$
|
||||
3060 IF m$="r" THEN LET z$(max-lw+1 TO )=p$
|
||||
3070 IF m$="c" THEN LET z$((max/2)-(lw/2) TO )=p$
|
||||
3080 PRINT z$;
|
||||
3090 NEXT i
|
||||
3095 PRINT
|
||||
3100 RETURN
|
||||
Loading…
Add table
Add a link
Reference in a new issue