Align columns: Difference between revisions
→{{header|D}}: add implementation |
|||
(385 intermediate revisions by more than 100 users not shown) | |||
Line 14: | Line 14: | ||
Further,$allow$for$each$word$in$a$column$to$be$either$left$ |
Further,$allow$for$each$word$in$a$column$to$be$either$left$ |
||
justified,$right$justified,$or$center$justified$within$its$column.</pre> |
justified,$right$justified,$or$center$justified$within$its$column.</pre> |
||
Note that: |
Note that: |
||
# The example input texts lines may, or may not, have trailing dollar characters. |
# The example input texts lines may, or may not, have trailing dollar characters. |
||
# All columns should share the same alignment. |
# 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. |
# 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. |
# Output text will be viewed in a mono-spaced font on a plain text editor or basic terminal. |
||
# The minimum space between columns should be computed from the text and not hard-coded. |
|||
# It is ''not'' a requirement to add separating characters between or around columns. |
|||
{{Template:Strings}} |
|||
<br><br> |
|||
=={{header|11l}}== |
|||
{{trans|D}} |
|||
<syntaxhighlight lang="11l">V 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.’ |
|||
V parts = txt.split("\n").map(line -> line.rtrim(‘$’).split(‘$’)) |
|||
V max_widths = [0] * parts[0].len |
|||
L(line) parts |
|||
L(word) line |
|||
max_widths[L.index] = max(max_widths[L.index], word.len) |
|||
((String, Int) -> String) ljust = (s, w) -> s‘’(‘ ’ * (w - s.len)) |
|||
((String, Int) -> String) centr = (s, w) -> (‘ ’ * (w - s.len - (w I/ 2 - s.len I/ 2)))‘’s‘’(‘ ’ * (w I/ 2 - s.len I/ 2)) |
|||
((String, Int) -> String) rjust = (s, w) -> (‘ ’ * (w - s.len))‘’s |
|||
L(justify) [ljust, centr, rjust] |
|||
print([‘Left’, ‘Center’, ‘Right’][L.index]‘ column-aligned output:’) |
|||
L(line) parts |
|||
L(word) line |
|||
print(justify(word, max_widths[L.index]), end' ‘ ’) |
|||
print() |
|||
print(‘- ’ * 52)</syntaxhighlight> |
|||
=={{header|360 Assembly}}== |
|||
<syntaxhighlight lang="360asm">* Align columns 12/04/2019 |
|||
ALICOL CSECT |
|||
USING ALICOL,R13 base register |
|||
B 72(R15) skip savearea |
|||
DC 17F'0' savearea |
|||
SAVE (14,12) save previous context |
|||
ST R13,4(R15) link backward |
|||
ST R15,8(R13) link forward |
|||
LR R13,R15 set addressability |
|||
LA R8,1 i=1 |
|||
DO WHILE=(C,R8,LE,=A(NI)) do r=1 to hbound(t) |
|||
LA R7,1 j=1 |
|||
LA R6,L'T i=length(t) |
|||
DO WHILE=(C,R6,GE,=A(1)) do i=length(t) to 1 by -1 |
|||
LR R1,R8 r |
|||
MH R1,=AL2(L'T) ~ |
|||
LA R4,T-L'T(R1) t(r) |
|||
BCTR R4,0 -1 |
|||
AR R4,R6 +i |
|||
MVC CI,0(R4) ci=substr(t(r),i,1) |
|||
CLI CI,C' ' if ci=' ' |
|||
BE ITERI1 then iterate i |
|||
CLI CI,C'$' if ci='$' |
|||
BE ITERI1 then iterate i |
|||
LR R7,R6 j=i |
|||
B LEAVEI1 leave i |
|||
ITERI1 BCTR R6,0 i-- |
|||
ENDDO , enddo i |
|||
LEAVEI1 LR R1,R8 r |
|||
MH R1,=AL2(L'T) ~ |
|||
LA R4,T-L'T(R1) @t(r) |
|||
LA R2,WT @wt |
|||
LR R5,R7 j |
|||
ICM R5,B'1000',=C' ' padding |
|||
LA R3,L'T length(wt) |
|||
MVCL R2,R4 wt=substr(t(r),1,j) |
|||
LA R0,1 1 |
|||
ST R0,I0 i0=1 |
|||
SR R9,R9 c=0 |
|||
LA R6,1 i=1 |
|||
DO WHILE=(CR,R6,LE,R7) do i=1 to j |
|||
LA R4,WT-1 @wt |
|||
AR R4,R6 i |
|||
MVC CI(1),0(R4) ci=substr(wt,i,1) |
|||
IF CLI,CI,EQ,C'$' THEN if ci='$' then |
|||
BAL R14,SEQ call seq |
|||
LR R2,R6 i |
|||
LA R2,1(R2) +1 |
|||
ST R2,I0 i0=i+1 |
|||
ENDIF , endif |
|||
LA R6,1(R6) i++ |
|||
ENDDO , enddo i |
|||
BAL R14,SEQ call seq |
|||
IF C,R9,GT,COLS THEN if c>cols then |
|||
ST R9,COLS cols=c |
|||
ENDIF , endif |
|||
LA R8,1(R8) r++ |
|||
ENDDO , enddo r |
|||
LR R2,R8 r |
|||
BCTR R2,0 -1 |
|||
ST R2,ROWS rows=r-1 |
|||
LA R7,1 j=1 |
|||
DO WHILE=(C,R7,LE,=A(3)) do j=1 to 3 |
|||
XPRNT =C'--',2 print |
|||
LA R8,1 r=1 |
|||
DO WHILE=(C,R8,LE,ROWS) do r=1 to rows |
|||
MVC PG,=CL120' ' pg=' ' |
|||
LA R0,1 1 |
|||
ST R0,IB ib=1 |
|||
LA R9,1 c=1 |
|||
DO WHILE=(C,R9,LE,COLS) do c=1 to cols |
|||
LR R1,R8 r |
|||
BCTR R1,0 -1 |
|||
MH R1,=AL2(NJ) ~ |
|||
AR R1,R9 c |
|||
MH R1,=AL2(L'WOR) ~ |
|||
LA R4,WOR-L'WOR(R1) @wor(r,c) |
|||
MVC W,0(R4) w=wor(r,c) |
|||
LA R6,L'W i=length(w) |
|||
DO WHILE=(C,R6,GE,=A(1)) do i=length(w) to 1 by -1 |
|||
LA R4,W-1 @w |
|||
AR R4,R6 i |
|||
MVC CI,0(R4) ci=substr(w,i,1) |
|||
CLI CI,C' ' if ci^=' ' |
|||
BNE LEAVEI2 then goto leavei2; |
|||
BCTR R6,0 i-- |
|||
ENDDO , enddo i |
|||
LEAVEI2 EQU * ~ |
|||
IF LTR,R6,Z,R6 THEN if i=0 then |
|||
LA R10,1 l=1 |
|||
ELSE , else |
|||
LR R10,R6 l=i |
|||
ENDIF , endif |
|||
IF C,R7,EQ,=F'1' THEN if j=1 then |
|||
L R11,IB ibx=ib |
|||
ENDIF , endif |
|||
IF C,R7,EQ,=F'2' THEN if j=2 then |
|||
LR R1,R9 c |
|||
SLA R1,2 ~ |
|||
L R11,WID-L'WID(R1) wid(c) |
|||
A R11,IB +ib |
|||
SR R11,R10 ibx=ib+wid(c)-l |
|||
ENDIF , endif |
|||
IF C,R7,EQ,=F'3' THEN if j=3 then |
|||
LR R1,R9 c |
|||
SLA R1,2 ~ |
|||
L R11,WID-L'WID(R1) wid(c) |
|||
SR R11,R10 -l |
|||
SRA R11,1 /2 |
|||
A R11,IB ibx=ib+(wid(c)-l)/2 |
|||
ENDIF , endif |
|||
LA R2,PG-1 @pg |
|||
AR R2,R11 +ibx |
|||
LR R3,R10 l |
|||
LA R4,W @w |
|||
LR R5,R10 l |
|||
MVCL R2,R4 substr(pg,ibx,l)=substr(w,1,l) |
|||
LR R1,R9 c |
|||
SLA R1,2 ~ |
|||
L R2,WID-L'WID(R1) wid(c) |
|||
A R2,IB +ib |
|||
LA R2,1(R2) +1 |
|||
ST R2,IB ib=ib+wid(c)+1 |
|||
LA R9,1(R9) c++ |
|||
ENDDO , enddo c |
|||
XPRNT PG,L'PG print |
|||
LA R8,1(R8) r++ |
|||
ENDDO , enddo r |
|||
LA R7,1(R7) j++ |
|||
ENDDO , enddo j |
|||
L R13,4(0,R13) restore previous savearea pointer |
|||
RETURN (14,12),RC=0 restore registers from calling sav |
|||
SEQ EQU * --begin seq |
|||
LA R9,1(R9) c=c+1 |
|||
LR R10,R6 i |
|||
S R10,I0 l=i-i0 |
|||
LA R4,WT-1 @wt |
|||
A R4,I0 +i0 |
|||
LR R5,R10 l |
|||
ICM R5,B'1000',=C' ' padding |
|||
LR R1,R8 r |
|||
BCTR R1,0 -1 |
|||
MH R1,=AL2(NJ) ~ |
|||
AR R1,R9 +c |
|||
MH R1,=AL2(L'WOR) ~ |
|||
LA R2,WOR-L'WOR(R1) @wor(r,c) |
|||
LA R3,L'WOR length(wor) |
|||
MVCL R2,R4 wor(r,c)=substr(wt,i0,l) |
|||
LR R1,R9 c |
|||
SLA R1,2 ~ |
|||
L R2,WID-L'WID(R1) wid(c) |
|||
IF CR,R2,LT,R10 THEN if l>wid(c) then |
|||
LR R1,R9 c |
|||
SLA R1,2 ~ |
|||
ST R10,WID-L'WID(R1) wid(c)=l |
|||
ENDIF , endif |
|||
BR R14 --end seq |
|||
NI EQU 6 ni |
|||
NJ EQU 12 nj |
|||
T DC CL68'Given$a$text$file$of$many$lines,$where$fields$within$a$line$' |
|||
DC CL68'are$delineated$by$a$single$''dollar''$character,$write$a$progX |
|||
ramm' |
|||
DC CL68'that$aligns$each$column$of$fields$by$ensuring$that$words$in$eX |
|||
ach$' |
|||
DC CL68'column$are$separated$by$at$least$one$space.' |
|||
DC CL68'Further,$allow$for$each$word$in$a$column$to$be$either$left$' |
|||
DC CL68'justified,$right$justified,$or$center$justified$within$its$coX |
|||
lumn.' |
|||
WOR DC (NI*NJ)CL10' ' wor(ni,nj) char(10) |
|||
WID DC 16F'0' wid(16) |
|||
COLS DC F'0' |
|||
ROWS DC F'0' |
|||
WT DS CL(L'T) |
|||
W DS CL(L'WOR) |
|||
CI DS CL1 |
|||
I0 DS F |
|||
IB DS F |
|||
PG DS CL120 |
|||
REGEQU |
|||
END ALICOL </syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
-- |
|||
Given a text file of many lines, where fields within a line |
|||
are delineated by a single 'dollar' character, write a programm |
|||
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 programm |
|||
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 programm |
|||
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. |
|||
</pre> |
|||
=={{header|8th}}== |
|||
<syntaxhighlight lang="forth"> |
|||
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.| |
|||
var, raw-text |
|||
[] var, data |
|||
var width |
|||
: read-and-parse \ -- |
|||
raw-text @ |
|||
( "$" s:/ data @ swap a:push drop ) |
|||
s:eachline ; |
|||
: find-widest \ -- n |
|||
data @ ( ( swap s:len nip n:max ) swap a:reduce ) 0 a:reduce ; |
|||
: print-data \ fmt -- |
|||
width @ swap s:strfmt >r |
|||
data @ |
|||
( |
|||
nip |
|||
( |
|||
nip |
|||
r@ s:strfmt . |
|||
) a:each drop |
|||
cr |
|||
) a:each drop rdrop ; |
|||
: app:main |
|||
read-and-parse |
|||
\ find widest column, and add one for the space: |
|||
find-widest n:1+ width ! |
|||
\ print the data |
|||
cr "right:" . cr "%%>%ds" print-data |
|||
cr "left:" . cr "%%<%ds" print-data |
|||
cr "center:" . cr "%%|%ds" print-data |
|||
bye ; |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
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. |
|||
</pre> |
|||
=={{header|AArch64 Assembly}}== |
|||
{{works with|as|Raspberry Pi 3B version Buster 64 bits <br> or android 64 bits with application Termux }} |
|||
<syntaxhighlight lang="aarch64 assembly"> |
|||
/* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits */ |
|||
/* program alignColumn64.s */ |
|||
/*******************************************/ |
|||
/* Constantes file */ |
|||
/*******************************************/ |
|||
/* for this file see task include a file in language AArch64 assembly*/ |
|||
.include "../includeConstantesARM64.inc" |
|||
.equ BUFFERSIZE, 16 * 10 |
|||
/*********************************/ |
|||
/* Initialized data */ |
|||
/*********************************/ |
|||
.data |
|||
szMessLeft: .asciz "LEFT :\n" |
|||
szMessRight: .asciz "\nRIGHT :\n" |
|||
szMessCenter: .asciz "\nCENTER :\n" |
|||
szCarriageReturn: .asciz "\n" |
|||
szLine1: .asciz "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" |
|||
szLine2: .asciz "are$delineated$by$a$single$'dollar'$character,$write$a$program" |
|||
szLine3: .asciz "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" |
|||
szLine4: .asciz "column$are$separated$by$at$least$one$space." |
|||
szLine5: .asciz "Further,$allow$for$each$word$in$a$column$to$be$either$left$" |
|||
szLine6: .asciz "justified,$right$justified,$or$center$justified$within$its$column." |
|||
.align 8 |
|||
qtbPtLine: .quad szLine1,szLine2,szLine3,szLine4,szLine5,szLine6 |
|||
.equ NBLINES, (. - qtbPtLine) / 8 |
|||
/*********************************/ |
|||
/* UnInitialized data */ |
|||
/*********************************/ |
|||
.bss |
|||
/*********************************/ |
|||
/* code section */ |
|||
/*********************************/ |
|||
.text |
|||
.global main |
|||
main: // entry of program |
|||
ldr x0,qAdrqtbPtLine |
|||
bl computeMaxiLengthWords |
|||
mov x19,x0 // column counter |
|||
ldr x0,qAdrszMessLeft |
|||
bl affichageMess |
|||
ldr x0,qAdrqtbPtLine |
|||
mov x1,x19 // column size |
|||
bl alignLeft |
|||
ldr x0,qAdrszMessRight |
|||
bl affichageMess |
|||
ldr x0,qAdrqtbPtLine |
|||
mov x1,x19 // column size |
|||
bl alignRight |
|||
ldr x0,qAdrszMessCenter |
|||
bl affichageMess |
|||
ldr x0,qAdrqtbPtLine |
|||
mov x1,x19 // column size |
|||
bl alignCenter |
|||
100: // standard end of the program |
|||
mov x0, #0 // return code |
|||
mov x8, #EXIT // request to exit program |
|||
svc #0 // perform the system call |
|||
qAdrszCarriageReturn: .quad szCarriageReturn |
|||
qAdrszMessLeft: .quad szMessLeft |
|||
qAdrszMessRight: .quad szMessRight |
|||
qAdrszMessCenter: .quad szMessCenter |
|||
qAdrqtbPtLine: .quad qtbPtLine |
|||
/******************************************************************/ |
|||
/* compute maxi words */ |
|||
/******************************************************************/ |
|||
/* x0 contains adresse pointer array */ |
|||
computeMaxiLengthWords: |
|||
stp fp,lr,[sp,-16]! // save registres |
|||
mov x2,#0 // indice pointer array |
|||
mov x3,#0 // maxi length words |
|||
1: |
|||
ldr x1,[x0,x2,lsl #3] // load pointer |
|||
mov x4,#0 // length words counter |
|||
mov x5,#0 // indice line character |
|||
2: |
|||
ldrb w6,[x1,x5] // load a line character |
|||
cmp x6,#0 // line end ? |
|||
beq 4f |
|||
cmp x6,#'$' // separator ? |
|||
bne 3f |
|||
cmp x4,x3 |
|||
csel x3,x4,x3,gt // if greather replace maxi |
|||
mov x4,#-1 // raz length counter |
|||
3: |
|||
add x4,x4,#1 |
|||
add x5,x5,#1 // increment character indice |
|||
b 2b // and loop |
|||
4: // end line |
|||
cmp x4,x3 // compare word counter and maxi |
|||
csel x3,x4,x3,gt // if greather replace maxi |
|||
add x2,x2,#1 // increment indice line pointer |
|||
cmp x2,#NBLINES // maxi ? |
|||
blt 1b // no -> loop |
|||
mov x0,x3 // return maxi length counter |
|||
100: |
|||
ldp fp,lr,[sp],16 // restaur des 2 registres |
|||
ret |
|||
/******************************************************************/ |
|||
/* align left */ |
|||
/******************************************************************/ |
|||
/* x0 contains the address of pointer array*/ |
|||
/* x1 contains column size */ |
|||
alignLeft: |
|||
stp fp,lr,[sp,-16]! // save registres |
|||
sub sp,sp,#BUFFERSIZE // reserve place for output buffer |
|||
mov fp,sp |
|||
mov x5,x0 // array address |
|||
mov x2,#0 // indice array |
|||
1: |
|||
ldr x3,[x5,x2,lsl #3] // load line pointer |
|||
mov x4,#0 // line character indice |
|||
mov x7,#0 // output buffer character indice |
|||
mov x6,#0 // word lenght |
|||
2: |
|||
ldrb w0,[x3,x4] // load a character line |
|||
strb w0,[fp,x7] // store in buffer |
|||
cmp w0,#0 // line end ? |
|||
beq 6f |
|||
cmp w0,#'$' // separator ? |
|||
bne 5f |
|||
mov x0,#' ' |
|||
strb w0,[fp,x7] // replace $ by space |
|||
3: |
|||
cmp x6,x1 // length word >= length column |
|||
bge 4f |
|||
add x7,x7,#1 |
|||
mov x0,#' ' |
|||
strb w0,[fp,x7] // add space to buffer |
|||
add x6,x6,#1 |
|||
b 3b // and loop |
|||
4: |
|||
mov x6,#-1 // raz word length |
|||
5: |
|||
add x4,x4,#1 // increment line indice |
|||
add x7,x7,#1 // increment buffer indice |
|||
add x6,x6,#1 // increment word length |
|||
b 2b |
|||
6: |
|||
mov x0,#'\n' |
|||
strb w0,[fp,x7] // return line |
|||
add x7,x7,#1 |
|||
mov x0,#0 |
|||
strb w0,[fp,x7] // final zéro |
|||
mov x0,fp |
|||
bl affichageMess // display output buffer |
|||
add x2,x2,#1 |
|||
cmp x2,#NBLINES |
|||
blt 1b |
|||
100: |
|||
add sp,sp,#BUFFERSIZE |
|||
ldp fp,lr,[sp],16 // restaur des 2 registres |
|||
ret |
|||
/******************************************************************/ |
|||
/* align right */ |
|||
/******************************************************************/ |
|||
/* x0 contains the address of pointer array*/ |
|||
/* x1 contains column size */ |
|||
alignRight: |
|||
stp fp,lr,[sp,-16]! // save registres |
|||
sub sp,sp,#BUFFERSIZE // reserve place for output buffer |
|||
mov fp,sp |
|||
mov x5,x0 // array address |
|||
mov x2,#0 // indice array |
|||
1: |
|||
ldr x3,[x5,x2,lsl #3] // load line pointer |
|||
mov x4,#0 // line character indice |
|||
mov x7,#0 // output buffer character indice |
|||
mov x6,#0 // word lenght |
|||
mov x8,x3 // word begin address |
|||
2: // compute word length |
|||
ldrb w0,[x3,x4] // load a character line |
|||
cmp w0,#0 // line end ? |
|||
beq 3f |
|||
cmp w0,#'$' // separator ? |
|||
beq 3f |
|||
add x4,x4,#1 // increment line indice |
|||
add x6,x6,#1 // increment word length |
|||
b 2b |
|||
3: |
|||
cmp x6,#0 |
|||
beq 4f |
|||
sub x6,x1,x6 // compute left spaces to add |
|||
4: // loop add spaces to buffer |
|||
cmp x6,#0 |
|||
blt 5f |
|||
mov x0,#' ' |
|||
strb w0,[fp,x7] // add space to buffer |
|||
add x7,x7,#1 |
|||
sub x6,x6,#1 |
|||
b 4b // and loop |
|||
5: |
|||
mov x9,#0 |
|||
6: // copy loop word to buffer |
|||
ldrb w0,[x8,x9] |
|||
cmp x0,#'$' |
|||
beq 7f |
|||
cmp x0,#0 // line end |
|||
beq 8f |
|||
strb w0,[fp,x7] |
|||
add x7,x7,#1 |
|||
add x9,x9,#1 |
|||
b 6b |
|||
7: |
|||
add x8,x8,x9 |
|||
add x8,x8,#1 // new word begin |
|||
mov x6,#0 // raz word length |
|||
add x4,x4,#1 // increment line indice |
|||
b 2b |
|||
8: |
|||
mov x0,#'\n' |
|||
strb w0,[fp,x7] // return line |
|||
add x7,x7,#1 |
|||
mov x0,#0 |
|||
strb w0,[fp,x7] // final zéro |
|||
mov x0,fp |
|||
bl affichageMess // display output buffer |
|||
add x2,x2,#1 |
|||
cmp x2,#NBLINES |
|||
blt 1b |
|||
100: |
|||
add sp,sp,#BUFFERSIZE |
|||
ldp fp,lr,[sp],16 // restaur des 2 registres |
|||
ret |
|||
/******************************************************************/ |
|||
/* align center */ |
|||
/******************************************************************/ |
|||
/* x0 contains the address of pointer array*/ |
|||
/* x1 contains column size */ |
|||
alignCenter: |
|||
stp fp,lr,[sp,-16]! // save registres |
|||
sub sp,sp,#BUFFERSIZE // reserve place for output buffer |
|||
mov fp,sp |
|||
mov x5,x0 // array address |
|||
mov x2,#0 // indice array |
|||
1: |
|||
ldr x3,[x5,x2,lsl #3] // load line pointer |
|||
mov x4,#0 // line character indice |
|||
mov x7,#0 // output buffer character indice |
|||
mov x6,#0 // word length |
|||
mov x8,x3 // word begin address |
|||
2: // compute word length |
|||
ldrb w0,[x3,x4] // load a character line |
|||
cmp w0,#0 // line end ? |
|||
beq 3f |
|||
cmp w0,#'$' // separator ? |
|||
beq 3f |
|||
add x4,x4,#1 // increment line indice |
|||
add x6,x6,#1 // increment word length |
|||
b 2b |
|||
3: |
|||
cmp x6,#0 |
|||
beq 5f |
|||
sub x6,x1,x6 // total spaces number to add |
|||
mov x12,x6 |
|||
lsr x6,x6,#1 // divise by 2 = left spaces number |
|||
4: |
|||
cmp x6,#0 |
|||
blt 5f |
|||
mov x0,#' ' |
|||
strb w0,[fp,x7] // add space to buffer |
|||
add x7,x7,#1 // increment output indice |
|||
sub x6,x6,#1 // decrement number space |
|||
b 4b // and loop |
|||
5: |
|||
mov x9,#0 |
|||
6: // copy loop word to buffer |
|||
ldrb w0,[x8,x9] |
|||
cmp x0,#'$' // séparator ? |
|||
beq 7f |
|||
cmp x0,#0 // line end ? |
|||
beq 10f |
|||
strb w0,[fp,x7] |
|||
add x7,x7,#1 |
|||
add x9,x9,#1 |
|||
b 6b |
|||
7: |
|||
lsr x6,x12,#1 // divise total spaces by 2 |
|||
sub x6,x12,x6 // and compute number spaces to right side |
|||
8: // loop to add right spaces |
|||
cmp x6,#0 |
|||
ble 9f |
|||
mov x0,#' ' |
|||
strb w0,[fp,x7] // add space to buffer |
|||
add x7,x7,#1 |
|||
sub x6,x6,#1 |
|||
b 8b // and loop |
|||
9: |
|||
add x8,x8,x9 |
|||
add x8,x8,#1 // new address word begin |
|||
mov x6,#0 // raz word length |
|||
add x4,x4,#1 // increment line indice |
|||
b 2b // and loop new word |
|||
10: |
|||
mov x0,#'\n' |
|||
strb w0,[fp,x7] // return line |
|||
add x7,x7,#1 |
|||
mov x0,#0 |
|||
strb w0,[fp,x7] // final zéro |
|||
mov x0,fp |
|||
bl affichageMess // display output buffer |
|||
add x2,x2,#1 // increment line indice |
|||
cmp x2,#NBLINES // maxi ? |
|||
blt 1b // loop |
|||
100: |
|||
add sp,sp,#BUFFERSIZE |
|||
ldp fp,lr,[sp],16 // restaur des 2 registres |
|||
ret |
|||
/********************************************************/ |
|||
/* File Include fonctions */ |
|||
/********************************************************/ |
|||
/* for this file see task include a file in language AArch64 assembly */ |
|||
.include "../includeARM64.inc" |
|||
</syntaxhighlight> |
|||
<pre> |
|||
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. |
|||
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. |
|||
</pre> |
|||
=={{header|ABAP}}== |
|||
<syntaxhighlight lang="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.</syntaxhighlight> |
|||
<pre style="height:15ex;overflow:scroll">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.</pre> |
|||
=={{header|Action!}}== |
|||
Atari 8-bit computer is able to show only 40 characters per line. The user has to press left/right arrow keys to scroll the content of whole text. |
|||
<syntaxhighlight lang="action!">DEFINE LINES_COUNT="10" |
|||
DEFINE COLUMNS_COUNT="20" |
|||
DEFINE WORDS_COUNT="100" |
|||
DEFINE BUFFER_SIZE="2000" |
|||
DEFINE LINE_WIDTH="40" |
|||
DEFINE PTR="CARD" |
|||
PTR ARRAY lines(LINES_COUNT) |
|||
BYTE ARRAY wordStart(WORDS_COUNT) |
|||
BYTE ARRAY wordLen(WORDS_COUNT) |
|||
BYTE ARRAY firstWordInLine(LINES_COUNT) |
|||
BYTE ARRAY wordsInLine(LINES_COUNT) |
|||
BYTE ARRAY colWidths(COLUMNS_COUNT) |
|||
BYTE ARRAY buffer(BUFFER_SIZE) |
|||
BYTE lineCount,colCount,wordCount |
|||
CHAR sep=['$] |
|||
PROC AddLine(CHAR ARRAY line) |
|||
lines(lineCount)=line |
|||
lineCount==+1 |
|||
RETURN |
|||
PROC InitData() |
|||
lineCount=0 |
|||
AddLine("Given$a$text$file$of$many$lines,$where$fields$within$a$line$") |
|||
AddLine("are$delineated$by$a$single$'dollar'$character,$write$a$program") |
|||
AddLine("that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$") |
|||
AddLine("column$are$separated$by$at$least$one$space.") |
|||
AddLine("Further,$allow$for$each$word$in$a$column$to$be$either$left$") |
|||
AddLine("justified,$right$justified,$or$center$justified$within$its$column.") |
|||
RETURN |
|||
PROC ProcessData() |
|||
BYTE i,pos,len,start,w,col |
|||
CHAR ARRAY line |
|||
colCount=0 wordCount=0 |
|||
FOR i=0 TO lineCount-1 |
|||
DO |
|||
line=lines(i) |
|||
len=line(0) |
|||
firstWordInLine(i)=wordCount |
|||
wordsInLine(i)=0 |
|||
pos=1 col=0 |
|||
WHILE pos<=len |
|||
DO |
|||
start=pos |
|||
WHILE pos<=len AND line(pos)#sep |
|||
DO pos==+1 OD |
|||
w=pos-start |
|||
wordStart(wordCount)=start |
|||
wordLen(wordCount)=w |
|||
wordCount==+1 |
|||
wordsInLine(i)==+1 |
|||
IF col=colCount THEN |
|||
colWidths(col)=w |
|||
colCount==+1 |
|||
ELSEIF w>colWidths(col) THEN |
|||
colWidths(col)=w |
|||
FI |
|||
col==+1 |
|||
pos==+1 |
|||
OD |
|||
OD |
|||
RETURN |
|||
BYTE FUNC GetBufLineLength() |
|||
BYTE i,res |
|||
res=0 |
|||
FOR i=0 TO colCount-1 |
|||
DO |
|||
res==+colWidths(i)+1 |
|||
OD |
|||
res==+1 |
|||
RETURN (res) |
|||
BYTE FUNC AtasciiToInternal(CHAR c) |
|||
BYTE c2 |
|||
c2=c&$7F |
|||
IF c2<32 THEN |
|||
RETURN (c+64) |
|||
ELSEIF c2<96 THEN |
|||
RETURN (c-32) |
|||
FI |
|||
RETURN (c) |
|||
PROC GenerateLine(BYTE index BYTE align BYTE POINTER p) |
|||
BYTE wordIndex,last,left,right,start,len,colW |
|||
INT i,j |
|||
CHAR ARRAY line |
|||
line=lines(index) |
|||
wordIndex=firstWordInLine(index) |
|||
last=wordIndex+wordsInLine(index)-1 |
|||
FOR i=0 TO colCount-1 |
|||
DO |
|||
colW=colWidths(i) |
|||
p^=124 p==+1 |
|||
IF wordIndex<=last THEN |
|||
start=wordStart(wordIndex) |
|||
len=wordLen(wordIndex) |
|||
IF align=0 THEN |
|||
left=0 |
|||
right=colW-len |
|||
ELSEIF align=1 THEN |
|||
left=(colW-len)/2 |
|||
right=colW-left-len |
|||
ELSE |
|||
left=colW-len |
|||
right=0 |
|||
FI |
|||
p==+left |
|||
for j=start TO start+len-1 |
|||
DO |
|||
p^=AtasciiToInternal(line(j)) |
|||
p==+1 |
|||
OD |
|||
p==+right |
|||
ELSE |
|||
p==+colW |
|||
FI |
|||
wordIndex==+1 |
|||
OD |
|||
p^=124 |
|||
RETURN |
|||
PROC FillBuffer(BYTE lineWidth) |
|||
BYTE i,align |
|||
BYTE POINTER p |
|||
p=buffer |
|||
Zero(p,BUFFER_SIZE) |
|||
FOR align=0 TO 2 |
|||
DO |
|||
FOR i=0 TO lineCount-1 |
|||
DO |
|||
GenerateLine(i,align,p) |
|||
p==+lineWidth |
|||
OD |
|||
OD |
|||
RETURN |
|||
BYTE FUNC GetMaxOffset() |
|||
BYTE res |
|||
res=GetBufLineLength()-LINE_WIDTH |
|||
RETURN (res) |
|||
PROC Update(BYTE offset,lineWidth) |
|||
BYTE POINTER srcPtr,dstPtr |
|||
BYTE i |
|||
srcPtr=buffer+offset |
|||
dstPtr=PeekC(88)+3*LINE_WIDTH |
|||
FOR i=0 TO 3*lineCount-1 |
|||
DO |
|||
MoveBlock(dstPtr,srcPtr,LINE_WIDTH) |
|||
srcPtr==+lineWidth |
|||
dstPtr==+LINE_WIDTH |
|||
IF i=lineCount-1 OR i=2*lineCount-1 THEN |
|||
dstPtr==+LINE_WIDTH |
|||
FI |
|||
OD |
|||
RETURN |
|||
PROC Main() |
|||
BYTE |
|||
lineWidth,offset,maxOffset,k, |
|||
CH=$02FC, ;Internal hardware value for last key pressed |
|||
CRSINH=$02F0 ;Controls visibility of cursor |
|||
CRSINH=1 ;hide cursor |
|||
InitData() |
|||
ProcessData() |
|||
lineWidth=GetBufLineLength() |
|||
FillBuffer(lineWidth) |
|||
Position(2,1) |
|||
Print("Press left/right arrow key to scroll") |
|||
maxOffset=lineWidth-LINE_WIDTH |
|||
offset=0 |
|||
Update(offset,lineWidth) |
|||
DO |
|||
k=CH |
|||
IF k#$FF THEN |
|||
CH=$FF |
|||
FI |
|||
IF k=134 AND offset>0 THEN |
|||
offset==-1 |
|||
Update(offset,lineWidth) |
|||
ELSEIF k=135 AND offset<maxOffset THEN |
|||
offset==+1 |
|||
Update(offset,lineWidth) |
|||
ELSEIF k=28 THEN |
|||
EXIT |
|||
FI |
|||
OD |
|||
RETURN</syntaxhighlight> |
|||
{{out}} |
|||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Align_columns.png Screenshot from Atari 8-bit computer] |
|||
<pre> |
|||
Press left/right arrow key to scroll |
|||
|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.| | | | |
|||
</pre> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
{{libheader|Simple components for Ada}} |
{{libheader|Simple components for Ada}} |
||
<syntaxhighlight lang="ada">with Ada.Characters.Latin_1; use Ada.Characters.Latin_1; |
|||
<lang ada> |
|||
with Ada.Characters.Latin_1; use Ada.Characters.Latin_1; |
|||
with Ada.Text_IO; use Ada.Text_IO; |
with Ada.Text_IO; use Ada.Text_IO; |
||
with Strings_Edit; use Strings_Edit; |
with Strings_Edit; use Strings_Edit; |
||
Line 88: | Line 1,096: | ||
end loop; |
end loop; |
||
Close (File); |
Close (File); |
||
end Column_Aligner; |
end Column_Aligner;</syntaxhighlight> |
||
</lang> |
|||
Formatted file sample: |
Formatted file sample: |
||
<pre style="height:15ex;overflow:scroll"> |
<pre style="height:15ex;overflow:scroll"> |
||
Line 111: | Line 1,118: | ||
justified, right justified, or center justified within its column. |
justified, right justified, or center justified within its column. |
||
</pre> |
</pre> |
||
=={{header|Aime}}== |
|||
<syntaxhighlight lang="aime">data b; |
|||
file f; |
|||
text n, t; |
|||
list c, r, s; |
|||
integer a, i, k, m, w; |
|||
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(b); |
|||
m = 0; |
|||
while (f.news(r, 0, 0, "$") ^ -1) { |
|||
c.append(r); |
|||
m = max(m, ~r); |
|||
} |
|||
i = 0; |
|||
while (i < m) { |
|||
w = 0; |
|||
for (, r in c) { |
|||
if (i < ~r) { |
|||
w = max(w, length(r[i])); |
|||
} |
|||
} |
|||
s.append(w + 1); |
|||
i += 1; |
|||
} |
|||
for (k, t in list("left", "center", "right")) { |
|||
o_(t, " justified\n"); |
|||
for (, r in c) { |
|||
for (i, n in r) { |
|||
m = s[i] - ~n; |
|||
o_form("/w~3/~/w~1/", a = (2 - k) * m >> 1, "", m - a, "", n); |
|||
} |
|||
o_newline(); |
|||
} |
|||
o_newline(); |
|||
}</syntaxhighlight> |
|||
{{Out}} |
|||
<pre>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.</pre> |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
<syntaxhighlight lang="algol68">STRING nl = REPR 10; |
|||
<lang algol> |
|||
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+ |
||
"are$delineated$by$a$single$'dollar'$character,$write$a$program"+nl+ |
"are$delineated$by$a$single$'dollar'$character,$write$a$program"+nl+ |
||
Line 178: | Line 1,256: | ||
aligner(page, align OF aligners[index]) |
aligner(page, align OF aligners[index]) |
||
OD |
OD |
||
END</ |
END</syntaxhighlight> |
||
=={{header| |
=={{header|Amazing Hopper}}== |
||
<syntaxhighlight lang="amazing hopper"> |
|||
#define IGet(__N__,__X__) [__N__]SGet(__X__) |
|||
#include <hbasic.h> |
|||
<lang awk>BEGIN { |
|||
#define MAX_LINE 1000 |
|||
FS="$" |
|||
lcounter = 1 |
|||
Begin |
|||
maxfield = 0 |
|||
Option Stack 15 |
|||
# justistification; pick up one |
|||
#justify = "left" |
|||
Declare as Numeric ( fd, i, index, max token ) |
|||
justify = "center" |
|||
as Numeric ( num tokens, size Column, tCells ) |
|||
#justify = "right" |
|||
as Alpha ( line ) |
|||
as Numeric ( display Left, display Right, display Center ) |
|||
GetParam(script, file to edit, separator) |
|||
// get statistics of file: #lines, #total chars, line more long, and num tokens from first line. |
|||
Token Sep( separator ) |
|||
Stat( file to edit, dats ) |
|||
// declare arrays to work: |
|||
Dim ( IGet(1,dats), Add(IGet(4,dats),10) ) for Fill Array("",cells) |
|||
Clear(dats) |
|||
MStore ( cells, display Left, display Right, display Center ) |
|||
// read each line as array, get # of elements, and put into array cells: |
|||
Open(OPEN_READ, file to edit ) (fd) |
|||
When( File Error ){ Stop } |
|||
index=1 |
|||
While Not Eof(fd) |
|||
ReadRow(MAX_LINE)(fd) and Copy to (line); get Length, and Move to (num tokens) |
|||
Set Interval [index, 1:num tokens]; Take( line ) and SPut(cells) |
|||
When ( var( max token) Is Lt (num tokens) ) { max token = num tokens } |
|||
++index |
|||
Wend |
|||
Close(fd) |
|||
// formatting... |
|||
For Up( i:=1, max token, 1 ) |
|||
Set Interval [1:end,i], and Let ( size Column := MaxValue( Len(Get(cells)) ) Plus(1) ) |
|||
Let ( tCells := Get(cells) ) |
|||
LPad$( " ", size Column, tCells ), and Put(display Left) |
|||
RPad$( " ", size Column, tCells ), and Put(display Right) |
|||
CPad$( " ", size Column, tCells ), and Put(display Center) |
|||
Next |
|||
// display: |
|||
Token Sep ("") |
|||
Print("Left Pad:\n", display Left, Newl, "Right Pad:\n", display Right, Newl, "Center Pad:\n", display Center,Newl) |
|||
End |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
Sample String was saved into "sample.txt" file. |
|||
<pre> |
|||
$ hopper src/acolumns.bas sample.txt "$" |
|||
Left Pad: |
|||
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 Pad: |
|||
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 Pad: |
|||
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. |
|||
$ |
|||
</pre> |
|||
=={{header|APL}}== |
|||
<syntaxhighlight lang="apl">align←{ |
|||
left ← {⍺↑⍵} |
|||
right ← {(-⍺)↑⍵} |
|||
center ← {⍺↑(-⌊(≢⍵)+(⍺-≢⍵)÷2)↑⍵} |
|||
text ← ⊃⎕NGET⍵ |
|||
words ← ((≠∘'$')⊆⊣)¨(~text∊⎕TC)⊆text |
|||
sizes ← 1+⌈⌿↑≢¨¨words |
|||
method ← ⍎⍺ |
|||
↑,/↑(⊂sizes)method¨¨↓↑words |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> 'left' align 'test.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. |
|||
'center' align 'test.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. |
|||
'right' align 'test.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.</pre> |
|||
=={{header|AppleScript}}== |
|||
Probably not the first language in which you would really choose to do this kind of thing, but certainly possible, and can be readily easily assembled from a set of generic primitives. |
|||
{{trans|JavaScript}} |
|||
<syntaxhighlight lang="applescript">-- COLUMN ALIGNMENTS --------------------------------------------------------- |
|||
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 |
|||
-- columnsAligned :: EnumValue -> [[String]] -> String |
|||
on columnsAligned(eAlign, lstCols) |
|||
-- padwords :: Int -> [String] -> [[String]] |
|||
script padwords |
|||
on |λ|(n, lstWords) |
|||
-- pad :: String -> String |
|||
script pad |
|||
on |λ|(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 |λ| |
|||
end script |
|||
map(pad, lstWords) |
|||
end |λ| |
|||
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 |λ|(str) |
|||
splitOn(strColDelim, str) |
|||
end |λ| |
|||
end script |
|||
set lstRows to map(_words, splitOn(linefeed, pstrLines)) |
|||
set nCols to widest(lstRows) |
|||
-- fullRow :: [[a]] -> [[a]] |
|||
script fullRow |
|||
on |λ|(lst) |
|||
lst & replicate(nCols - (length of lst), {""}) |
|||
end |λ| |
|||
end script |
|||
transpose(map(fullRow, lstRows)) |
|||
end lineColumns |
|||
-- widest [a] -> Int |
|||
on widest(xs) |
|||
|length|(maximumBy(comparing(my |length|), xs)) |
|||
end widest |
|||
-- TEST ---------------------------------------------------------------------- |
|||
on run |
|||
set lstCols to lineColumns("$", pstrLines) |
|||
script testAlignment |
|||
on |λ|(eAlign) |
|||
columnsAligned(eAlign, lstCols) |
|||
end |λ| |
|||
end script |
|||
intercalate(return & return, ¬ |
|||
map(testAlignment, {eLeft, eRight, eCenter})) |
|||
end run |
|||
-- GENERIC FUNCTIONS --------------------------------------------------------- |
|||
-- comparing :: (a -> b) -> (a -> a -> Ordering) |
|||
on comparing(f) |
|||
set mf to mReturn(f) |
|||
script |
|||
on |λ|(a, b) |
|||
set x to mf's |λ|(a) |
|||
set y to mf's |λ|(b) |
|||
if x < y then |
|||
-1 |
|||
else |
|||
if x > y then |
|||
1 |
|||
else |
|||
0 |
|||
end if |
|||
end if |
|||
end |λ| |
|||
end script |
|||
end comparing |
|||
-- 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 |λ|(v, item i of xs, i, xs) |
|||
end repeat |
|||
return v |
|||
end tell |
|||
end foldl |
|||
-- 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 |
|||
-- length :: [a] -> Int |
|||
on |length|(xs) |
|||
length of xs |
|||
end |length| |
|||
-- 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 |λ| : f |
|||
end script |
|||
end if |
|||
end mReturn |
|||
-- 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 |λ|(item i of xs, i, xs) |
|||
end repeat |
|||
return lst |
|||
end tell |
|||
end map |
|||
-- maximumBy :: (a -> a -> Ordering) -> [a] -> a |
|||
on maximumBy(f, xs) |
|||
set cmp to mReturn(f) |
|||
script max |
|||
on |λ|(a, b) |
|||
if a is missing value or cmp's |λ|(a, b) < 0 then |
|||
b |
|||
else |
|||
a |
|||
end if |
|||
end |λ| |
|||
end script |
|||
foldl(max, missing value, xs) |
|||
end maximumBy |
|||
-- min :: Ord a => a -> a -> a |
|||
on min(x, y) |
|||
if y < x then |
|||
y |
|||
else |
|||
x |
|||
end if |
|||
end min |
|||
-- 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) |
|||
if class of a is string then |
|||
set out to "" |
|||
else |
|||
set out to {} |
|||
end if |
|||
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 |
|||
-- 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 |
|||
-- transpose :: [[a]] -> [[a]] |
|||
on transpose(xss) |
|||
script column |
|||
on |λ|(_, iCol) |
|||
script row |
|||
on |λ|(xs) |
|||
item iCol of xs |
|||
end |λ| |
|||
end script |
|||
map(row, xss) |
|||
end |λ| |
|||
end script |
|||
map(column, item 1 of xss) |
|||
end transpose |
|||
-- [Text] -> Text |
|||
on unlines(lstLines) |
|||
intercalate(linefeed, lstLines) |
|||
end unlines |
|||
-- [Text] -> Text |
|||
on unwords(lstWords) |
|||
intercalate(" ", lstWords) |
|||
end unwords |
|||
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] |
|||
on zipWith(f, xs, ys) |
|||
set lng to min(length of xs, length of ys) |
|||
set lst to {} |
|||
tell mReturn(f) |
|||
repeat with i from 1 to lng |
|||
set end of lst to |λ|(item i of xs, item i of ys) |
|||
end repeat |
|||
return lst |
|||
end tell |
|||
end zipWith</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> 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. </pre> |
|||
=={{header|ARM Assembly}}== |
|||
{{works with|as|Raspberry Pi <br> or android 32 bits with application Termux}} |
|||
<syntaxhighlight lang="arm assembly"> |
|||
/* ARM assembly Raspberry PI */ |
|||
/* program alignColumn.s */ |
|||
/* REMARK 1 : this program use routines in a include file |
|||
see task Include a file language arm assembly |
|||
for the routine affichageMess conversion10 |
|||
see at end of this program the instruction include */ |
|||
/* for constantes see task include a file in arm assembly */ |
|||
/************************************/ |
|||
/* Constantes */ |
|||
/************************************/ |
|||
.include "../constantes.inc" |
|||
.equ BUFFERSIZE, 20 * 10 |
|||
/*********************************/ |
|||
/* Initialized data */ |
|||
/*********************************/ |
|||
.data |
|||
szMessLeft: .asciz "LEFT :\n" |
|||
szMessRight: .asciz "\nRIGHT :\n" |
|||
szMessCenter: .asciz "\nCENTER :\n" |
|||
szCarriageReturn: .asciz "\n" |
|||
szLine1: .asciz "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" |
|||
szLine2: .asciz "are$delineated$by$a$single$'dollar'$character,$write$a$program" |
|||
szLine3: .asciz "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" |
|||
szLine4: .asciz "column$are$separated$by$at$least$one$space." |
|||
szLine5: .asciz "Further,$allow$for$each$word$in$a$column$to$be$either$left$" |
|||
szLine6: .asciz "justified,$right$justified,$or$center$justified$within$its$column." |
|||
itbPtLine: .int szLine1,szLine2,szLine3,szLine4,szLine5,szLine6 |
|||
.equ NBLINES, (. - itbPtLine) / 4 |
|||
/*********************************/ |
|||
/* UnInitialized data */ |
|||
/*********************************/ |
|||
.bss |
|||
/*********************************/ |
|||
/* code section */ |
|||
/*********************************/ |
|||
.text |
|||
.global main |
|||
main: @ entry of program |
|||
ldr r0,iAdritbPtLine |
|||
bl computeMaxiLengthWords |
|||
mov r10,r0 @ column counter |
|||
ldr r0,iAdrszMessLeft |
|||
bl affichageMess |
|||
ldr r0,iAdritbPtLine |
|||
mov r1,r10 @ column size |
|||
bl alignLeft |
|||
ldr r0,iAdrszMessRight |
|||
bl affichageMess |
|||
ldr r0,iAdritbPtLine |
|||
mov r1,r10 @ column size |
|||
bl alignRight |
|||
ldr r0,iAdrszMessCenter |
|||
bl affichageMess |
|||
ldr r0,iAdritbPtLine |
|||
mov r1,r10 @ column size |
|||
bl alignCenter |
|||
100: @ standard end of the program |
|||
mov r0, #0 @ return code |
|||
mov r7, #EXIT @ request to exit program |
|||
svc #0 @ perform the system call |
|||
iAdrszCarriageReturn: .int szCarriageReturn |
|||
iAdrszMessLeft: .int szMessLeft |
|||
iAdrszMessRight: .int szMessRight |
|||
iAdrszMessCenter: .int szMessCenter |
|||
iAdritbPtLine: .int itbPtLine |
|||
/******************************************************************/ |
|||
/* compute maxi words */ |
|||
/******************************************************************/ |
|||
/* r0 contains adresse pointer array */ |
|||
computeMaxiLengthWords: |
|||
push {r1-r6,lr} @ save registers |
|||
mov r2,#0 @ indice pointer array |
|||
mov r3,#0 @ maxi length words |
|||
1: |
|||
ldr r1,[r0,r2,lsl #2] @ load pointer |
|||
mov r4,#0 @ length words counter |
|||
mov r5,#0 @ indice line character |
|||
2: |
|||
ldrb r6,[r1,r5] @ load a line character |
|||
cmp r6,#0 @ line end ? |
|||
beq 4f |
|||
cmp r6,#'$' @ separator ? |
|||
bne 3f |
|||
cmp r4,r3 |
|||
movgt r3,r4 @ ig greather replace maxi |
|||
mov r4,#-1 @ raz length counter |
|||
3: |
|||
add r4,r4,#1 |
|||
add r5,r5,#1 @ increment character indice |
|||
b 2b @ and loop |
|||
4: @ end line |
|||
cmp r4,r3 @ compare word counter and maxi |
|||
movgt r3,r4 @ if greather replace maxi |
|||
add r2,r2,#1 @ increment indice line pointer |
|||
cmp r2,#NBLINES @ maxi ? |
|||
blt 1b @ no -> loop |
|||
mov r0,r3 @ return maxi length counter |
|||
100: |
|||
pop {r1-r6,pc} |
|||
/******************************************************************/ |
|||
/* align left */ |
|||
/******************************************************************/ |
|||
/* r0 contains the address of pointer array*/ |
|||
/* r1 contains column size */ |
|||
alignLeft: |
|||
push {r4-r7,fp,lr} @ save registers |
|||
sub sp,sp,#BUFFERSIZE @ reserve place for output buffer |
|||
mov fp,sp |
|||
mov r5,r0 @ array address |
|||
mov r2,#0 @ indice array |
|||
1: |
|||
ldr r3,[r5,r2,lsl #2] @ load line pointer |
|||
mov r4,#0 @ line character indice |
|||
mov r7,#0 @ output buffer character indice |
|||
mov r6,#0 @ word lenght |
|||
2: |
|||
ldrb r0,[r3,r4] @ load a character line |
|||
strb r0,[fp,r7] @ store in buffer |
|||
cmp r0,#0 @ line end ? |
|||
beq 6f |
|||
cmp r0,#'$' @ separator ? |
|||
bne 5f |
|||
mov r0,#' ' |
|||
strb r0,[fp,r7] @ replace $ by space |
|||
3: |
|||
cmp r6,r1 @ length word >= length column |
|||
bge 4f |
|||
add r7,r7,#1 |
|||
mov r0,#' ' |
|||
strb r0,[fp,r7] @ add space to buffer |
|||
add r6,r6,#1 |
|||
b 3b @ and loop |
|||
4: |
|||
mov r6,#-1 @ raz word length |
|||
5: |
|||
add r4,r4,#1 @ increment line indice |
|||
add r7,r7,#1 @ increment buffer indice |
|||
add r6,r6,#1 @ increment word length |
|||
b 2b |
|||
6: |
|||
mov r0,#'\n' |
|||
strb r0,[fp,r7] @ return line |
|||
add r7,r7,#1 |
|||
mov r0,#0 |
|||
strb r0,[fp,r7] @ final zéro |
|||
mov r0,fp |
|||
bl affichageMess @ display output buffer |
|||
add r2,r2,#1 |
|||
cmp r2,#NBLINES |
|||
blt 1b |
|||
100: |
|||
add sp,sp,#BUFFERSIZE |
|||
pop {r4-r7,fp,pc} |
|||
/******************************************************************/ |
|||
/* align right */ |
|||
/******************************************************************/ |
|||
/* r0 contains the address of pointer array*/ |
|||
/* r1 contains column size */ |
|||
alignRight: |
|||
push {r4-r9,fp,lr} @ save registers |
|||
sub sp,sp,#BUFFERSIZE @ reserve place for output buffer |
|||
mov fp,sp |
|||
mov r5,r0 @ array address |
|||
mov r2,#0 @ indice array |
|||
1: |
|||
ldr r3,[r5,r2,lsl #2] @ load line pointer |
|||
mov r4,#0 @ line character indice |
|||
mov r7,#0 @ output buffer character indice |
|||
mov r6,#0 @ word lenght |
|||
mov r8,r3 @ word begin address |
|||
2: @ compute word length |
|||
ldrb r0,[r3,r4] @ load a character line |
|||
cmp r0,#0 @ line end ? |
|||
beq 3f |
|||
cmp r0,#'$' @ separator ? |
|||
beq 3f |
|||
add r4,r4,#1 @ increment line indice |
|||
add r6,r6,#1 @ increment word length |
|||
b 2b |
|||
3: |
|||
cmp r6,#0 |
|||
beq 4f |
|||
sub r6,r1,r6 @ compute left spaces to add |
|||
4: @ loop add spaces to buffer |
|||
cmp r6,#0 |
|||
blt 5f |
|||
mov r0,#' ' |
|||
strb r0,[fp,r7] @ add space to buffer |
|||
add r7,r7,#1 |
|||
sub r6,r6,#1 |
|||
b 4b @ and loop |
|||
5: |
|||
mov r9,#0 |
|||
6: @ copy loop word to buffer |
|||
ldrb r0,[r8,r9] |
|||
cmp r0,#'$' |
|||
beq 7f |
|||
cmp r0,#0 @ line end |
|||
beq 8f |
|||
strb r0,[fp,r7] |
|||
add r7,r7,#1 |
|||
add r9,r9,#1 |
|||
b 6b |
|||
7: |
|||
add r8,r8,r9 |
|||
add r8,r8,#1 @ new word begin |
|||
mov r6,#0 @ raz word length |
|||
add r4,r4,#1 @ increment line indice |
|||
b 2b |
|||
8: |
|||
mov r0,#'\n' |
|||
strb r0,[fp,r7] @ return line |
|||
add r7,r7,#1 |
|||
mov r0,#0 |
|||
strb r0,[fp,r7] @ final zéro |
|||
mov r0,fp |
|||
bl affichageMess @ display output buffer |
|||
add r2,r2,#1 |
|||
cmp r2,#NBLINES |
|||
blt 1b |
|||
100: |
|||
add sp,sp,#BUFFERSIZE |
|||
pop {r4-r9,fp,pc} |
|||
/******************************************************************/ |
|||
/* align center */ |
|||
/******************************************************************/ |
|||
/* r0 contains the address of pointer array*/ |
|||
/* r1 contains column size */ |
|||
alignCenter: |
|||
push {r4-r12,lr} @ save registers |
|||
sub sp,sp,#BUFFERSIZE @ reserve place for output buffer |
|||
mov fp,sp |
|||
mov r5,r0 @ array address |
|||
mov r2,#0 @ indice array |
|||
1: |
|||
ldr r3,[r5,r2,lsl #2] @ load line pointer |
|||
mov r4,#0 @ line character indice |
|||
mov r7,#0 @ output buffer character indice |
|||
mov r6,#0 @ word length |
|||
mov r8,r3 @ word begin address |
|||
2: @ compute word length |
|||
ldrb r0,[r3,r4] @ load a character line |
|||
cmp r0,#0 @ line end ? |
|||
beq 3f |
|||
cmp r0,#'$' @ separator ? |
|||
beq 3f |
|||
add r4,r4,#1 @ increment line indice |
|||
add r6,r6,#1 @ increment word length |
|||
b 2b |
|||
3: |
|||
cmp r6,#0 |
|||
beq 5f |
|||
sub r6,r1,r6 @ total spaces number to add |
|||
mov r12,r6 |
|||
lsr r6,r6,#1 @ divise by 2 = left spaces number |
|||
4: |
|||
cmp r6,#0 |
|||
blt 5f |
|||
mov r0,#' ' |
|||
strb r0,[fp,r7] @ add space to buffer |
|||
add r7,r7,#1 @ increment output indice |
|||
sub r6,r6,#1 @ decrement number space |
|||
b 4b @ and loop |
|||
5: |
|||
mov r9,#0 |
|||
6: @ copy loop word to buffer |
|||
ldrb r0,[r8,r9] |
|||
cmp r0,#'$' @ séparator ? |
|||
beq 7f |
|||
cmp r0,#0 @ line end ? |
|||
beq 10f |
|||
strb r0,[fp,r7] |
|||
add r7,r7,#1 |
|||
add r9,r9,#1 |
|||
b 6b |
|||
7: |
|||
lsr r6,r12,#1 @ divise total spaces by 2 |
|||
sub r6,r12,r6 @ and compute number spaces to right side |
|||
8: @ loop to add right spaces |
|||
cmp r6,#0 |
|||
ble 9f |
|||
mov r0,#' ' |
|||
strb r0,[fp,r7] @ add space to buffer |
|||
add r7,r7,#1 |
|||
sub r6,r6,#1 |
|||
b 8b @ and loop |
|||
9: |
|||
add r8,r8,r9 |
|||
add r8,r8,#1 @ new address word begin |
|||
mov r6,#0 @ raz word length |
|||
add r4,r4,#1 @ increment line indice |
|||
b 2b @ and loop new word |
|||
10: |
|||
mov r0,#'\n' |
|||
strb r0,[fp,r7] @ return line |
|||
add r7,r7,#1 |
|||
mov r0,#0 |
|||
strb r0,[fp,r7] @ final zéro |
|||
mov r0,fp |
|||
bl affichageMess @ display output buffer |
|||
add r2,r2,#1 @ increment line indice |
|||
cmp r2,#NBLINES @ maxi ? |
|||
blt 1b @ loop |
|||
100: |
|||
add sp,sp,#BUFFERSIZE |
|||
pop {r4-r12,pc} |
|||
/***************************************************/ |
|||
/* ROUTINES INCLUDE */ |
|||
/***************************************************/ |
|||
.include "../affichage.inc" |
|||
</syntaxhighlight> |
|||
<pre> |
|||
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. |
|||
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. |
|||
</pre> |
|||
=={{header|Arturo}}== |
|||
<syntaxhighlight lang="rebol">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. |
|||
} |
} |
||
{ |
|||
output: map split.lines text => [split.by:"$" &] |
|||
if ( NF > maxfield ) maxfield = NF; |
|||
for(i=1; i <= NF; i++) { |
|||
loop output 'line [ |
|||
line[lcounter,i] = $i |
|||
loop line 'word -> prints pad word 12 |
|||
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 "" |
print "" |
||
]</syntaxhighlight> |
|||
} |
|||
}</lang> |
|||
{{out}} |
|||
<pre> Given a text file of many lines, where fields within a line |
|||
<lang c>#include <stdio.h> |
|||
are delineated by a single 'dollar' character, write a program |
|||
#include <stdlib.h> |
|||
that aligns each column of fields by ensuring that words in each |
|||
#include <string.h> |
|||
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.</pre> |
|||
=={{header|AutoHotkey}}== |
|||
struct linelement { |
|||
char **wordlist; |
|||
int longest; |
|||
struct linelement *next; |
|||
}; |
|||
<syntaxhighlight lang="autohotkey">Alignment := "L" ; Options: L, R, C |
|||
typedef struct linelement line_t; |
|||
Text = |
|||
( LTrim |
|||
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. |
|||
) |
|||
Loop, Parse, Text ; calculate column's width |
|||
char *trim(char *s, int *len) |
|||
If A_LoopField in $,`n |
|||
{ |
|||
If (N > W) |
|||
char *b; |
|||
W := N, N := 0 |
|||
int l; |
|||
Else |
|||
N := 0 |
|||
Else |
|||
++N |
|||
Width := ++W |
|||
Loop, Parse, Text, `n ; process each line |
|||
while( (*s == ' ') || (*s == '\t') ) s++; |
|||
{ |
|||
b = s; |
|||
Words := StrSplit(A_LoopField, "$") |
|||
l = strlen(b); |
|||
For i, Word in Words ; process each word |
|||
s += l; s--; |
|||
Line .= Align(Word, Alignment, Width) |
|||
while( (*s == ' ') || (*s == '\t') ) s--; |
|||
Result .= RTrim(Line) . "`n" |
|||
s++; *s = 0; |
|||
Line := "" |
|||
if ( l > *len ) *len = l; |
|||
return b; |
|||
} |
} |
||
Clipboard := Result ; present results |
|||
char **split(char *l, int c, int *longest) |
|||
MsgBox, The results are in the Clipboard |
|||
{ |
|||
int howmany, i; |
|||
char **arr; |
|||
char *n; |
|||
Align(Pal, How, Width) { ; function for alignment |
|||
if ( (n = strchr(l, 10)) != NULL ) *n = 0; |
|||
Length := StrLen(Pal) |
|||
if ( (n = strchr(l, 13)) != NULL ) *n = 0; |
|||
If (How = "L") |
|||
Return Pal . Spc(Width - Length) |
|||
Else If (How = "R") |
|||
Return Spc(Width - Length) . Pal |
|||
Else If (How = "C") |
|||
Return Spc((Width - Length)//2) . Pal . Spc(Width - Length - (Width - Length)//2) |
|||
} |
|||
Spc(Number) { ; function to concatenate space characters |
|||
for(howmany=1, i=0; l[i] != 0 ; i++) |
|||
Loop, %Number% |
|||
if ( (l[i]==c) && ((i+1) < strlen(l))) howmany++; |
|||
Ret .= A_Space |
|||
arr = malloc(sizeof(char *) * (howmany+1)); |
|||
Return Ret |
|||
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; |
|||
} |
} |
||
</syntaxhighlight> |
|||
=={{header|AutoIt}}== |
|||
<syntaxhighlight lang="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() |
|||
#define MAXLINELEN 1024 |
|||
Global $sText = _ |
|||
#define FILLCHAR ' ' |
|||
"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) |
|||
/* decide the alignment */ |
|||
enum textalign { |
|||
LEFT_ALIGNED, RIGHT_ALIGNED, CENTER_ALIGNED |
|||
}; |
|||
const int alignment = CENTER_ALIGNED; |
|||
; == 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 |
|||
int main() |
|||
Global $aFields[$iLines][$iMaxColumn +1][2] |
|||
{ |
|||
; == and store the max. length of item in columns |
|||
char buf[MAXLINELEN]; |
|||
Global $aColLen[$iMaxColumn] |
|||
line_t *head, *cur; |
|||
char *lb; |
|||
int reallongest, i, len, ipos; |
|||
; == fill the array |
|||
head = malloc(sizeof(line_t)); |
|||
Global $aSplitLine |
|||
memset(head, 0, sizeof(line_t)); |
|||
$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 |
|||
/* for each line, split it ($-separated words) */ |
|||
$sAlign = InputBox('Column alignment', 'There are ' & $iMaxColumn & ' columns.' & @LF & '0 = left 1 = center 2 = right' & @LF & _ |
|||
cur = head; |
|||
'Input alignment for all columns without delimiters.' & @LF & 'Let it empty, to align all left.') |
|||
while ( fgets(buf, MAXLINELEN, stdin) != NULL ) { |
|||
If $sAlign = '' Then |
|||
lb = malloc(strlen(buf)); |
|||
For $i = 1 To $iMaxColumn |
|||
strncpy(lb, buf, strlen(buf)); |
|||
$sAlign &= '0' |
|||
cur->wordlist = split(lb, '$', &(cur->longest)); |
|||
Next |
|||
cur->next = malloc(sizeof(line_t)); |
|||
EndIf |
|||
memset(cur->next, 0, sizeof(line_t)); |
|||
Global $aAlignment = StringSplit($sAlign, '', 2) |
|||
cur = cur->next; |
|||
} |
|||
cur->next = NULL; /* last node is a end-marker */ |
|||
; == output all to console |
|||
/* each line holds the longest word length; find the |
|||
Global $sLineOut |
|||
longest among all lines; this determines the width |
|||
For $i = 0 To UBound($aFields) -1 |
|||
of all columns */ |
|||
$sLineOut = '' |
|||
reallongest = head->longest; |
|||
For $j = 0 To $iMaxColumn -1 |
|||
cur = head; |
|||
If $aFields[$i][$j][0] = '' Then ContinueLoop |
|||
while( cur->next != NULL ) { |
|||
$sLineOut &= _GetAligned($aFields[$i][$j][0], $aFields[$i][$j][1], $aAlignment[$j], $aColLen[$j]) |
|||
if ( cur->longest > reallongest ) |
|||
Next |
|||
reallongest = cur->longest; |
|||
ConsoleWrite(StringTrimRight($sLineOut, 1) & @LF) |
|||
cur = cur->next; |
|||
Next |
|||
} |
|||
Func _GetAligned($_sString, $_iLen, $_iAlign, $_iMaxLen) |
|||
reallongest++; |
|||
Local $sSpace = '' |
|||
buf[reallongest] = 0; /* no bounds check... */ |
|||
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 |
|||
</syntaxhighlight> |
|||
Example output in Alignment: left - center - right - left - center - right - left - center - right - left - center - right |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|AWK}}== |
|||
/* print the columns */ |
|||
<syntaxhighlight lang="awk"> |
|||
cur = head; |
|||
# syntax: GAWK -f ALIGN_COLUMNS.AWK ALIGN_COLUMNS.TXT |
|||
while( cur->next != NULL ) { |
|||
BEGIN { |
|||
for(i=0; cur->wordlist[i] != NULL; i++) { |
|||
colsep = " " # separator between columns |
|||
len = strlen(cur->wordlist[i]); |
|||
report("raw data") |
|||
switch(alignment) { |
|||
} |
|||
case LEFT_ALIGNED: |
|||
{ printf("%s\n",$0) |
|||
ipos = 0; |
|||
arr[NR] = $0 |
|||
break; |
|||
n = split($0,tmp_arr,"$") |
|||
for (j=1; j<=n; j++) { |
|||
ipos = reallongest - len; |
|||
width = max(width,length(tmp_arr[j])) |
|||
break; |
|||
} |
|||
case CENTER_ALIGNED: |
|||
} |
|||
ipos = (reallongest - len)/2; |
|||
END { |
|||
break; |
|||
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") |
|||
memset(buf, FILLCHAR, reallongest); |
|||
memcpy(buf+ipos, cur->wordlist[i], len); |
|||
printf("%s ", buf); |
|||
} |
} |
||
} |
|||
printf("\n"); |
|||
function max(x,y) { return((x > y) ? x : y) } |
|||
cur = cur->next; |
|||
</syntaxhighlight> |
|||
} |
|||
<p>Output:</p> |
|||
}</lang> |
|||
<pre> |
|||
report: raw 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. |
|||
report: left justified |
|||
=={{header|C++}}== |
|||
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. |
|||
report: right justified |
|||
The following code fragments are all in one source file for this example (and in this order), but broken up here for clarity. |
|||
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. |
|||
report: center justified |
|||
A reusable template function that handles the tokenizing, and is independent of any work that might wish to be done with the results: |
|||
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. |
|||
</pre> |
|||
=={{header|BaCon}}== |
|||
<lang cpp>#include <vector> |
|||
<syntaxhighlight lang="freebasic"> |
|||
#include <string> // for getline etc. |
|||
DECLARE in$[] = { "Given$a$text$file$of$many$lines,$where$fields$within$a$line$", \ |
|||
#include <iostream> |
|||
"are$delineated$by$a$single$'dollar'$character,$write$a$program", \ |
|||
#include <sstream> // for istringstream |
|||
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$", \ |
|||
#include <algorithm> // for max |
|||
"column$are$separated$by$at$least$one$space.", \ |
|||
#include <iomanip> // for setw |
|||
"Further,$allow$for$each$word$in$a$column$to$be$either$left$", \ |
|||
#include <fstream> // for ofstream |
|||
"justified,$right$justified,$or$center$justified$within$its$column." } |
|||
OPTION DELIM "$" |
|||
using namespace std; |
|||
CONST items = 6 |
|||
template< typename C > |
|||
void enumerateFields( const string& strInput, char chDelim, C callback ) |
|||
{ |
|||
istringstream issFile( strInput ); |
|||
string strLine; |
|||
string strField; |
|||
size_t nColIndex; |
|||
SUB Print_In_Columns(style) |
|||
while ( getline( issFile, strLine ) ) |
|||
{ |
|||
istringstream issLine( strLine ); |
|||
nColIndex = 0; |
|||
' Find widest column |
|||
while ( getline( issLine, strField, chDelim ) ) |
|||
FOR y = 0 TO items-1 |
|||
FOR x = 1 TO AMOUNT(in$[y]) |
|||
IF LEN(TOKEN$(in$[y], x)) > max THEN max = LEN(TOKEN$(in$[y], x)) |
|||
NEXT |
|||
NEXT |
|||
' Print aligned |
|||
nColIndex++; |
|||
FOR y = 0 TO items-1 |
|||
FOR x = 1 TO AMOUNT(in$[y]) |
|||
} |
|||
PRINT ALIGN$(TOKEN$(in$[y], x), max+1, style); |
|||
}</lang> |
|||
NEXT |
|||
PRINT |
|||
NEXT |
|||
PRINT |
|||
END SUB |
|||
A function object that fills an array with column widths: |
|||
Print_In_Columns(0) |
|||
<lang cpp>typedef vector< size_t > ColWidths; |
|||
Print_In_Columns(1) |
|||
Print_In_Columns(2) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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 |
|||
struct MaxColWidthsDeterminer |
|||
are delineated by a single 'dollar' character, write a program |
|||
{ |
|||
that aligns each column of fields by ensuring that words in each |
|||
explicit MaxColWidthsDeterminer( ColWidths& colWidths ) |
|||
column are separated by at least one space. |
|||
: m_colWidths( colWidths ) {} |
|||
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 |
|||
void operator()( size_t nColIndex, const string& strField ); |
|||
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. |
|||
</pre> |
|||
ColWidths& m_colWidths; |
|||
}; |
|||
=={{header|BASIC}}== |
|||
void MaxColWidthsDeterminer::operator()( size_t nColIndex, |
|||
const string& strField ) |
|||
{ |
|||
size_t nWidth = strField.length(); |
|||
==={{header|BBC BASIC}}=== |
|||
if ( nColIndex >= m_colWidths.size() ) |
|||
{{works with|BBC BASIC for Windows}} |
|||
m_colWidths.push_back( nWidth ); |
|||
<syntaxhighlight lang="bbcbasic"> DATA 6 |
|||
else |
|||
DATA "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" |
|||
m_colWidths[ nColIndex ] = max( m_colWidths[ nColIndex ], nWidth ); |
|||
DATA "are$delineated$by$a$single$'dollar'$character,$write$a$program" |
|||
}</lang> |
|||
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$</syntaxhighlight> |
|||
==={{header|Commodore BASIC}}=== |
|||
<syntaxhighlight lang="basic">10 rem ******************************** |
|||
20 rem print words in columns |
|||
30 rem commodore basic 2.0 |
|||
40 rem ******************************** |
|||
50 print chr$(14) : rem change to upper/lower case set |
|||
60 gosub 140 : rem find length of longest word |
|||
70 algn$ = "left" |
|||
80 gosub 260 : rem print aligned text |
|||
90 algn$ = "center" |
|||
100 gosub 260 |
|||
110 algn$ = "right" |
|||
120 gosub 260 |
|||
130 end |
|||
140 rem *** find length of longest word |
|||
150 mx=0 |
|||
160 for i=1 to 6 |
|||
170 read a$ |
|||
180 n=1 |
|||
190 for j=1 to len(a$) |
|||
200 if mid$(a$,j,1)<>"$" then n=n+1: goto 230 |
|||
210 if mx<n then mx=n |
|||
220 n=1 |
|||
230 next |
|||
240 next |
|||
250 return |
|||
260 rem print aligned text |
|||
270 restore : rem reset data read pointer |
|||
280 s$ = " " |
|||
290 print : print algn$;"-aligned" |
|||
300 c=1 : rem column counter |
|||
310 for i=1 to 6 |
|||
320 read a$ |
|||
330 n=1 |
|||
340 for j=1 to len(a$) |
|||
350 if mid$(a$,j,1)<>"$" then n=n+1 : goto 380 |
|||
360 gosub 440 : rem print word |
|||
370 n=1 |
|||
380 next |
|||
390 if n>1 then gosub 440 |
|||
400 next |
|||
410 print |
|||
420 return |
|||
430 rem ********* print word ********** |
|||
440 b$ = mid$(a$,j-n+1,n-1) |
|||
450 b = len(b$) |
|||
460 if algn$ = "center" then 520 |
|||
470 if algn$ = "right" then 570 |
|||
480 if c+b<40 and c+mx>40 then print b$: c=1: return |
|||
490 if c+mx>40 then print : c=1 |
|||
500 print b$;left$(s$,mx-b);: c=c+mx |
|||
510 return |
|||
520 if c+mx>40 then print : c=1 |
|||
530 bb=(mx-b)/2 : ba=bb |
|||
540 if bb>1 and int(bb)=bb then ba=bb-1 |
|||
550 print left$(s$,ba);b$;left$(s$,bb);: c=c+mx |
|||
560 return |
|||
570 if c+mx>40 then print : c=1 |
|||
580 print left$(s$,mx-b);b$;: c=c+mx |
|||
590 return |
|||
600 rem *********** the words ********* |
|||
610 data "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" |
|||
620 data "are$delineated$by$a$single$'dollar'$character,$write$a$program" |
|||
630 data "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" |
|||
640 data "column$are$separated$by$at$least$one$space." |
|||
650 data "Further,$allow$for$each$word$in$a$column$to$be$either$left$" |
|||
660 data "justified,$right$justified,$or$center$justified$within$its$column"</syntaxhighlight> |
|||
=={{header|Batch File}}== |
|||
<syntaxhighlight lang="dos">@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</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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.</pre> |
|||
=={{header|Beads}}== |
|||
<syntaxhighlight lang="beads">beads 1 program 'Align columns' |
|||
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.''' |
|||
var |
|||
words : array^2 of str |
|||
widths : array of num |
|||
calc div_line |
|||
var s = '+' |
|||
loop across:widths val:w |
|||
s = s & str_repeat('-',w) & '+' |
|||
log s |
|||
calc show_table( |
|||
justify |
|||
) |
|||
loop across:words index:i |
|||
var s = '|' |
|||
loop across:widths index:j val:w |
|||
var |
|||
word = words[i,j] |
|||
if word == U |
|||
word = '' |
|||
case justify |
|||
| RIGHT |
|||
s = s & pad_left(word,w) |
|||
| LEFT |
|||
s = s & pad_right(word,w) |
|||
| CENTER |
|||
w = w - str_len(word) |
|||
s = s & str_repeat(' ',idiv(w,2)) & word & str_repeat(' ',idiv(w,2)+mod(w,2)) |
|||
s = s & '|' |
|||
log s |
|||
div_line |
|||
calc main_init |
|||
var w |
|||
split_lines_words (text, words, delim:'$') |
|||
loop across:words index:i |
|||
loop across:words[i] index:j |
|||
w = str_len(words[i,j]) |
|||
widths[j] = max(w,widths[j]) |
|||
loop across:[LEFT CENTER RIGHT] val:v |
|||
log "\n{v} justified\n" |
|||
div_line |
|||
show_table(v)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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.| | | | |
|||
+----------+----------+----------+------+------+---------+----------+--------+-------+-------+------+----+ |
|||
</pre> |
|||
=={{header|BQN}}== |
|||
A function which returns a rectangular 2D array which represents the lines. |
|||
<syntaxhighlight lang="bqn">Split ← (⊢-˜+`׬)∘=⊔⊢ |
|||
PadRow ← { |
|||
w‿t𝕊𝕩: # t → type. |
|||
# 0 → left |
|||
# 1 → right |
|||
# 2 → center |
|||
pstyle←t⊑⟨{0‿𝕩},{𝕩‿0},{⟨⌊𝕩÷2,⌈𝕩÷2⟩}⟩ |
|||
𝕩{(⊣∾𝕨∾⊢)´(Pstyle 𝕩)/¨<w}¨(⌈´-⊢)≠¨𝕩 |
|||
} |
|||
Align ← {{𝕨∾' '∾𝕩}´˘⍉" "‿𝕨⊸PadRow˘⍉>⟨""⟩‿0 PadRow '$' Split¨(@+10) Split 𝕩} |
|||
1 Align text</syntaxhighlight> |
|||
<syntaxhighlight lang="bqn">┌─ |
|||
╵" 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. " |
|||
┘</syntaxhighlight> |
|||
[https://mlochbaum.github.io/BQN/try.html#code=dGV4dOKGkCJHaXZlbiRhJHRleHQkZmlsZSRvZiRtYW55JGxpbmVzLCR3aGVyZSRmaWVsZHMkd2l0aGluJGEkbGluZSQKYXJlJGRlbGluZWF0ZWQkYnkkYSRzaW5nbGUkJ2RvbGxhcickY2hhcmFjdGVyLCR3cml0ZSRhJHByb2dyYW0KdGhhdCRhbGlnbnMkZWFjaCRjb2x1bW4kb2YkZmllbGRzJGJ5JGVuc3VyaW5nJHRoYXQkd29yZHMkaW4kZWFjaCQKY29sdW1uJGFyZSRzZXBhcmF0ZWQkYnkkYXQkbGVhc3Qkb25lJHNwYWNlLgpGdXJ0aGVyLCRhbGxvdyRmb3IkZWFjaCR3b3JkJGluJGEkY29sdW1uJHRvJGJlJGVpdGhlciRsZWZ0JApqdXN0aWZpZWQsJHJpZ2h0JGp1c3RpZmllZCwkb3IkY2VudGVyJGp1c3RpZmllZCR3aXRoaW4kaXRzJGNvbHVtbi4iCgpTcGxpdCDihpAgKOKKoi3LnCtgw5fCrCniiJg94oqU4oqiClBhZFJvdyDihpAgewogIHfigL908J2VivCdlak6ICMgdCDihpIgdHlwZS4KICAgICAgICAjIDAg4oaSIGxlZnQKICAgICAgICAjIDEg4oaSIHJpZ2h0CiAgICAgICAgIyAyIOKGkiBjZW50ZXIKIHBzdHlsZeKGkHTiipHin6h7MOKAv/Cdlal9LHvwnZWp4oC/MH0se+KfqOKMivCdlanDtzIs4oyI8J2VqcO3MuKfqX3in6kKIPCdlal7KOKKo+KIvvCdlajiiL7iiqIpwrQoUHN0eWxlIPCdlakpL8KoPHd9wqgo4oyIwrQt4oqiKeKJoMKo8J2VqQp9CkFsaWduIOKGkCB7e/CdlajiiL4nICfiiL7wnZWpfcK0y5jijYkiICLigL/wnZWo4oq4UGFkUm93y5jijYk+4p+oIiLin6nigL8wIFBhZFJvdyAnJCcgU3BsaXTCqChAKzEwKSBTcGxpdCDwnZWpfQoKMSBBbGlnbiB0ZXh0CgoK Try It!] |
|||
=={{header|C}}== |
|||
See [[Column Aligner/C]] |
|||
=={{header|C sharp|C#}}== |
|||
===Old version=== |
|||
Uses a delegate, which were added to the language in C# 2, to define left-, right-, or center-justified. |
|||
{{works with|C sharp|C#|2+}} |
|||
A function object that outputs fields formatted in columns: |
|||
<syntaxhighlight lang="csharp">using System; |
|||
<lang cpp>struct FormattedLister |
|||
class ColumnAlignerProgram |
|||
{ |
{ |
||
delegate string Justification(string s, int width); |
|||
enum Alignment { eLeft, eRight, eCenter }; |
|||
static string[] AlignColumns(string[] lines, Justification justification) |
|||
FormattedLister( const ColWidths& colWidths, ostream& os, |
|||
Alignment alignment = eLeft ) |
|||
: m_colWidths( colWidths ), m_os( os ), m_alignment( alignment ), |
|||
m_nPrevColIndex( 0 ) |
|||
{ |
{ |
||
const char Separator = '$'; |
|||
// build input table and calculate columns count |
|||
m_os.setf( ( m_alignment == eRight ) ? ios::right : ios::left, |
|||
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); } |
|||
~FormattedLister() |
|||
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 = { |
|||
m_os.flags( m_savedStreamFlags ); |
|||
"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); |
|||
} |
|||
} |
} |
||
}</syntaxhighlight> |
|||
===Newer version=== |
|||
void operator()( size_t nColIndex, const string& strField ); |
|||
Uses features of newer versions, like LINQ, lambdas and switch expressions. |
|||
{{works with|C sharp|C#|8+}} |
|||
const ColWidths& m_colWidths; |
|||
<syntaxhighlight lang="csharp">using System; |
|||
ostream& m_os; |
|||
using System.Linq; |
|||
Alignment m_alignment; |
|||
size_t m_nPrevColIndex; |
|||
ios::fmtflags m_savedStreamFlags; |
|||
}; |
|||
enum Justification { Left, Center, Right } |
|||
void FormattedLister::operator()( size_t nColIndex, const string& strField ) |
|||
{ |
|||
if ( nColIndex < m_nPrevColIndex ) |
|||
m_os << '\n'; |
|||
public class Program |
|||
if ( m_alignment == eCenter ) |
|||
{ |
|||
static void Main() |
|||
{ |
{ |
||
string text = |
|||
size_t nSpacesBefore = ( m_colWidths[ nColIndex ] - strField.length() ) |
|||
@"Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
|||
/ 2; |
|||
are$delineated$by$a$single$'dollar'$character,$write$a$program |
|||
size_t nSpacesAfter = m_colWidths[ nColIndex ] - strField.length() |
|||
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ |
|||
- nSpacesBefore + 1; |
|||
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."; |
|||
AlignColumns(text, Justification.Left); |
|||
m_os << string( nSpacesBefore, ' ' ) << strField |
|||
Console.WriteLine(); |
|||
AlignColumns(text, Justification.Center); |
|||
Console.WriteLine(); |
|||
AlignColumns(text, Justification.Right); |
|||
} |
} |
||
else |
|||
public static void AlignColumns(string text, Justification justification) => |
|||
AlignColumns(text.Split(Environment.NewLine), justification); |
|||
public static void AlignColumns(string[] lines, Justification justification) => |
|||
AlignColumns(lines.Select(line => line.Split('$')).ToArray(), justification); |
|||
public static void AlignColumns(string[][] table, Justification justification) |
|||
{ |
{ |
||
Console.WriteLine(justification + ":"); |
|||
m_os << setw( static_cast< streamsize >( m_colWidths[ nColIndex ] ) ) |
|||
int columns = table.Max(line => line.Length); |
|||
var columnWidths = |
|||
} |
|||
Enumerable.Range(0, columns) |
|||
.Select(i => table.Max(line => i < line.Length ? line[i].Length : 0) |
|||
).ToArray(); |
|||
foreach (var line in table) { |
|||
Console.WriteLine(string.Join(" ", |
|||
Enumerable.Range(0, line.Length) |
|||
.Select(i => justification switch { |
|||
Justification.Left => line[i].PadRight(columnWidths[i]), |
|||
Justification.Right => line[i].PadLeft(columnWidths[i]), |
|||
_ => line[i].PadLeft(columnWidths[i] / 2).PadRight(columnWidths[i]) |
|||
}) |
|||
)); |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
m_nPrevColIndex = nColIndex; |
|||
{{out}} |
|||
}</lang> |
|||
<pre style="height:30ex;overflow:scroll"> |
|||
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: |
|||
The test program, that makes a pass through the data to determine the column widths, and then three more for outputting in each of the three column alignments: |
|||
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: |
|||
<lang cpp>int main() |
|||
Given a text file of many lines, where fields within a line |
|||
{ |
|||
are delineated by a single 'dollar' character, write a program |
|||
const string strInput( |
|||
that aligns each column of fields by ensuring that words in each |
|||
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$\n" |
|||
column are separated by at least one space. |
|||
"are$delineated$by$a$single$'dollar'$character,$write$a$program\n" |
|||
Further, allow for each word in a column to be either left |
|||
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$\n" |
|||
justified, right justified, or center justified within its column.</pre> |
|||
"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." ); |
|||
=={{header|C++}}== |
|||
const char chDelim = '$'; |
|||
See [[Column Aligner/C++]] |
|||
=={{header|Clojure}}== |
|||
ColWidths colWidths; |
|||
<syntaxhighlight lang="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$ |
|||
enumerateFields( strInput, chDelim, MaxColWidthsDeterminer( colWidths ) ); |
|||
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))) |
|||
ofstream outFile( "ColumnAligner.txt" ); |
|||
if ( outFile ) |
|||
{ |
|||
enumerateFields( strInput, chDelim, |
|||
FormattedLister( colWidths, outFile ) ); |
|||
outFile << '\n'; |
|||
(defn col-width [n table] (reduce max (map #(try (count (nth % n)) |
|||
enumerateFields( strInput, chDelim, |
|||
(catch Exception _ 0)) |
|||
table))) |
|||
(defn spaces [n] (str/repeat n " ")) |
|||
outFile << '\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 |
|||
enumerateFields( strInput, chDelim, |
|||
"get the width of each column, then generate a new table with propper padding for eath item" |
|||
FormattedLister( colWidths, outFile, |
|||
([table justification] |
|||
FormattedLister::eCenter ) ); |
|||
(let [col-widths (map #(+ 2 (col-width % table)) (range (count(first table))))] |
|||
outFile << endl; |
|||
(map |
|||
(fn [row] (map #(add-padding %1 %2 justification) row col-widths)) |
|||
}</lang> |
|||
table)))) |
|||
(defn print-table |
|||
[table] |
|||
(do (println) |
|||
(print (str/join "" (flatten (interleave table (repeat "\n"))))))) |
|||
(print-table (aligned-table table :center)) |
|||
</syntaxhighlight> |
|||
=={{header|COBOL}}== |
|||
<syntaxhighlight lang="cobol"> |
|||
identification division. |
|||
program-id. AlignColumns. |
|||
data division. |
|||
working-storage section. |
|||
*>-> Constants |
|||
78 MAX-LINES value 6. |
|||
78 MAX-LINE-SIZE value 66. |
|||
78 MAX-COLUMNS value 12. |
|||
78 MAX-COLUMN-SIZE value 16. |
|||
*>-> Indexes |
|||
01 w-idx pic is 9(2). |
|||
01 w-idy pic is 9(2). |
|||
01 w-pos pic is 9(3). |
|||
*>-> Data structures |
|||
01 w-lines. |
|||
05 w-line pic is x(MAX-LINE-SIZE) occurs MAX-LINES. |
|||
01 w-column-sizes. |
|||
05 w-column-size pic is 99 occurs MAX-COLUMNS value zeros. |
|||
01 w-matrix. |
|||
05 filler occurs MAX-LINES. |
|||
10 filler occurs MAX-COLUMNS. |
|||
15 w-content pic is x(MAX-COLUMN-SIZE). |
|||
*>-> Output |
|||
01 w-line-out pic is x(120). |
|||
*>-> Data alignment |
|||
01 w-alignment pic is x(1). |
|||
88 alignment-left value is "L". |
|||
88 alignment-center value is "C". |
|||
88 alignment-right value is "R". |
|||
procedure division. |
|||
main. |
|||
move "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" to w-line(1) |
|||
move "are$delineated$by$a$single$'dollar'$character,$write$a$program" to w-line(2) |
|||
move "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" to w-line(3) |
|||
move "column$are$separated$by$at$least$one$space." to w-line(4) |
|||
move "Further,$allow$for$each$word$in$a$column$to$be$either$left$" to w-line(5) |
|||
move "justified,$right$justified,$or$center$justified$within$its$column." to w-line(6) |
|||
perform calculate-size-columns |
|||
set alignment-left to true |
|||
perform show-content |
|||
set alignment-center to true |
|||
perform show-content |
|||
set alignment-right to true |
|||
perform show-content |
|||
goback |
|||
. |
|||
calculate-size-columns. |
|||
perform |
|||
varying w-idx from 1 by 1 |
|||
until w-idx > MAX-LINES |
|||
unstring w-line(w-idx) delimited by "$" into w-content(w-idx, 1), w-content(w-idx, 2), |
|||
w-content(w-idx, 3), w-content(w-idx, 4), w-content(w-idx, 5), w-content(w-idx, 6), |
|||
w-content(w-idx, 7), w-content(w-idx, 8), w-content(w-idx, 9), w-content(w-idx, 10), |
|||
w-content(w-idx, 11), w-content(w-idx, 12), |
|||
perform |
|||
varying w-idy from 1 by 1 |
|||
until w-idy > MAX-COLUMNS |
|||
if function stored-char-length(w-content(w-idx, w-idy)) > w-column-size(w-idy) |
|||
move function stored-char-length(w-content(w-idx, w-idy)) to w-column-size(w-idy) |
|||
end-if |
|||
end-perform |
|||
end-perform |
|||
. |
|||
show-content. |
|||
move all "-" to w-line-out |
|||
display w-line-out |
|||
perform |
|||
varying w-idx from 1 by 1 |
|||
until w-idx > MAX-LINES |
|||
move spaces to w-line-out |
|||
move 1 to w-pos |
|||
perform |
|||
varying w-idy from 1 by 1 |
|||
until w-idy > MAX-COLUMNS |
|||
call "C$JUSTIFY" using w-content(w-idx, w-idy)(1:w-column-size(w-idy)), w-alignment |
|||
move w-content(w-idx, w-idy) to w-line-out(w-pos:w-column-size(w-idy)) |
|||
compute w-pos = w-pos + w-column-size(w-idy) + 1 |
|||
end-perform |
|||
display w-line-out |
|||
end-perform |
|||
. |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<syntaxhighlight lang="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. |
|||
------------------------------------------------------------------------------------------------------------------------ |
|||
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. |
|||
</syntaxhighlight> |
|||
=={{header|CoffeeScript}}== |
|||
<syntaxhighlight lang="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 |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<syntaxhighlight lang="text"> |
|||
> 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. |
|||
</syntaxhighlight> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
< |
<syntaxhighlight lang="lisp">(defun nonempty (seq) |
||
(position-if (lambda (x) (declare (ignore x)) t) seq)) |
(position-if (lambda (x) (declare (ignore x)) t) seq)) |
||
(defun split (delim seq) |
(defun split (delim seq) |
||
"Splits seq on delim into a list of subsequences. Trailing empty |
"Splits seq on delim into a list of subsequences. Trailing empty |
||
subsequences are removed." |
subsequences are removed." |
||
(labels |
(labels |
||
((f (seq &aux (pos (position delim seq))) |
((f (seq &aux (pos (position delim seq))) |
||
(if pos |
|||
(cons |
(cons |
||
(subseq seq 0 pos) |
(subseq seq 0 pos) |
||
(f (subseq seq (1+ pos)))) |
(f (subseq seq (1+ pos)))) |
||
(list seq)))) |
|||
(let* |
(let* ((list (f seq)) |
||
((list |
(end (position-if #'nonempty list :from-end t))) |
||
(end (position-if #'nonempty list :from-end t))) |
|||
(subseq list 0 (1+ end))))) |
(subseq list 0 (1+ end))))) |
||
(defun lengthen (list minlen filler-elem &aux (len (length list))) |
(defun lengthen (list minlen filler-elem &aux (len (length list))) |
||
"Destructively pads list with filler-elem up to minlen." |
"Destructively pads list with filler-elem up to minlen." |
||
(if (< len minlen) |
(if (< len minlen) |
||
(nconc list (make-list |
(nconc list (make-list (- minlen len) :initial-element filler-elem)) |
||
(- minlen len) :initial-element filler-elem)) |
|||
list)) |
list)) |
||
(defun align-columns (text |
(defun align-columns (text |
||
&key (align :left) |
|||
&aux |
|||
(fmtmod (case align |
|||
(:right ":") |
|||
(: |
(:left "@") |
||
(:right ":") |
|||
(t (error "Invalid alignment.")))) |
|||
(:center "@:") |
|||
(fields (mapcar |
|||
(t (error "Invalid alignment.")))) |
|||
(lambda (line) (split #\$ line)) |
|||
(split #\ |
(fields (mapcar (lambda (line) (split #\$ line)) |
||
(split #\Newline text))) |
|||
(mostcols (loop for l in fields maximize (length l))) |
|||
(mostcols (loop for l in fields |
|||
widest) |
|||
maximize (length l))) |
|||
(setf fields (mapcar |
|||
widest) |
|||
(lambda (l) (lengthen l mostcols "")) |
|||
(setf fields (mapcar (lambda (l) (lengthen l mostcols "")) |
|||
fields)) |
|||
fields)) |
|||
(setf widest (loop |
|||
for col below (length (first fields)) |
(setf widest (loop for col below (length (first fields)) |
||
collect (loop |
collect (loop for row in fields |
||
maximize (length (elt row col))))) |
|||
(format nil |
(format nil |
||
(with-output-to-string (s) |
(with-output-to-string (s) |
||
(princ "~{~{" s) |
(princ "~{~{" s) |
||
(dolist (w widest) |
(dolist (w widest) |
||
(format s "~~~d~a<~~a~~>" (1+ w) fmtmod)) |
(format s "~~~d~a<~~a~~>" (1+ w) fmtmod)) |
||
(princ "~}~%~}" s)) |
(princ "~}~%~}" s)) |
||
fields))</ |
fields))</syntaxhighlight> |
||
=={{header|D}}== |
=={{header|D}}== |
||
<syntaxhighlight lang="d">void main() { |
|||
<lang d> |
|||
import std.stdio; |
import std.stdio, std.string, std.algorithm, std.range, std.typetuple; |
||
import std.string; |
|||
char[]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."; |
|||
immutable data = |
|||
int main() { |
|||
"Given$a$txt$file$of$many$lines,$where$fields$within$a$line$ |
|||
char[][]lines = text.split("\n"); |
|||
are$delineated$by$a$single$'dollar'$character,$write$a$program |
|||
char[][][]words; |
|||
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ |
|||
int[]maxlens; |
|||
column$are$separated$by$at$least$one$space. |
|||
foreach(line;lines) { |
|||
Further,$allow$for$each$word$in$a$column$to$be$either$left$ |
|||
words ~= line.split("$"); |
|||
justified,$right$justified,$or$center$justified$within$its$column." |
|||
// make sure we have enough slots in maxlens |
|||
.split.map!(r => r.chomp("$").split("$")).array; |
|||
if (words[$-1].length > maxlens.length) { |
|||
maxlens.length = words[$-1].length; |
|||
size_t[size_t] maxWidths; |
|||
} |
|||
foreach (const line; data) |
|||
foreach(i,word;words[$-1]) { |
|||
foreach (immutable i, const word; line) |
|||
maxWidths[i] = max(maxWidths.get(i, 0), word.length); |
|||
} |
|||
foreach (immutable just; TypeTuple!(leftJustify, center, rightJustify)) |
|||
// now that we've done a whole pass and grabbed all the max lengths, start over and pad everything to the right length |
|||
foreach(line; |
foreach (immutable line; data) |
||
writefln("%-(%s %)", line.length.iota |
|||
.map!(i => just(line[i], maxWidths[i], ' '))); |
|||
} |
|||
}</syntaxhighlight> |
|||
// now join all the words back into lines and print them |
|||
{{out}} |
|||
foreach(line;words) { |
|||
<pre>Given a txt file of many lines, where fields within a line |
|||
writefln("%s",line.join(" ")); |
|||
are delineated by a single 'dollar' character, write a program |
|||
} |
|||
that aligns each column of fields by ensuring that words in each |
|||
return 0; |
|||
column are separated by at least one space. |
|||
} |
|||
Further, allow for each word in a column to be either left |
|||
</lang> |
|||
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. </pre> |
|||
=={{header|Delphi}}== |
|||
{{libheader|Delphi StdCtrls, Classes, SysUtils, StrUtils, Contnrs}} |
|||
<syntaxhighlight lang="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; |
|||
</syntaxhighlight> |
|||
=={{header|E}}== |
=={{header|E}}== |
||
<syntaxhighlight lang="e">pragma.enable("accumulator") |
|||
<lang e> |
|||
pragma.enable("accumulator") |
|||
def left(width, word) { |
def left(width, word) { |
||
Line 619: | Line 3,275: | ||
} + "\n" |
} + "\n" |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="e">? def text := "Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
||
are$delineated$by$a$single$'dollar'$character,$write$a$program |
are$delineated$by$a$single$'dollar'$character,$write$a$program |
||
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ |
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ |
||
Line 650: | Line 3,306: | ||
column are separated by at least one space. |
column are separated by at least one space. |
||
Further, allow for each word in a column to be either left |
Further, allow for each word in a column to be either left |
||
justified, right justified, or center justified within its column.</ |
justified, right justified, or center justified within its column.</syntaxhighlight> |
||
=={{header|EasyLang}}== |
|||
{{trans|AWK}} |
|||
<syntaxhighlight lang=text> |
|||
global width inp$[] . |
|||
proc read . . |
|||
repeat |
|||
inp$ = input |
|||
until inp$ = "" |
|||
inp$[] &= inp$ |
|||
ar$[] = strsplit inp$ "$" |
|||
for s$ in ar$[] |
|||
width = higher width len s$ |
|||
. |
|||
. |
|||
. |
|||
read |
|||
# |
|||
proc out mode . . |
|||
for inp$ in inp$[] |
|||
ar$[] = strsplit inp$ "$" |
|||
for s$ in ar$[] |
|||
spc = width - len s$ + 1 |
|||
if mode = 1 |
|||
write s$ |
|||
for i to spc |
|||
write " " |
|||
. |
|||
elif mode = 2 |
|||
for i to spc |
|||
write " " |
|||
. |
|||
write s$ |
|||
elif mode = 3 |
|||
for i to spc div 2 |
|||
write " " |
|||
. |
|||
write s$ |
|||
for i to spc - spc div 2 |
|||
write " " |
|||
. |
|||
. |
|||
. |
|||
print "" |
|||
. |
|||
. |
|||
out 1 |
|||
print "" |
|||
out 2 |
|||
print "" |
|||
out 3 |
|||
# |
|||
input_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. |
|||
</syntaxhighlight> |
|||
=={{header|Elixir}}== |
|||
{{trans|Ruby}} |
|||
{{works with|Elixir|1.3}} |
|||
The String module of Elixir doesn't have the function of the center position adjusting. |
|||
It calls and processes the function of 'Erlang'. |
|||
<syntaxhighlight lang="elixir">defmodule Align do |
|||
def columns(text, alignment) do |
|||
fieldsbyrow = String.split(text, "\n", trim: true) |
|||
|> Enum.map(fn row -> String.split(row, "$", trim: true) end) |
|||
maxfields = Enum.map(fieldsbyrow, fn field -> length(field) end) |> Enum.max |
|||
colwidths = Enum.map(fieldsbyrow, fn field -> field ++ List.duplicate("", maxfields - length(field)) end) |
|||
|> List.zip |
|||
|> Enum.map(fn column -> |
|||
Tuple.to_list(column) |> Enum.map(fn col-> String.length(col) end) |> Enum.max |
|||
end) |
|||
Enum.each(fieldsbyrow, fn row -> |
|||
Enum.zip(row, colwidths) |
|||
|> Enum.map(fn {field, width} -> adjust(field, width, alignment) end) |
|||
|> Enum.join(" ") |> IO.puts |
|||
end) |
|||
end |
|||
defp adjust(field, width, :Left), do: String.pad_trailing(field, width) |
|||
defp adjust(field, width, :Right), do: String.pad_leading(field, width) |
|||
defp adjust(field, width, _), do: :string.centre(String.to_charlist(field), width) |
|||
end |
|||
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. |
|||
""" |
|||
Enum.each([:Left, :Right, :Center], fn alignment -> |
|||
IO.puts "\n# #{alignment} Column-aligned output:" |
|||
Align.columns(text, alignment) |
|||
end)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
# 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. |
|||
</pre> |
|||
=={{header|Erlang}}== |
|||
<syntaxhighlight lang="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]. </syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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 |
|||
</pre> |
|||
=={{header|Euphoria}}== |
|||
<syntaxhighlight lang="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</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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. |
|||
</pre> |
|||
=={{header|F_Sharp|F#}}== |
|||
<syntaxhighlight lang="fsharp">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</syntaxhighlight> |
|||
Output, when called with a file containing the sample input |
|||
<pre>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. |
|||
--------------------------------------------------------------------------------------------------------</pre> |
|||
=={{header|Factor}}== |
|||
<syntaxhighlight lang="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 ;</syntaxhighlight> |
|||
example-text { +left+ +middle+ +right+ } [ print-aligned ] with each |
|||
=={{header|FBSL}}== |
|||
Using a multiline string: |
|||
<syntaxhighlight lang="qbasic">#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</syntaxhighlight> |
|||
{{out}} |
|||
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... |
|||
=={{header|Forth}}== |
|||
{{works with|GNU Forth}} |
|||
<syntaxhighlight lang="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</syntaxhighlight> |
|||
=={{header|Fortran}}== |
|||
For the general situation, a utility has no knowledge of the maximum number of fields in a record nor the maximum length of a record, still less knowledge of the sizes of the fields in the records. Decent file systems (for example, that of the Burroughs 6700) make available the MaxRecordLength of a file when a file is opened, but many systems are less than helpful. It is possible to open a file as UNFORMATTED and then simply read sequences of binary data to be interpreted to taste, but in the ASCII world that means deciding on record markers being CR, CRLF, LF, or LFCR and I have encountered files with mixtures... In any case, a file with a fixed record length will likely not contain any such markers. |
|||
The plan here is to read the file to find out. But, given that the maximum record length ''is'' unknown, reading records into some storage area is problematical. Some systems can create a "string" variable via the read statement that will be of the proper size, but older Fortran works always with storage sizes fixed at compile time. However, after F77 started being extended, a common extension was the Q-element in FORMAT statements, which instead of interpreting the content of a record, reports instead the number of characters yet unread in a record. Thus, a statement like <code>READ(in,"(Q)") L</code> will read a record of input and the first action is to place in variable L the number of characters yet to be processed of that record. Since the content of the record is not being transferred, there is no need for a CHARACTER area of sufficient size to receive all of it. Indeed here, nothing is read. As for the LF/CRLF/LFCR/CR issue, with FORMATTED input the file system makes its decision and presents record content without incorporating such out-of-context data. |
|||
When data are being read into a CHARACTER variable, once the receiver is filled subsequent data in a long record will be ignored, and if the input record was smaller than the variable, trailing spaces will be supplied to fill out the variable. It is for this reason that the read statement is <code>READ (IN,11,END = 20) L,ACARD(1:L)</code> so that, ''on-the-fly'', the length of the record is determined, and then only that number of characters are placed in ACARD with no (possibly large number of) trailing spaces being appended. Naturally, subsequent inspection of ACARD will have to be careful not to look beyond character L, where detritus from previous usage will languish. |
|||
Once the main programme has ascertained the maximum record length, subroutine RAKE can be invoked with this as a parameter. From F90 on, as introduced by Algol in the 1960s, functions and subroutines have been allowed to declare arrays of a size specified by a variable and so the "surely big enough" issue is reduced. Thus, given a maximum length of M, a record containing M field delimiters can represent M + 1 fields, all null. The last field's delimiter is the end-of-record, so one more. It is also possible to use ALLOCATE(...) to request storage of suitable dimension for a variable within a routine, but that introduces verbiage. So, a programme can request just enough storage for its particular tasks and thereby possibly succeed on a problem too large for an always-big-enough storage scheme, but on the other hand, the fixed storage allocation scheme doesn't suddenly run out in the middle of a job. |
|||
Accordingly, a second scan of the records of the text file can be made, with a view to ascertaining the maximum widths for the first, second, etc. columns. This is done by storing in array C the positions of the delimiters in the text, so the content of a field ''i'' on a record will be starting with C(I - 1) + 1, and ending with C(I) - 1, - that is, the first character following a delimiter to the last character before a delimiter. In other words, the delimiter is not a part of the field's content. For convenience in this, C(0) = 0, since the first field is number one, and the last field's delimiter is one past the end of the record. Having an array start with non-default bounds is a feature of F90, similarly the array assignment that tracks the maximum field widths in array W. The specification makes no call for leading or trailing spaces in a field's content to be trimmed; if it did then two sets of fingers would be used to mark the first and last position of each text. Happily, there is also no call to recognise quoted texts, that might contain delimiter characters that are not delimiters. |
|||
Equipped at last with knowledge of each column's maximum width, yet another pass can be made through the file to produce the output. A feature of the format code A''w'' is that text is aligned to the right within the width of ''w''. So, concoct a FORMAT text with suitable A''w'' entries, also augmenting the width by one for each column to meet the requirement that each column's content is separated from the others by at least one space. This concoction is easy enough, and could be improved by taking advantage of the "factoring" that format statements allow so that for example "A7,A7" can be replaced by "2A7", and further, bracketing of sequences is allowed and with repeat counts for them also. Alas, finding the minimum sequence is in general a very difficult problem, so no attempt is made. As for "sufficient storage" for the FORMAT variable, a two-digit width specification seems sufficient so each field's format code would be "A''dd''," - four characters. Only later Fortran allows the I0 format code, meaning that an integer will be written only with sufficient digits, not a fixed "sufficiency" of digits. A pity the code for this isn't just "I" rather than "I0" which implies a width of zero. |
|||
A difficulty now arises in terminating the format text with the closing bracket. This is done by searching for the sequence ", " and replacing the comma by the closing bracket. This is present only because format 21 specifies <MF> as a repeat count. If it were say 666 instead, after the last W value was written the format processing would cycle back to its next repetition, write out an "A", then stop since there is no W value to write via the "I0" format code. Thus, the format text ends ",A" and the INDEX fails to find the desired ", ". It could instead search for ",A " (just ",A" would stop on the second field's format code) but ", " seems clear. The <MF> usage is standard only for recent Fortran. Formatted output opportunities are many and options numerous. Other schemes could be used, such as the write statement specifying the text literals in its items, but that would require an implied-DO output list and it seemed nicer to be able to use the array specification W(1:MF) instead. |
|||
Given a FORMAT text that produces output in aligned columns makes it easy enough to meet the other requirements. To cause texts to be aligned left, append sufficient spaces to each output text, and for centred text, half that number. This relies on the special intrinsic function REPEAT(text,n) returning a varying number of characters - CHARACTER functions have to return a ''fixed'' number of characters, until the standardisation of varying-length strings in F2003 ''et seq''. Earlier Fortrans lack the REPEAT function, but its effect can be gained via something like CHARACTER*66 SPACE, where SPACE is set to spaces, and SPACE(1:N) is used where REPEAT(" ",N) is desired. And if messing with variable FORMAT is unwanted, the REPEAT scheme can be used for the right-justified output also. |
|||
<syntaxhighlight lang="fortran"> |
|||
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. |
|||
</syntaxhighlight> |
|||
Every line of output starts with a space, and if it were to be sent to a lineprinter, this would be used as the carriage control character (meaning, advance one line then print the rest) - the first column does not need to be set off by one space from the previous column, but rather than devise special treatment it is spaced off anyway. The free-format output statements also start with a space. Output: |
|||
<pre> |
|||
6 Recs, longest rec. length is 66 |
|||
Align Left |
|||
Format(A11,A11,A11,A7,A7,A10,A11,A9,A8,A8,A7,A5,A1) |
|||
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 |
|||
Format(A11,A11,A11,A7,A7,A10,A11,A9,A8,A8,A7,A5,A1) |
|||
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 |
|||
Format(A11,A11,A11,A7,A7,A10,A11,A9,A8,A8,A7,A5,A1) |
|||
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. |
|||
</pre> |
|||
=={{header|FreeBASIC}}== |
|||
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64 |
|||
Sub Split(s As String, sep As String, result() As String) |
|||
Dim As Integer i, j, count = 0 |
|||
Dim temp As String |
|||
Dim As Integer position(Len(s) + 1) |
|||
position(0) = 0 |
|||
For i = 0 To Len(s) - 1 |
|||
For j = 0 To Len(sep) - 1 |
|||
If s[i] = sep[j] Then |
|||
count += 1 |
|||
position(count) = i + 1 |
|||
End If |
|||
Next j |
|||
Next i |
|||
position(count + 1) = Len(s) + 1 |
|||
Redim result(count) |
|||
For i = 1 To count + 1 |
|||
result(i - 1) = Mid(s, position(i - 1) + 1, position(i) - position(i - 1) - 1) |
|||
Next |
|||
End Sub |
|||
Sub CSet(buffer As String, s As Const String) |
|||
Dim As Integer bLength = Len(buffer) |
|||
Dim As Integer sLength = Len(s) |
|||
Dim As Integer diff, lSpaces |
|||
If sLength >= bLength Then |
|||
LSet buffer, s |
|||
Else |
|||
diff = bLength - sLength |
|||
lSpaces = diff \ 2 |
|||
LSet buffer, Space(lSpaces) + s |
|||
End If |
|||
End Sub |
|||
Dim lines() As String |
|||
Dim count As Integer = 0 |
|||
Open "align_columns.txt" For Input As #1 |
|||
While Not Eof(1) |
|||
Redim Preserve lines(count) |
|||
Line Input #1, lines(count) |
|||
count +=1 |
|||
Wend |
|||
Close #1 |
|||
Dim As Integer i,j, length, numColumns = 0 |
|||
Dim As Integer numLines = UBound(lines) + 1 |
|||
Dim fields() As String |
|||
' Work out the maximum number of columns |
|||
For i = 0 To numLines - 1 |
|||
Erase fields |
|||
Split RTrim(lines(i), "$"), "$", fields() |
|||
length = UBound(fields) + 1 |
|||
If length > numColumns Then numColumns = length |
|||
Next |
|||
' Split lines into fields and work out maximum size of each column |
|||
Dim matrix(numLines - 1, numColumns - 1) As String |
|||
Dim columnSizes(numColumns - 1) As Integer |
|||
For i = 0 To numLines - 1 |
|||
Erase fields |
|||
Split RTrim(lines(i), "$"), "$", fields() |
|||
For j = 0 To UBound(fields) |
|||
matrix(i, j) = fields(j) |
|||
length = Len(fields(j)) |
|||
If length > columnSizes(j) Then columnSizes(j) = length |
|||
Next j |
|||
Next i |
|||
Dim buffer As String |
|||
'Separate each column by 2 spaces |
|||
Open "align_left_columns.txt" For Output As #1 |
|||
Open "align_right_columns.txt" For Output As #2 |
|||
Open "align_center_columns.txt" For Output As #3 |
|||
For i = 0 To UBound(matrix, 1) |
|||
For j = 0 To UBound(matrix, 2) |
|||
buffer = Space(columnSizes(j)) |
|||
LSet buffer, matrix(i, j) |
|||
Print #1, buffer; |
|||
RSet buffer, matrix(i, j) |
|||
Print #2, buffer; |
|||
CSet buffer, matrix(i, j) |
|||
Print #3, buffer; |
|||
If j < UBound(matrix, 2) Then |
|||
Print #1, " "; : Print #2, " "; : Print #3, " "; |
|||
End If |
|||
Next j |
|||
Print #1, : Print #2, : Print #3, |
|||
Next i |
|||
Close #1 : Close #2 : Close #3</syntaxhighlight> |
|||
{{out}} |
|||
<pre>--- align_columns.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_left_columns.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_right_columns.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_center_columns.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. |
|||
</pre> |
|||
=={{header|FutureBasic}}== |
|||
Note: FB's NSLog, used for demonstrations, does not have a center alignment provision. However FB allows advanced alignment and text formatting in normal application development. Simple right and left alignment are shown here. |
|||
<syntaxhighlight lang="futurebasic"> |
|||
include "NSLog.incl" |
|||
local fn AlignColumn |
|||
NSUInteger i |
|||
CFStringRef testStr = @"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." |
|||
CFArrayRef temp = fn StringComponentsSeparatedByString( testStr, @"$" ) |
|||
CFMutableArrayRef arr = fn MutableArrayWithArray( temp ) |
|||
NSUInteger count = fn ArrayCount( arr ) |
|||
ptr a(50) |
|||
NSLog( @"\nLeft aligned:\n" ) |
|||
NSUInteger lineCheck = 1 |
|||
for i = 0 to count -1 |
|||
a( lineCheck ) = (ptr)fn StringUTF8String( arr[i] ) |
|||
if ( lineCheck == 9 ) |
|||
NSLog( @"%-12s %-11s %-12s %-11s %-12s %-12s %-12s %-12s %-12s", a(1),a(2),a(3),a(4),a(5),a(6),a(7),a(8),a(9) ) |
|||
lineCheck = 1 |
|||
else |
|||
lineCheck++ |
|||
end if |
|||
next |
|||
NSLog( @"\n\nRight aligned:\n" ) |
|||
lineCheck = 1 |
|||
for i = 0 to count -1 |
|||
a( lineCheck ) = (ptr)fn StringUTF8String( arr[i] ) |
|||
if ( lineCheck == 9 ) |
|||
NSLog( @"%12s %11s %12s %11s %12s %12s %12s %12s %12s", a(1),a(2),a(3),a(4),a(5),a(6),a(7),a(8),a(9) ) |
|||
lineCheck = 1 |
|||
else |
|||
lineCheck++ |
|||
end if |
|||
next |
|||
end fn |
|||
fn AlignColumn |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{output}} |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|Gambas}}== |
|||
'''[https://gambas-playground.proko.eu/?gist=023b4c5144d45e047abe02ebf5c4525a Click this link to run this code]''' |
|||
<syntaxhighlight lang="gambas">Public Sub Main() 'Written in Gambas 3.9.2 as a Command line Application - 15/03/2017 |
|||
Dim siCount, siCounter, siLength As Short 'Counters |
|||
Dim siLongest As Short = -1 'To store the longest 'Word' |
|||
Dim sLine, sRows As New String[] 'Arrays |
|||
Dim sTemp, sAlign As String 'Temp strings |
|||
Dim sInput As String = "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." 'Main string (with End Of Line characters added) |
|||
For Each sTemp In Split(sInput, "\n") 'For each Line (split by End of Line character).. |
|||
sLine.add(sTemp) 'Add the Line to sLine array |
|||
Next |
|||
For siCount = 0 To sLine.Max 'For each of Lines in the array.. |
|||
For Each sTemp In Split(sLine[siCount], "$") 'For each 'Word' in the Line (Split by the '$') |
|||
siLength = Len(sTemp) 'Store the length of the current 'Word' |
|||
If siLength > siLongest Then siLongest = siLength 'Make sure siLength has the length of the longest 'Word' |
|||
sRows.add(Trim(sTemp)) 'Create an array of the 'Words' |
|||
Next |
|||
sRows.add("\n") 'Add a End Of Line character to the sRows array |
|||
Next |
|||
For siCounter = 0 To 2 'For each alignment (Left, Right and Centre) |
|||
For Each sTemp In sRows 'For each 'Word' in the sRows array.. |
|||
If sTemp = "\n" Then 'If it's a End Of Line character then.. |
|||
Print 'Print |
|||
Continue 'Jump to the next iteration of the For Next Loop |
|||
Endif |
|||
If siCounter = 0 Then Print sTemp & Space(siLongest - Len(sTemp)); 'Print control for Left align |
|||
If siCounter = 1 Then Print Space(siLongest - Len(sTemp)) & sTemp; 'Print control for Right align |
|||
If siCounter = 2 Then 'Print control for Centre align |
|||
siCount = (siLongest - Len(sTemp)) / 2 'Difference between the length of the longest 'Word' and the current 'Word' / 2 |
|||
sAlign = Space(siCount) & sTemp & Space(siCount) 'Put the string together for printing |
|||
If Len(sAlign) < siLongest Then sAlign &= " " 'Check it's the correct length if not add a space on the end |
|||
Print sAlign; 'Print the 'Word' |
|||
Endif |
|||
Next |
|||
Print 'Print an empty line between each alignment list |
|||
Next |
|||
End</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|Go}}== |
|||
<syntaxhighlight lang="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) |
|||
}</syntaxhighlight> |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|Groovy}}== |
=={{header|Groovy}}== |
||
Solution: |
Solution: |
||
< |
<syntaxhighlight lang="groovy">def alignColumns = { align, rawText -> |
||
def lines = rawText.tokenize('\n') |
def lines = rawText.tokenize('\n') |
||
def words = lines.collect { it.tokenize(/\$/) } |
def words = lines.collect { it.tokenize(/\$/) } |
||
Line 667: | Line 4,345: | ||
words.each { padAll(justify[align], columnWidths, it).each { print it }; println() } |
words.each { padAll(justify[align], columnWidths, it).each { print it }; println() } |
||
}</ |
}</syntaxhighlight> |
||
Test Program: |
Test Program: |
||
< |
<syntaxhighlight lang="groovy">def rawTextInput = '''Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
||
are$delineated$by$a$single$'dollar'$character,$write$a$program |
are$delineated$by$a$single$'dollar'$character,$write$a$program |
||
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ |
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ |
||
Line 681: | Line 4,359: | ||
alignColumns(align, rawTextInput) |
alignColumns(align, rawTextInput) |
||
println() |
println() |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre style="height:25ex;overflow:scroll">Left Justified: |
<pre style="height:25ex;overflow:scroll">Left Justified: |
||
Given a text file of many lines, where fields within a line |
Given a text file of many lines, where fields within a line |
||
Line 707: | Line 4,385: | ||
Further, allow for each word in a column to be either left |
Further, allow for each word in a column to be either left |
||
justified, right justified, or center justified within its column.</pre> |
justified, right justified, or center justified within its column.</pre> |
||
=={{header|Harbour}}== |
|||
<syntaxhighlight lang="visualfoxpro"> |
|||
PROCEDURE Main() |
|||
LOCAL a := { "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." } |
|||
LOCAL e, nMax |
|||
// remove trailing dollars |
|||
AEval( a, {|e,n| Iif( Right(e,1)=="$", a[n] := hb_StrShrink( e, 1 ), NIL ) } ) |
|||
// find max word length |
|||
nMax := 0 |
|||
AEval( a, {|e| AEval( hb_Atokens( e, "$"), {|i| nMax := Max( nMax, Len(i) )} ) } ) |
|||
nMax++ |
|||
// start printing, padding words as needed |
|||
? |
|||
? "----Left aligned columns----" |
|||
FOR EACH e IN a |
|||
? |
|||
AEval( hb_Atokens( e, "$"), {|i| QQout( PadR(i, nMax) )} ) |
|||
NEXT |
|||
? |
|||
? "----Center aligned columns----" |
|||
FOR EACH e IN a |
|||
? |
|||
AEval( hb_Atokens( e, "$"), {|i| QQout( PadC(i, nMax) )} ) |
|||
NEXT |
|||
? |
|||
? "----Right aligned columns----" |
|||
FOR EACH e IN a |
|||
? |
|||
AEval( hb_Atokens( e, "$"), {|i| QQout( PadL(i, nMax) )} ) |
|||
NEXT |
|||
RETURN |
|||
</syntaxhighlight> |
|||
Output: |
|||
<syntaxhighlight lang="text">----Left aligned columns---- |
|||
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 columns---- |
|||
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 columns---- |
|||
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.</syntaxhighlight> |
|||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
<syntaxhighlight lang="haskell">import Data.List (unfoldr, transpose) |
|||
<lang haskell> |
|||
import |
import Control.Arrow (second) |
||
import Control.Monad |
|||
import Control.Arrow |
|||
dat = |
|||
dat = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$\n" ++ |
|||
"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" ++ |
|||
"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 = |
|||
brkdwn = unfoldr (\xs -> if null xs then Nothing else Just (second (drop 1) (span ('$'/=) xs)) ) |
|||
takeWhile (not . null) . unfoldr (Just . second (drop 1) . span ('$' /=)) |
|||
spas = repeat ' ' |
|||
format j ls = map ( |
format j ls = map (unwords . zipWith align colw) rows |
||
where |
where |
||
rows = map brkdwn $ lines ls |
rows = map brkdwn $ lines ls |
||
colw = map (maximum. map length) . transpose $ rows |
colw = map (maximum . map length) . transpose $ rows |
||
align cw w = |
align cw w = |
||
case j of |
case j of |
||
'c' -> |
'c' -> replicate l ' ' ++ w ++ replicate r ' ' |
||
'r' -> |
'r' -> replicate dl ' ' ++ w |
||
'l' -> w ++ |
'l' -> w ++ replicate dl ' ' |
||
where |
|||
dl = cw - length w |
|||
(l, r) = (dl `div` 2, dl - l)</syntaxhighlight> |
|||
{{out}} |
|||
(l,r) |
|||
| odd dl = (hdl,hdl+1) |
|||
| otherwise = (hdl,hdl) |
|||
</lang> |
|||
output example: |
|||
<pre> |
<pre> |
||
*Main> mapM_ putStrLn $ format 'c' dat |
*Main> mapM_ putStrLn $ format 'c' dat |
||
Line 747: | Line 4,490: | ||
column are separated by at least one space. |
column are separated by at least one space. |
||
Further, allow for each word in a column to be either left |
Further, allow for each word in a column to be either left |
||
justified, right justified, or center justified within its column. |
justified, right justified, or center justified within its column.</pre> |
||
</pre> |
|||
Or, using '''Text''' and its functions as an alternative to '''[Char]''' strings: |
|||
<syntaxhighlight lang="haskell">import Prelude as P |
|||
import Data.Text as T |
|||
(Text, pack, unpack, splitOn, unlines, unwords, length, |
|||
justifyLeft, justifyRight, center) |
|||
import Data.List (transpose, zip, maximumBy) |
|||
import Data.Ord (comparing) |
|||
rows :: [[Text]] |
|||
rows = |
|||
(splitOn (pack "$") . pack) <$> |
|||
[ "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." |
|||
] |
|||
cols :: [[Text]] |
|||
cols = |
|||
transpose $ |
|||
((++) <*> |
|||
(flip P.replicate (pack []) . |
|||
(-) (maximum (P.length <$> rows)) . P.length)) <$> |
|||
rows |
|||
main :: IO () |
|||
main = |
|||
mapM_ putStrLn $ |
|||
[ (\cols f -> |
|||
(unpack . T.unlines) $ |
|||
T.unwords <$> transpose ((\(xs, n) -> f (n + 1) ' ' <$> xs) <$> cols)) |
|||
(zip cols ((T.length . maximumBy (comparing T.length)) <$> cols)) |
|||
] <*> |
|||
[justifyLeft, justifyRight, center]</syntaxhighlight> |
|||
{{Out}} |
|||
<pre>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. </pre> |
|||
=={{header|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 ([http://www.HicEst.com/MatrixExplorer.htm 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. |
|||
<syntaxhighlight lang="hicest"> |
|||
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</syntaxhighlight> |
|||
<pre>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.</pre> |
|||
=={{header|Icon}} and {{header|Unicon}}== |
|||
An argument of <tt>left</tt>, <tt>center</tt>, or <tt>right</tt> controls the |
|||
column alignment. The default is left-alignment. |
|||
<syntaxhighlight lang="icon">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</syntaxhighlight> |
|||
Sample run: |
|||
<pre>->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. |
|||
-></pre> |
|||
=={{header|J}}== |
=={{header|J}}== |
||
Here, we rely on J's built-in formatting mechanism for boxed arrays, with spaces to separate the columns. |
|||
'''Solution''', using <tt>'LEFT CENTER RIGHT'=:i.3</tt> to specify justification: |
|||
_2 {:\ ": <;._2@:,~&>/ '$';LF;text [ 9!:17 ,~ CENTER [ 9!:7 ' '$~11 |
|||
(J's [[j:Vocabulary/Foreigns#m9|9!:n]] series of conjunctions queries (even) or sets (odd) session parameters. 9!:6 queries the box display characters, and 9!:7 sets them. Here, we use spaces with 9!:7 (discarding the blank rows). Meanwhile 9!:17 determines whether box contents are left justified, center justified or right justified, and we also use that. There's some additional discussion of this approach on the [[Talk:Align_columns#J_solution|talk page]].) |
|||
'''Solution''' |
|||
<syntaxhighlight lang="j">'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 |
|||
)</syntaxhighlight> |
|||
'''Example''': |
'''Example''': |
||
text=: noun define |
<syntaxhighlight lang="j"> 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 |
|||
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 |
Given a text file of many lines, where fields within a line |
||
are delineated by a single 'dollar' character, write a program |
are delineated by a single 'dollar' character, write a program |
||
Line 768: | Line 4,695: | ||
column are separated by at least one space. |
column are separated by at least one space. |
||
Further, allow for each word in a column to be either left |
Further, allow for each word in a column to be either left |
||
justified, right justified, or center justified within its column.</syntaxhighlight> |
|||
=={{header|Java}}== |
|||
{{works with|Java|7}} |
|||
{{libheader|Apache Commons Lang}} |
|||
<syntaxhighlight lang="java">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; |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|JavaScript}}== |
|||
===Imperative=== |
|||
<syntaxhighlight lang="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);</syntaxhighlight> |
|||
===Functional=== |
|||
<syntaxhighlight lang="javascript">//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'); |
|||
};</syntaxhighlight> |
|||
Or (ES5) using transpose and zipWith: |
|||
<syntaxhighlight lang="javascript">(function (strText) { |
|||
'use strict'; |
|||
// [[a]] -> [[a]] |
|||
function transpose(lst) { |
|||
return lst[0].map(function (_, iCol) { |
|||
return lst.map(function (row) { |
|||
return row[iCol]; |
|||
}) |
|||
}); |
|||
} |
|||
// (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('$'); |
|||
}), |
|||
lngCols = widest(lstRows), |
|||
lstCols = transpose(lstRows.map(function (r) { |
|||
return fullRow(r, lngCols) |
|||
})), |
|||
lstColWidths = lstCols.map(widest); |
|||
// THREE PARAGRAPHS, WITH VARIOUS WORD COLUMN ALIGNMENTS: |
|||
return [eLeft, eRight, eCenter] |
|||
.map(function (eAlign) { |
|||
var fPad = function (n, lstWords) { |
|||
return padWords(n, lstWords, eAlign); |
|||
}; |
|||
return transpose( |
|||
zipWith(fPad, lstColWidths, lstCols) |
|||
) |
|||
.map(unwords); |
|||
}) |
|||
.map(unlines) |
|||
.join('\n\n'); |
|||
})( |
|||
"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." |
|||
);</syntaxhighlight> |
|||
{{Out}} |
|||
<pre>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. </pre> |
|||
=={{header|jq}}== |
|||
{{ Works with|jq|1.4}} |
|||
The key to the following implementation is the filter named "transpose", which is defined to work on a possibly jagged matrix. It is provided as a built-in in jq 1.5 and later. |
|||
<syntaxhighlight lang="jq"># 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") |
|||
;</syntaxhighlight> |
|||
'''Example''': |
|||
<syntaxhighlight lang="jq">"Center:", format("center"), "", |
|||
"Left:", format("left"), "", |
|||
"Right:", format("right")</syntaxhighlight> |
|||
{{Out}} |
|||
<div style="overflow:scroll; height:200px;"><syntaxhighlight lang="sh">$ 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. |
|||
</syntaxhighlight></div> |
|||
=={{header|Jsish}}== |
|||
From Javascript ES5 entry. |
|||
<syntaxhighlight lang="javascript">/* Align columns, in Jsish */ |
|||
function alignColumns(phrases:array, just:string) { |
|||
var x, y, max, diff, left, right, cols=0; |
|||
for(x=0; x<phrases.length; x++) { |
|||
phrases[x] = phrases[x].split("$"); |
|||
if (phrases[x].length>cols) cols=phrases[x].length; |
|||
} |
|||
for (x=0; x<cols; x++) { |
|||
max = 0; |
|||
for (y=0; y<phrases.length; y++) if (phrases[y][x] && max<phrases[y][x].length) max = phrases[y][x].length; |
|||
for (y=0; y<phrases.length; y++) { |
|||
if (phrases[y][x]) { |
|||
diff = (max-phrases[y][x].length)/2; |
|||
left = " ".repeat(Math.floor(diff)); |
|||
right = " ".repeat(Math.ceil(diff)); |
|||
if (just == "left") { right += left; left=""; } |
|||
if (just == "right") { left += right; right=""; } |
|||
phrases[y][x] = left + phrases[y][x] + right; |
|||
} |
|||
} |
|||
} |
|||
for (x=0; x<phrases.length; x++) phrases[x] = phrases[x].join(" "); |
|||
phrases = phrases.join("\n"); |
|||
return phrases; |
|||
} |
|||
if (Interp.conf('unitTest')) { |
|||
var phrases = ["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 (var just of ['left', 'center', 'right']) { |
|||
var trial = phrases.slice(0); |
|||
puts(just); |
|||
puts(alignColumns(trial, just), '\n'); |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>prompt$ jsish --U alignColumns.jsi |
|||
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.</pre> |
|||
=={{header|Julia}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="julia">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</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
--------------------------------------------------------------------------------------------------------- |
|||
</pre> |
|||
=={{header|Kotlin}}== |
|||
<syntaxhighlight lang="scala">import java.nio.charset.StandardCharsets |
|||
import java.nio.file.Files |
|||
import java.nio.file.Paths |
|||
enum class AlignFunction { |
|||
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, l: Int): String |
|||
} |
|||
/** Aligns fields into columns, separated by "|". |
|||
* @constructor Initializes columns aligner from lines in a list of strings. |
|||
* @property lines Lines in a single string. Empty string does form a column. |
|||
*/ |
|||
class ColumnAligner(val lines: List<String>) { |
|||
operator fun invoke(a: AlignFunction) : String { |
|||
var result = "" |
|||
for (lineWords in words) { |
|||
for (i in lineWords.indices) { |
|||
if (i == 0) |
|||
result += '|' |
|||
result += a(lineWords[i], column_widths[i]) |
|||
result += '|' |
|||
} |
|||
result += '\n' |
|||
} |
|||
return result |
|||
} |
|||
private val words = arrayListOf<Array<String>>() |
|||
private val column_widths = arrayListOf<Int>() |
|||
init { |
|||
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 |
|||
} else { |
|||
column_widths[i] = Math.max(column_widths[i], lineWords[i].length) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
fun main(args: Array<String>) { |
|||
if (args.isEmpty()) { |
|||
println("Usage: ColumnAligner file [L|R|C]") |
|||
return |
|||
} |
|||
val ca = ColumnAligner(Files.readAllLines(Paths.get(args[0]), StandardCharsets.UTF_8)) |
|||
val alignment = if (args.size >= 2) args[1] else "L" |
|||
when (alignment) { |
|||
"L" -> print(ca(AlignFunction.LEFT)) |
|||
"R" -> print(ca(AlignFunction.RIGHT)) |
|||
"C" -> print(ca(AlignFunction.CENTER)) |
|||
else -> System.err.println("Error! Unknown alignment: " + alignment) |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Lambdatalk}}== |
|||
The input data is a sequence of characters where words are supposed to be separated by $ and lines be ended by \$. A HTML table is used to format the output left, centered or right justified. |
|||
<syntaxhighlight lang="scheme"> |
|||
{def 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.} |
|||
-> txt |
|||
{def columns // function's name |
|||
{def columns.r // loop function |
|||
{lambda {:just :a :b} |
|||
{if {A.empty? :a} // end of loop |
|||
then :b // return the string |
|||
else {columns.r :just // justification |
|||
{A.rest :a}. // loop on next char |
|||
{if {W.equal? {A.first :a} \} // if end of line |
|||
then < tr> :b // open a table row |
|||
else {if {W.equal? {A.first :a} $} // if space between words |
|||
then < td style="text-align::just;">:b // open a table data with justif |
|||
else {A.first :a}:b }} } }}} // else add character |
|||
{lambda {:just :txt} // main function |
|||
{table // open an HTML table |
|||
{columns.r // call the loop function |
|||
:just // justification |
|||
{A.reverse {A.split ${:txt}}} // split and reverse |
|||
. // end point |
|||
}}}} |
|||
-> columns |
|||
{columns left 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.. |
|||
{columns center txt} and {columns right txt} outputs can be seen in this website: http://lambdaway.free.fr/lambdawalks/?view=align_columns |
|||
</syntaxhighlight> |
|||
=={{header|Lasso}}== |
|||
<syntaxhighlight lang="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)</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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. |
|||
</pre> |
|||
=={{header|Liberty BASIC}}== |
|||
<syntaxhighlight lang="lb">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</syntaxhighlight> |
|||
=={{header|Lua}}== |
|||
{{works with|Lua|5.1}} |
|||
<syntaxhighlight lang="lua"> |
|||
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 |
|||
</syntaxhighlight> |
|||
Usage Example: |
|||
<syntaxhighlight lang="lua"> |
|||
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") |
|||
</syntaxhighlight> |
|||
=={{header|M2000 Interpreter}}== |
|||
<syntaxhighlight lang="m2000 interpreter"> |
|||
Module Align_Columns { |
|||
a$={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 cr$=chr$(13), lf$=chr$(10) |
|||
def c1=0, cmax=0, p1=-1, i |
|||
flush ' empty stack |
|||
for i=1 to len(a$) |
|||
select case mid$(a$,i,1) |
|||
case "$", cr$ |
|||
if p1<>-1 then data (p1, c1): p1=-1: cmax=max(c1,cmax):c1=0 |
|||
case lf$ |
|||
data (-1,0) ' push to end of stack an array of two items (a tuple in m2000) |
|||
else case |
|||
if p1=-1 then p1=i :c1=1 else c1++ |
|||
end select |
|||
next |
|||
if p1<>-1 then push (p1, c1): cmax=max(c1,cmax):c1=0 |
|||
\\ so now stack of values hold all tuples. |
|||
Dim Words(), AlignType$(1 to 3) |
|||
AlignType$(1)=lambda$ (a$,wd)->field$(a$, wd) |
|||
AlignType$(2)=lambda$ (a$,wd)->{ |
|||
a$=left$(a$, wd) |
|||
=left$(string$(" ", (len(a$)-wd) div 2)+a$+string$(" ",wd),wd) |
|||
} |
|||
AlignType$(3)= lambda$ (a$,wd)->format$("{0:"+str$(-wd)+"}", a$) |
|||
\\ [] return a stack object, reference and leave current stack of values a new stack |
|||
\\ Array( stack_object) empty the stack object moving items to an array |
|||
Words()=Array([]) |
|||
document export$ |
|||
def aline$ |
|||
cmax++ ' add one space |
|||
For al=1 to 3 |
|||
For i=0 to len(Words())-1 |
|||
if Words(i)(0)=-1 then |
|||
' we use rtrim$() to cut trailing spaces |
|||
export$=rtrim$(aline$)+cr$+lf$ : aline$="" |
|||
else |
|||
aline$+=AlignType$(al)(mid$(a$,Words(i)(0), Words(i)(1)),cmax) |
|||
end if |
|||
next i |
|||
next |
|||
\\ export to clipboard |
|||
Clipboard export$ |
|||
Rem Form 140, 60 |
|||
Rem Print #-2, export$ ' render text to console without using console's columns |
|||
} |
|||
Align_Columns |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:30ex;overflow:scroll"> |
|||
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. |
|||
</pre > |
|||
=={{header|Maple}}== |
|||
Assign the sample data. |
|||
<syntaxhighlight lang="maple"> |
|||
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": |
|||
</syntaxhighlight> |
|||
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. |
|||
<syntaxhighlight lang="maple"> |
|||
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: |
|||
</syntaxhighlight> |
|||
For the sample text, we get the following results. |
|||
<syntaxhighlight lang="maple"> |
|||
> 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. |
|||
</syntaxhighlight> |
|||
Alternatively, this could be printed to a file (using fprintf instead of printf). |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
|||
<syntaxhighlight lang="mathematica">TableForm[StringSplit[StringSplit[a,"\n"],"$"],TableAlignments -> Center]</syntaxhighlight> |
|||
Output with example text : |
|||
[[File:centeredtext.png]] |
|||
=={{header|MATLAB}} / {{header|Octave}}== |
|||
center-justified formatting is not implemented here |
|||
<syntaxhighlight lang="matlab"> |
|||
function r = align_columns(f) |
|||
fid = fopen('align_column_data.txt', 'r'); |
|||
D = {}; |
|||
M = 0; |
|||
while ~feof(fid) |
|||
s = fgetl(fid); |
|||
strsplit(s,'$'); |
|||
m = diff([0,find(s=='$')])-1; |
|||
M = max([M,zeros(1,length(m)-length(M))], [m,zeros(1,length(M)-length(m))]); |
|||
D{end+1}=s; |
|||
end |
|||
fclose(fid); |
|||
fprintf(1,'%%-- right-justified --%%\n') |
|||
FMT = sprintf('%%%ds ',M); |
|||
for k=1:length(D) |
|||
d = strsplit(D{k},'$'); |
|||
fprintf(1,FMT,d{:}); |
|||
fprintf(1,'\n'); |
|||
end |
|||
fprintf(1,'%%-- left-justified --%%\n') |
|||
FMT = sprintf('%%-%ds ',M); |
|||
for k=1:length(D) |
|||
d = strsplit(D{k},'$'); |
|||
fprintf(1,FMT,d{:}); |
|||
fprintf(1,'\n'); |
|||
end |
|||
end; |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
align_columns |
|||
%-- 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. |
|||
%-- 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. |
|||
</pre> |
|||
=={{header|MiniScript}}== |
|||
<syntaxhighlight lang="miniscript"> |
|||
Alignment = {"left": -1, "center": 0, "right": 1} |
|||
Align = {} |
|||
Align.load = function(contents) |
|||
self.lines = contents.split(char(13)) |
|||
self.rows = [] |
|||
self.numColumns = 0 |
|||
for line in self.lines |
|||
columns = line.split("$") |
|||
if columns.len > self.numColumns then self.numColumns = columns.len |
|||
self.rows.push(columns) |
|||
end for |
|||
self.widths = [] |
|||
for col in range(0, self.numColumns - 1) |
|||
maxWidth = 0 |
|||
for line in self.rows |
|||
if col > line.len - 1 then continue |
|||
if line[col].len > maxWidth then maxWidth = line[col].len |
|||
end for |
|||
self.widths.push(maxWidth) |
|||
end for |
|||
end function |
|||
Align.__getField = function(word, width, alignment) |
|||
if alignment == Alignment.left then return (word + " " * width)[:width] |
|||
if alignment == Alignment.right then return (" " * width+word)[-width:] |
|||
if alignment == Alignment.center then |
|||
leftMargin = floor((width - word.len) / 2) |
|||
return (" " * leftMargin + word + " " * width)[:width] |
|||
end if |
|||
end function |
|||
Align.output = function(alignment) |
|||
for line in self.rows |
|||
for c in range(0, line.len - 1) |
|||
print self.__getField(line[c], self.widths[c], alignment) + " ", "" |
|||
end for |
|||
print |
|||
end for |
|||
end function |
|||
txt = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" + char(13) |
|||
txt += "are$delineated$by$a$single$'dollar'$character,$write$a$program" + char(13) |
|||
txt += "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" + char(13) |
|||
txt += "column$are$separated$by$at$least$one$space." + char(13) |
|||
txt += "Further,$allow$for$each$word$in$a$column$to$be$either$left$" + char(13) |
|||
txt += "justified,$right$justified,$or$center$justified$within$its$column." |
|||
Align.load(txt) |
|||
print "Left alignment:" |
|||
Align.output(Alignment.left) |
|||
print |
|||
print "Right alignment:" |
|||
Align.output(Alignment.right) |
|||
print |
|||
print "Centered: " |
|||
Align.output(Alignment.center) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
>miniscript.exe align-columns.ms |
|||
Left alignment: |
|||
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 alignment: |
|||
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: |
|||
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. |
|||
</pre> |
|||
=={{header|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. |
|||
<syntaxhighlight lang="ml/i">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</syntaxhighlight> |
|||
=={{header|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. |
|||
<syntaxhighlight lang="ml/i">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</syntaxhighlight> |
|||
=={{header|MUMPS}}== |
|||
<syntaxhighlight lang="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.</syntaxhighlight> |
|||
=={{header|Nim}}== |
|||
<syntaxhighlight lang="nim">from strutils import splitLines, split |
|||
from sequtils import mapIt |
|||
from strfmt import format, write |
|||
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(it.split '$') |
|||
var maxs = newSeq[int](max words.mapIt(it.len)) |
|||
for line in words: |
|||
for j,w in line: |
|||
maxs[j] = max(maxs[j], w.len+1) |
|||
for i, align in ["<",">","^"]: |
|||
echo(["Left", "Right", "Center"][i], " column-aligned output:") |
|||
for line in words: |
|||
for j,w in line: |
|||
stdout.write(w.format align & $maxs[j]) |
|||
stdout.write "\n" |
|||
stdout.write "\n"</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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. </pre> |
|||
=={{header|Nit}}== |
|||
Source: [https://github.com/nitlang/nit/blob/master/examples/rosettacode/align_columns.nit the official Nit’s repository] |
|||
<syntaxhighlight lang="nit"># Task: Align columns |
|||
# |
|||
# Uses `Text::justify` from the standard library. |
|||
module align_columns |
|||
fun aligner(text: String, left: Float) |
|||
do |
|||
# Each row is a sequence of fields |
|||
var rows = new Array[Array[String]] |
|||
for line in text.split('\n') do |
|||
rows.add line.split("$") |
|||
end |
|||
# Compute the final length of each column |
|||
var lengths = new Array[Int] |
|||
for fields in rows do |
|||
var i = 0 |
|||
for field in fields do |
|||
var fl = field.length |
|||
if lengths.length <= i or fl > lengths[i] then |
|||
lengths[i] = fl |
|||
end |
|||
i += 1 |
|||
end |
|||
end |
|||
# Process each line and align each field |
|||
for fields in rows do |
|||
var line = new Array[String] |
|||
var i = 0 |
|||
for field in fields do |
|||
line.add field.justify(lengths[i], left) |
|||
i += 1 |
|||
end |
|||
print line.join(" ") |
|||
end |
|||
end |
|||
var 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.""" |
|||
aligner(text, 0.0) |
|||
aligner(text, 1.0) |
|||
aligner(text, 0.5)</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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. |
|||
</pre> |
|||
=={{header|Oberon-2}}== |
|||
works with oo2c version 2. |
|||
<syntaxhighlight lang="oberon2"> |
|||
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. |
|||
</syntaxhighlight> |
|||
<pre> |
|||
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. |
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. |
|||
</pre> |
|||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
< |
<syntaxhighlight lang="ocaml">#load "str.cma" |
||
open Str |
open Str |
||
Line 824: | Line 6,478: | ||
let sp2 = String.make pad2 ' ' in |
let sp2 = String.make pad2 ' ' in |
||
Printf.printf "%s%s%s " sp1 word sp2); |
Printf.printf "%s%s%s " sp1 word sp2); |
||
;;</ |
;;</syntaxhighlight> |
||
=={{header| |
=={{header|Oforth}}== |
||
<lang Perl> |
|||
<syntaxhighlight lang="oforth">import: mapping |
|||
#/usr/bin/perl -w |
|||
import: file |
|||
use strict ; |
|||
: <<nbl \ stream n -- stream |
|||
#[ ' ' <<c ] times ; |
|||
String method: justify( n just -- s ) |
|||
| l m | |
|||
n self size - dup ->l 2 / ->m |
|||
String new |
|||
just $RIGHT if=: [ l <<nbl self << return ] |
|||
just $LEFT if=: [ self << l <<nbl return ] |
|||
m <<nbl self << l m - <<nbl |
|||
; |
|||
: align( file just -- ) |
|||
| lines maxsize | |
|||
#[ wordsWith( '$' ) ] file File new map ->lines |
|||
0 #[ apply( #[ size max ] ) ] lines apply ->maxsize |
|||
#[ apply( #[ justify( maxsize , just) . ] ) printcr ] lines apply |
|||
;</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
>"align.txt" $LEFT align |
|||
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 |
|||
> |
|||
</pre> |
|||
=={{header|ooRexx}}== |
|||
<syntaxhighlight lang="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 |
|||
</syntaxhighlight> |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|OpenEdge/Progress}}== |
|||
<syntaxhighlight lang="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.</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
--------------------------- |
|||
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 |
|||
---------------------------</pre> |
|||
=={{header|OxygenBasic}}== |
|||
<pre> |
|||
'================ |
|||
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 |
|||
</pre> |
|||
=={{header|Oz}}== |
|||
<syntaxhighlight lang="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} |
|||
die "Call : perl columnaligner.pl <inputfile> <printorientation>!\n" unless |
|||
Txt#{Spaces Extra} |
|||
@ARGV == 2 ; #$ARGV[ 0 ] contains example file , $ARGV[1] any of 'left' , 'right' or 'center' |
|||
end |
|||
die "last argument must be one of center, left or right!\n" unless |
|||
$ARGV[ 1 ] =~ /center|left|right/ ; |
|||
fun {Right Txt Extra} |
|||
sub printLines( $$$ ) ; |
|||
{Spaces Extra}#Txt |
|||
open ( INFILE , "<" , "$ARGV[ 0 ]" ) or die "Can't open $ARGV[ 0 ]!\n" ; |
|||
end |
|||
my @lines = <INFILE> ; |
|||
close ( INFILE ) ; |
|||
fun {Center Txt Extra} |
|||
map { chomp $_ } @lines ; |
|||
Half = Extra div 2 |
|||
in |
|||
map { push @fieldwidths , length( $_ ) } split ( /\$/ , $lines[ 0 ] ) ; |
|||
{Spaces Half}#Txt#{Spaces Half + Extra mod 2} |
|||
foreach my $i ( 1..$#lines ) { |
|||
end |
|||
my @words = split( /\$/ , $lines[ $i ] ) ; |
|||
foreach my $j ( 0..$#words ) { |
|||
%% helpers: |
|||
if ( $j <= $#fieldwidths ) { |
|||
if ( length( $words[ $j ] ) > $fieldwidths[ $j ] ) { |
|||
%% 3 -> unit(1 2 3) |
|||
$fieldwidths[ $j ] = length( $words[ $j ] ) ; |
|||
fun {TupleRange Max} |
|||
} |
|||
{List.toTuple unit {List.number 1 Max 1}} |
|||
} |
|||
end |
|||
else { |
|||
push @fieldwidths, length( $words[ $j ] ) ; |
|||
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}</syntaxhighlight> |
|||
=={{header|Pascal}}== |
|||
See [[Align_columns#Delphi | Delphi]] |
|||
modified to {{works with|Free Pascal}} |
|||
<syntaxhighlight lang="pascal">program Project1; |
|||
{$H+}//Use ansistrings |
|||
uses |
|||
Classes, |
|||
SysUtils, |
|||
StrUtils; |
|||
procedure AlignByColumn(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: TStringList; |
|||
TextLines: array of TStringList; |
|||
OutPutString, EmptyString, Item: string; |
|||
MaxLength, i, j: Int32; |
|||
begin |
|||
try |
|||
MaxLength := 0; |
|||
TextLine := TStringList.Create; |
|||
TextLine.Text := TextToAlign; |
|||
setlength(Textlines, TextLine.Count); |
|||
for i := 0 to TextLine.Count - 1 do |
|||
begin |
|||
Textlines[i] := TStringList.Create; |
|||
Textlines[i].Text := AnsiReplaceStr(TextLine[i], '$', #$D#$A); |
|||
end; |
|||
for i := 0 to High(TextLines) do |
|||
for j := 0 to Textlines[i].Count - 1 do |
|||
if MaxLength < Length(TextLines[i][j]) then |
|||
MaxLength := Length(TextLines[i][j]); |
|||
if MaxLength > 0 then |
|||
MaxLength := MaxLength + 2; // Add two empty spaces to it |
|||
for i := 0 to High(TextLines) do |
|||
begin |
|||
OutPutString := ''; |
|||
for j := 0 to Textlines[i].Count - 1 do |
|||
begin |
|||
EmptyString := StringOfChar(' ', MaxLength); |
|||
if j <> 0 then |
|||
EmptyString[1] := '|'; |
|||
Item := TextLines[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; |
|||
writeln(OutPutString); |
|||
end; |
|||
finally |
|||
writeln; |
|||
FreeAndNil(TextLine); |
|||
for i := High(TextLines) downto 0 do |
|||
FreeAndNil(TextLines[i]); |
|||
end; |
|||
end; |
|||
begin |
|||
AlignByColumn(taLeftJustify); |
|||
AlignByColumn(taCenter); |
|||
AlignByColumn(taRightJustify); |
|||
end.</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|Perl}}== |
|||
<syntaxhighlight 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[ 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" ; |
|||
}</syntaxhighlight> |
|||
a shorter solution |
|||
<syntaxhighlight lang="perl">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</syntaxhighlight> |
|||
=={{header|Phix}}== |
|||
<!--<syntaxhighlight lang="phix">--> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">data</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> |
|||
<span style="color: #008000;">"Given$a$text$file$of$many$lines,$where$fields$within$a$line$"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #008000;">"are$delineated$by$a$single$'dollar'$character,$write$a$program"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #008000;">"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #008000;">"column$are$separated$by$at$least$one$space."</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #008000;">"Further,$allow$for$each$word$in$a$column$to$be$either$left$"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #008000;">"justified,$right$justified,$or$center$justified$within$its$column."</span> |
|||
<span style="color: #0000FF;">}</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">out</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">delim</span> |
|||
<span style="color: #008080;">while</span> <span style="color: #000000;">first</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">delim</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">find_from</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">first</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">delim</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">delim</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #000000;">out</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">out</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">first</span><span style="color: #0000FF;">..</span><span style="color: #000000;">delim</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> |
|||
<span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">delim</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">out</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">align</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">width</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">alignment</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">width</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span> |
|||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">alignment</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">&</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">alignment</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">s</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #000080;font-style:italic;">-- (PL if I'd written this, I'd have n-floor(n/2) on the rhs)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">))</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">&</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">AlignColumns</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">llij</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">li</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">maxlens</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
<span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">li</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">'$'</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">li</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">li</span><span style="color: #0000FF;">)></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">maxlens</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">maxlens</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">li</span><span style="color: #0000FF;">)-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">maxlens</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">li</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">llij</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">li</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">llij</span><span style="color: #0000FF;">></span><span style="color: #000000;">maxlens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span> <span style="color: #000000;">maxlens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">llij</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (alignment = left/centre/right)</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">align</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">maxlens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">' '</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">getc</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
<span style="color: #000000;">AlignColumns</span><span style="color: #0000FF;">()</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|Phixmonti}}== |
|||
<syntaxhighlight lang="phixmonti">include ..\Utilitys.pmt |
|||
0 40 repeat var gap |
|||
( "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." ) |
|||
len var lines |
|||
def alignWords /# -1/0/1 for left/center/right #/ |
|||
>ps |
|||
lines for |
|||
get len for >ps |
|||
tps get gap ps> get nip 1 + |
|||
tps -1 == if -1 * align else |
|||
tps 0 == if tostr align else |
|||
tps 1 == if align else |
|||
drop drop "Wrong!" exitfor |
|||
endif endif endif |
|||
print |
|||
endfor |
|||
drop |
|||
nl |
|||
endfor |
|||
ps> drop |
|||
enddef |
|||
lines for var i |
|||
i get "$" " " subst split |
|||
len for var j |
|||
j get len dup |
|||
gap j get rot |
|||
< if swap j set else swap drop endif var gap drop |
|||
endfor |
|||
i set |
|||
endfor |
|||
-1 alignWords nl |
|||
0 alignWords nl |
|||
1 alignWords nl |
|||
drop</syntaxhighlight> |
|||
=={{header|PHP}}== |
|||
<syntaxhighlight lang="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(array_key_exists($col, $fields) ? $fields[$col] : 0)); |
|||
foreach ($fieldsbyrow as &$fields) |
|||
$fields[$col] = str_pad(array_key_exists($col, $fields) ? $fields[$col] : "", $maxwidth, ' ', $justtype); |
|||
unset($fields); // see http://bugs.php.net/29992 |
|||
} |
} |
||
$result = ''; |
|||
map { printLine( $_ , $ARGV[ 1 ] , \@fieldwidths ) } @lines ; |
|||
foreach ($fieldsbyrow as $fields) |
|||
################################################################## #### |
|||
$result .= implode(' ', $fields) . "\n"; |
|||
sub printLine { |
|||
return $result; |
|||
} |
|||
my $orientation = shift ; |
|||
my $widthref = shift ; |
|||
$textinfile = 'Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
|||
my @words = split( /\$/, $line ) ; |
|||
are$delineated$by$a$single$\'dollar\'$character,$write$a$program |
|||
foreach my $k ( 0..$#words ) { |
|||
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ |
|||
my $printwidth = $widthref->[ $k ] + 1 ; |
|||
column$are$separated$by$at$least$one$space. |
|||
if ( $orientation eq 'center' ) { |
|||
Further,$allow$for$each$word$in$a$column$to$be$either$left$ |
|||
$printwidth++ ; |
|||
justified,$right$justified,$or$center$justified$within$its$column.'; |
|||
} |
|||
if ( $orientation eq 'left' ) { |
|||
foreach (array('L', 'R', 'C') as $j) |
|||
print $words[ $k ] ; |
|||
echo aligner($textinfile, $j); |
|||
for ( my $i = 0 ; $i < $printwidth - length( $words[ $k ] ) ; $i++ ) { |
|||
print " " ; |
|||
?></syntaxhighlight> |
|||
} |
|||
} |
|||
=={{header|Picat}}== |
|||
if ( $orientation eq 'right' ) { |
|||
<syntaxhighlight lang="picat">import util. |
|||
for ( my $i = 0 ; $i < $printwidth - length( $words[ $k ] ) ; $i++ ) { |
|||
print " " ; |
|||
main => |
|||
} |
|||
Text = |
|||
print $words[ $k ] ; |
|||
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
|||
} |
|||
are$delineated$by$a$single$'dollar'$character,$write$a$program |
|||
if ( $orientation eq 'center' ) { |
|||
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ |
|||
my $left = int( ( $printwidth - length( $words[ $k ] ) ) / 2 ) ; |
|||
column$are$separated$by$at$least$one$space. |
|||
my $right = $printwidth - length( $words[ $k ] ) - $left ; |
|||
Further,$allow$for$each$word$in$a$column$to$be$either$left$ |
|||
if ( $left == 1 ) { |
|||
justified,$right$justified,$or$center$justified$within$its$column.", |
|||
print " " ; |
|||
Lines = split(Text,"\n"), |
|||
Lines = [Line1|_], |
|||
if ( $left > 1 ) { |
|||
N = len(split(strip(Line1,"$ "), "$")), % number of columns |
|||
WidthArr = {0 : _ in 1..N}, |
|||
foreach (Line in Lines) |
|||
Words = split(strip(Line,"$ "), "$"), |
|||
foreach ({I,Word} in zip(1..N, Words)) |
|||
WidthArr[I] := max(WidthArr[I], len(Word)) |
|||
end |
|||
end, |
|||
foreach (I in 1..N) |
|||
WidthArr[I] := WidthArr[I]+1 % separate cols by at least one space |
|||
end, |
|||
print " " ; |
|||
foreach (Align in [left, right, center]) |
|||
output_lines(Lines,N,WidthArr,Align), |
|||
} |
|||
nl,nl |
|||
end. |
|||
output_lines(Lines,N,WidthArr,Align) => |
|||
foreach (Line in Lines) |
|||
Words = split(strip(Line,"$ "), "$"), |
|||
foreach ({I,Word} in zip(1..N, Words)) |
|||
output_word(Word,WidthArr[I],Align) |
|||
end, |
|||
nl |
|||
end. |
|||
output_word(Word,Width,left) => |
|||
printf("%-*s",Width,Word). |
|||
output_word(Word,Width,right) => |
|||
printf("%*s",Width,Word). |
|||
output_word(Word,Width,_) => |
|||
Pad = len(Word)-Width, |
|||
Pad1 is Pad div 2, |
|||
Pad2 is Pad-Pad1, |
|||
printf("%*s%s%*s",Pad1,"",Word,Pad2,""). |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|PicoLisp}}== |
|||
<syntaxhighlight lang="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</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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. </pre> |
|||
=={{header|PL/I}}== |
|||
<syntaxhighlight lang="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; |
|||
</syntaxhighlight> |
|||
=={{header|PowerShell}}== |
|||
<syntaxhighlight lang="powershell"> |
|||
$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) |
|||
print "\n" ; |
|||
} |
|||
} |
|||
$arr | Format-Table -HideTableHeaders -Wrap * |
|||
</lang> |
|||
</syntaxhighlight> |
|||
<b>Output:</b> |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|Prolog}}== |
|||
Works with SWI-Prolog. |
|||
<syntaxhighlight lang="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). |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<FONT SIZE="2"><pre> ?- 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 .</pre></FONT> |
|||
=={{header|PureBasic}}== |
|||
{{works with|PureBasic|4.41}} |
|||
<syntaxhighlight lang="purebasic">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</syntaxhighlight> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
===Procedural=== |
|||
<lang python>from StringIO import StringIO |
|||
====Using f-strings==== |
|||
<syntaxhighlight lang="python">from itertools import zip_longest |
|||
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()] |
|||
widths = [max(len(word) for word in col) |
|||
for col in zip_longest(*parts, fillvalue='')] |
|||
for justify in "<_Left ^_Center >_Right".split(): |
|||
j, jtext = justify.split('_') |
|||
print(f"{jtext} column-aligned output:\n") |
|||
for line in parts: |
|||
print(' '.join(f"{wrd:{j}{wdth}}" for wdth, wrd in zip(widths, line))) |
|||
print("- " * 52) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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. |
|||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|||
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. |
|||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|||
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. |
|||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </pre> |
|||
====Using StringIO==== |
|||
<syntaxhighlight lang="python">from StringIO import StringIO |
|||
textinfile = '''Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
textinfile = '''Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
||
Line 925: | Line 7,755: | ||
Return the justified output as a string |
Return the justified output as a string |
||
''' |
''' |
||
assert justification in |
assert justification in j2justifier, "justification can be L, R, or C; (Left, Right, or Centered)." |
||
justifier = j2justifier[justification] |
justifier = j2justifier[justification] |
||
Line 950: | Line 7,780: | ||
infile = StringIO(textinfile) |
infile = StringIO(textinfile) |
||
print "\n# %s Column-aligned output:" % align |
print "\n# %s Column-aligned output:" % align |
||
print aligner(infile, align[0])</ |
print aligner(infile, align[0])</syntaxhighlight> |
||
{{out}} |
|||
Example output: |
|||
<pre> |
<pre> |
||
# Left Column-aligned output: |
# Left Column-aligned output: |
||
Line 977: | Line 7,807: | ||
Further, allow for each word in a column to be either left |
Further, allow for each word in a column to be either left |
||
justified, right justified, or center justified within its column. </pre> |
justified, right justified, or center justified within its column. </pre> |
||
====Brief native version==== |
|||
Works with Python 2 and 3. |
|||
<syntaxhighlight lang="python">''' |
|||
cat <<'EOF' > 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. |
|||
EOF |
|||
''' |
|||
for align in '<^>': |
|||
rows = [ line.strip().split('$') for line in open('align_columns.dat') ] |
|||
fmts = [ '{:%s%d}' % (align, max( len(row[i]) if i < len(row) else 0 for row in rows )) |
|||
for i in range(max(map(len, rows))) ] |
|||
for row in rows: |
|||
print(' '.join(fmts).format(*(row + [''] * len(fmts)))) |
|||
print('')</syntaxhighlight> |
|||
====Alternative==== |
|||
{{trans|D}} |
|||
<syntaxhighlight lang="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.""" |
|||
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]), end=' ') |
|||
print() |
|||
print("- " * 52)</syntaxhighlight> |
|||
===Functional=== |
|||
====As a fold==== |
|||
A fold/'''reduce''' between two transpositions. |
|||
(Selection of string justification methods via '''getattr'''): |
|||
{{Works with|Python|3.7}} |
|||
<syntaxhighlight lang="python">'''Variously aligned columns |
|||
from delimited text. |
|||
''' |
|||
from functools import reduce |
|||
from itertools import repeat |
|||
# TEST ---------------------------------------------------- |
|||
# main :: IO () |
|||
def main(): |
|||
'''Test of three alignments.''' |
|||
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.''' |
|||
rows = [x.split('$') for x in txt.splitlines()] |
|||
table = paddedRows(max(map(len, rows)))('')(rows) |
|||
print('\n\n'.join(map( |
|||
alignedTable(table)(' '), |
|||
[-1, 0, 1] # Left, Center, Right |
|||
))) |
|||
# alignedTable :: [[String]] -> Alignment -> String -> String |
|||
def alignedTable(rows): |
|||
'''Tabulation of rows of cells, with cell alignment |
|||
specified by: |
|||
eAlign -1 = left |
|||
eAlign 0 = center |
|||
eAlign 1 = right |
|||
and separator between columns |
|||
supplied by the `sep` argument. |
|||
''' |
|||
def go(sep, eAlign): |
|||
lcr = ['ljust', 'center', 'rjust'][1 + eAlign] |
|||
# nextAlignedCol :: [[String]] -> [String] -> [[String]] |
|||
def nextAlignedCol(cols, col): |
|||
w = max(len(cell) for cell in col) |
|||
return cols + [ |
|||
[getattr(s, lcr)(w, ' ') for s in col] |
|||
] |
|||
return '\n'.join([ |
|||
sep.join(cells) for cells in |
|||
zip(*reduce(nextAlignedCol, zip(*rows), [])) |
|||
]) |
|||
return lambda sep: lambda eAlign: go(sep, eAlign) |
|||
# GENERIC ------------------------------------------------- |
|||
# paddedRows :: Int -> a -> [[a]] -> [[a]] |
|||
def paddedRows(n): |
|||
'''A list of rows of even length, |
|||
in which each may be padded (but |
|||
not truncated) to length n with |
|||
appended copies of value v.''' |
|||
def go(v, xs): |
|||
def pad(x): |
|||
d = n - len(x) |
|||
return (x + list(repeat(v, d))) if 0 < d else x |
|||
return [pad(row) for row in xs] |
|||
return lambda v: lambda xs: go(v, xs) if xs else [] |
|||
# MAIN --- |
|||
if __name__ == '__main__': |
|||
main()</syntaxhighlight> |
|||
{{Out}} |
|||
<pre>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. </pre> |
|||
=={{header|q}}== |
|||
<syntaxhighlight lang="q">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." ) |
|||
ta:{[aln;txt] / tabulate aligned |
|||
sl:(count'')s:"$"vs/:txt; / strings and their lengths |
|||
cw:{rl#\:max x@/:\:til max rl:count each x}sl; / cell widths |
|||
ps:$[aln=`R;-1-cw;1+cw]$''s; / padded strings |
|||
ps:$[aln=`C;(neg(cw-sl)div 2)rotate''ps;ps]; / center |
|||
1,[;"\n\n"]"\n"sv raze each ps; } / print</syntaxhighlight> |
|||
{{out}} |
|||
<pre>q)ta[`L]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. |
|||
q)ta[`R]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. |
|||
q)ta[`C]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.</pre> |
|||
[https://code.kx.com/q/ref/ Q Reference Card] |
|||
=={{header|R}}== |
=={{header|R}}== |
||
<syntaxhighlight lang="r"># Read in text |
|||
{{incorrect|R|Alignment in the rightmost columns is wrong.}} |
|||
<lang R> |
|||
# Read in text |
|||
lines <- readLines(tc <- textConnection("Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
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 |
are$delineated$by$a$single$'dollar'$character,$write$a$program |
||
Line 1,002: | Line 8,021: | ||
# Print |
# Print |
||
print0 <- function(x) invisible(apply(x, 1, function(x) cat(x, "\n"))) |
|||
noquote(leftjust) |
|||
print0(leftjust) |
|||
noquote(rightjust) |
|||
print0(rightjust) |
|||
noquote(centrejust) |
|||
print0(centrejust)</syntaxhighlight> |
|||
</lang> |
|||
Right justified output shown. |
Right justified output shown. |
||
<div style="width:full;overflow:scroll"><pre> |
<div style="width:full;overflow:scroll"><pre> |
||
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. |
|||
[6,] justified, right justified, or center justified within its column. |
|||
</pre></div> |
</pre></div> |
||
=={{header| |
=={{header|Racket}}== |
||
<syntaxhighlight lang="racket"> |
|||
<lang ruby>require 'stringio' |
|||
#lang racket |
|||
(define (display-aligned text #:justify [justify 'left]) |
|||
textinfile = <<END |
|||
(define lines |
|||
Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
|||
(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) |
|||
</syntaxhighlight> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|Rakudo|2018.03}} |
|||
Call with parameter left (default), center or right. |
|||
<syntaxhighlight lang="raku" line>my @lines = |
|||
q|Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
|||
are$delineated$by$a$single$'dollar'$character,$write$a$program |
are$delineated$by$a$single$'dollar'$character,$write$a$program |
||
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ |
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$ |
||
Line 1,027: | Line 8,086: | ||
Further,$allow$for$each$word$in$a$column$to$be$either$left$ |
Further,$allow$for$each$word$in$a$column$to$be$either$left$ |
||
justified,$right$justified,$or$center$justified$within$its$column. |
justified,$right$justified,$or$center$justified$within$its$column. |
||
|.lines; |
|||
END |
|||
my @widths; |
|||
J2justifier = {'L' => String.instance_method(:ljust), |
|||
'R' => String.instance_method(:rjust), |
|||
'C' => String.instance_method(:center)} |
|||
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 } |
|||
} |
|||
}</syntaxhighlight> |
|||
Or a more functional version, called like <code>./align.p6 left input.txt</code>, which however only supports left and right alignment (not center): |
|||
<syntaxhighlight lang="raku" line>sub MAIN ($alignment where 'left'|'right', $file) { |
|||
my @lines := $file.IO.lines.map(*.split('$').cache).cache; |
|||
my @widths = roundrobin(|@lines).map(*».chars.max); |
|||
my $align = {left=>'-', right=>''}{$alignment}; |
|||
my $format = @widths.map( '%' ~ ++$ ~ '$' ~ $align ~ * ~ 's' ).join(' ') ~ "\n"; |
|||
printf $format, |$_ for @lines; |
|||
}</syntaxhighlight> |
|||
=={{header|RapidQ}}== |
|||
<syntaxhighlight lang="vb"> |
|||
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 |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:20ex;overflow:scroll">TextLeft contains: |
|||
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. |
|||
TextRight contains: |
|||
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. |
|||
TextCenter contains: |
|||
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. |
|||
</pre> |
|||
=={{header|REBOL}}== |
|||
<syntaxhighlight lang="rebol">REBOL [ |
|||
Title: "Align Columns" |
|||
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] |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:15ex;overflow:scroll">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. |
|||
</pre> |
|||
=={{header|Red}}== |
|||
<syntaxhighlight lang="red">Red [ |
|||
Title: "Align Columns" |
|||
Original-Author: oofoe |
|||
] |
|||
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.} |
|||
; Parse specimen into data grid. |
|||
data: copy [] |
|||
foreach line split text lf [ |
|||
append/only data split line "$" |
|||
] |
|||
; Compute independent widths for each column. |
|||
widths: copy [] |
|||
foreach line data [ |
|||
forall line [ |
|||
i: index? line |
|||
if i > length? widths [append widths 0] |
|||
widths/:i: max widths/:i length? line/1 |
|||
] |
|||
] |
|||
pad: function [n] [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: function [n s] [ |
|||
d: n - length? s |
|||
h: round/down d / 2 |
|||
rejoin [pad h s pad d - h] |
|||
] |
|||
; 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 [newline "Align" i "..." newline] entable data get i]</syntaxhighlight> |
|||
=={{header|REXX}}== |
|||
===(no output)=== |
|||
<syntaxhighlight lang="rexx">/*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</syntaxhighlight> |
|||
===(with output)=== |
|||
<syntaxhighlight lang="rexx">/*REXX program displays various alignments for words in an array of text strings. */ |
|||
size= 0; t.=; cols= 0; wid.= 0; @.= /*zero or nullify some variables. */ |
|||
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\=='' /* [↓] process all the text lines. */ |
|||
_= strip(t.r,,'$') /*strip leading & trailing dollar signs*/ |
|||
do c=1 until _=='' /* [↓] process each of the words. */ |
|||
parse var _ @.r.c '$' _ /*extract the words from a line of text*/ |
|||
wid.c= max(wid.c, length(@.r.c) ) /*find the maximum 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 the width of the biggest line. */ |
|||
rows= r - 1 /*adjust ROWS because of the DO loop.*/ |
|||
do j=1 for 3; say; say /*show two blank lines for a separator.*/ |
|||
say center(word('left right center', j) "aligned", size+cols-1, "═") /*show title*/ |
|||
do r=1 for rows; _= /*construct 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 _= _ center(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 all done. */</syntaxhighlight> |
|||
{{out|output|text= when using the default input:}} |
|||
<pre> |
|||
══════════════════════════════════════════════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. |
|||
</pre> |
|||
===(boxed output)=== |
|||
Note: this version boxes each column of output to better show the columns. |
|||
<syntaxhighlight lang="rexx">/*REXX program displays various alignments for words in an array of text strings. */ |
|||
size= 0; t.=; cols= 0; wid.= 0; @.= /*zero or nullify some variables. */ |
|||
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\=='' /* [↓] process all the text lines. */ |
|||
_= strip(t.r,,'$') /*strip leading & trailing dollar signs*/ |
|||
do c=1 until _=='' /* [↓] process each of the words. */ |
|||
parse var _ @.r.c '$' _ /*extract the words from a line of text*/ |
|||
wid.c= max(wid.c, length(@.r.c) ) /*find the maximum 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 the width of the biggest line. */ |
|||
rows= r - 1 /*adjust ROWS because of the DO loop.*/ |
|||
do j=1 for 3; say; say /*show two blank lines for a separator.*/ |
|||
say center(word('left right center', j) "aligned", size+cols+1, "═") /*show title*/ |
|||
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) /*justify left*/ |
|||
if j==2 then _= _ || ! || right(x, wid.c) /* " ruggt*/ |
|||
if j==3 then _= _ || ! || center(x, wid.c) /* " ctr.*/ |
|||
end /*c*/ |
|||
if r==0 then do; _= '┌'substr(_, 2, length(_) - 1)"┐" /*top line.*/ |
|||
bot= '└'substr(_, 2, length(_) - 2)"┘" /*bot " */ |
|||
end |
|||
else _= _ || ! /*append trailing end boxing character.*/ |
|||
say _ |
|||
end /*r*/ /* [↑] shows words in boxes. */ |
|||
say translate(bot, '┴', "┬") /*display the bottom line of the box. */ |
|||
end /*j*/ /*stick a fork in it, we're all done. */</syntaxhighlight> |
|||
{{out|output|text= when using the default input:}} |
|||
<pre> |
|||
═══════════════════════════════════════════════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.│ │ │ │ |
|||
└──────────┴──────────┴──────────┴──────┴──────┴─────────┴──────────┴────────┴───────┴───────┴──────┴────┘ |
|||
</pre> |
|||
=={{header|Ruby}}== |
|||
{{works with|Ruby|1.9.3+}} |
|||
<syntaxhighlight lang="ruby">J2justifier = {Left: :ljust, Right: :rjust, Center: :center} |
|||
=begin |
=begin |
||
Justify columns of textual tabular input where the record separator is the newline |
Justify columns of textual tabular input where the record separator is the newline |
||
and the field separator is a 'dollar' character. |
and the field separator is a 'dollar' character. |
||
justification can be |
justification can be Symbol; (:Left, :Right, or :Center). |
||
Return the justified output as a string |
Return the justified output as a string |
||
=end |
=end |
||
def aligner(infile, justification = |
def aligner(infile, justification = :Left) |
||
justifier = J2justifier[justification] |
|||
fieldsbyrow = infile.map {|line| line.strip.split('$')} |
fieldsbyrow = infile.map {|line| line.strip.split('$')} |
||
# pad to same number of fields per record |
# pad to same number of fields per record |
||
maxfields = fieldsbyrow.map |
maxfields = fieldsbyrow.map(&:length).max |
||
fieldsbyrow.map! {|row| |
fieldsbyrow.map! {|row| row + ['']*(maxfields - row.length)} |
||
row + ['']*(maxfields - row.length) |
|||
} |
|||
# calculate max fieldwidth per column |
# calculate max fieldwidth per column |
||
colwidths = fieldsbyrow.transpose.map {|column| |
colwidths = fieldsbyrow.transpose.map {|column| |
||
column.map |
column.map(&:length).max |
||
} |
} |
||
# pad fields in columns to colwidth with spaces |
# pad fields in columns to colwidth with spaces |
||
justifier = J2justifier[justification] |
|||
fieldsbyrow.map! {|row| |
|||
fieldsbyrow.map {|row| |
|||
row.zip(colwidths).map {|field, width| |
row.zip(colwidths).map {|field, width| |
||
field.send(justifier, width) |
|||
} |
}.join(" ") |
||
} |
}.join("\n") |
||
fieldsbyrow.map {|row| row.join(" ")}.join("\n") |
|||
end |
end |
||
require 'stringio' |
|||
for align in %w{Left Right Center} |
|||
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 [:Left, :Right, :Center] |
|||
infile = StringIO.new(textinfile) |
infile = StringIO.new(textinfile) |
||
puts "\n# %s Column-aligned output:" % align |
puts "\n# %s Column-aligned output:" % align |
||
puts aligner(infile, align |
puts aligner(infile, align) |
||
end |
end |
||
</syntaxhighlight> |
|||
{{out}} |
|||
Example output: |
|||
<pre> |
<pre> |
||
# Left Column-aligned output: |
# Left Column-aligned output: |
||
Line 1,095: | Line 8,592: | ||
justified, right justified, or center justified within its column. |
justified, right justified, or center justified within its column. |
||
</pre> |
</pre> |
||
=={{header|Run BASIC}}== |
|||
<syntaxhighlight lang="runbasic">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</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:15ex;overflow:scroll">------------ 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. </pre> |
|||
=={{header|Rust}}== |
|||
<syntaxhighlight lang="rust">use std::iter::{repeat, 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_end_matches('$')) |
|||
{ |
|||
let lens = line.split('$').map(|s| s.chars().count()); |
|||
for (idx, len) in lens.enumerate() { |
|||
if idx < widths.len() { |
|||
widths[idx] = std::cmp::max(widths[idx], len); |
|||
} else { |
|||
widths.push(len); |
|||
} |
|||
} |
|||
} |
|||
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_end_matches('$')) |
|||
{ |
|||
for (s, w) in line.split('$').zip(widths.iter()) { |
|||
let blank_count = w - s.chars().count(); |
|||
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)); |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:15ex;overflow:scroll"> |
|||
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. |
|||
</pre> |
|||
=={{header|Scala}}== |
|||
{{works with|scala|2.8.0.r18997-b20091009021954}} |
|||
For Scala 2.7, change from fromPath to fromFile, and remove the extra parameter to Source's getLines. |
|||
<syntaxhighlight lang="scala">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 |
|||
} |
|||
}</syntaxhighlight> |
|||
Another take: |
|||
<syntaxhighlight lang="scala">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</syntaxhighlight> |
|||
=={{header|Scheme}}== |
|||
<syntaxhighlight lang="scheme"> |
|||
(import (scheme base) |
|||
(scheme write) |
|||
(srfi 1) |
|||
(except (srfi 13) string-for-each string-map) |
|||
(srfi 14)) |
|||
;; text is a list of lines, alignment is left/right/center |
|||
;; displays the aligned text in columns with a single space gap |
|||
(define (align-columns text alignment) |
|||
(define (split line) ; splits string on $ into list of strings |
|||
(string-tokenize line (char-set-complement (->char-set "$")))) |
|||
(define (extend lst n) ; extends list to length n, by adding "" to end |
|||
(append lst (make-list (- n (length lst)) ""))) |
|||
(define (align-word word width) ; align single word to fit width |
|||
(case alignment |
|||
((left) (string-pad-right word width)) |
|||
((right) (string-pad word width)) |
|||
((center) (let ((rem (- width (string-length word)))) |
|||
(string-pad-right (string-pad word (- width (truncate (/ rem 2)))) |
|||
width))))) |
|||
; |
|||
(display alignment) (newline) |
|||
(let* ((text-list (map split text)) |
|||
(max-line-len (fold (lambda (text val) (max (length text) val)) 0 text-list)) |
|||
(text-lines (map (lambda (line) (extend line max-line-len)) text-list)) |
|||
(min-col-widths (map (lambda (col) |
|||
(fold (lambda (line val) |
|||
(max (string-length (list-ref line col)) |
|||
val)) |
|||
0 |
|||
text-lines)) |
|||
(iota max-line-len)))) |
|||
(map (lambda (line) |
|||
(map (lambda (word width) |
|||
(display (string-append (align-word word width) |
|||
" "))) |
|||
line min-col-widths) |
|||
(newline)) |
|||
text-lines)) |
|||
(newline)) |
|||
;; show example |
|||
(define *example* |
|||
'("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 *example* 'left) |
|||
(align-columns *example* 'center) |
|||
(align-columns *example* 'right) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|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). |
|||
<syntaxhighlight lang="sed"> |
|||
#!/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 |
|||
} |
|||
</syntaxhighlight> |
|||
Example: |
|||
<pre> |
|||
$ 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. |
|||
</pre> |
|||
=={{header|Seed7}}== |
|||
<syntaxhighlight lang="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;</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|SETL}}== |
|||
<syntaxhighlight lang="setl">program align; |
|||
magic := false; $ turn off regexp matching in GNU SETL |
|||
read_file; |
|||
ncols := max/[#line : line in lines]; |
|||
sizes := [1+max/[#(line(col) ? "") : line in lines] : col in [1..ncols]]; |
|||
loop for line in lines do |
|||
print(+/[align(line(col), sizes(col)) : col in [1..#line]]); |
|||
end loop; |
|||
read_file:: |
|||
f := open(command_line(1), "r"); |
|||
lines := []; |
|||
loop doing geta(f, line); while line /= om do |
|||
lines with:= split(line, "$"); |
|||
end loop; |
|||
close(f); |
|||
proc align(s, n); |
|||
case command_line(2) of |
|||
("r"): return lpad(s, n); |
|||
("l"): return rpad(s, n); |
|||
("c"): return center(s, n); |
|||
end case; |
|||
end proc; |
|||
proc center(s, n); |
|||
padding := n - #s; |
|||
l := " " * ceil(padding/2); |
|||
r := " " * floor(padding/2); |
|||
return l + s + r; |
|||
end proc; |
|||
end program;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>$ setl align.setl test.txt 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. |
|||
$ setl align.setl test.txt 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. |
|||
$ setl align.setl test.txt c |
|||
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.</pre> |
|||
=={{header|Shiny}}== |
|||
<syntaxhighlight lang="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'</syntaxhighlight> |
|||
<pre>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.</pre> |
|||
=={{header|Sidef}}== |
|||
<syntaxhighlight lang="ruby">class Format(text, width) { |
|||
method align(j) { |
|||
text.map { |row| |
|||
row.range.map { |i| |
|||
'%-*s ' % (width[i], |
|||
'%*s' % (row[i].len + (width[i]-row[i].len * j/2), row[i])); |
|||
}.join(""); |
|||
}.join("\n") + "\n"; |
|||
} |
|||
} |
|||
func Formatter(text) { |
|||
var textArr = []; |
|||
var widthArr = []; |
|||
text.each_line { |
|||
var words = .split('$'); |
|||
textArr.append(words); |
|||
words.each_kv { |i, word| |
|||
if (i == widthArr.len) { |
|||
widthArr.append(word.len); |
|||
} |
|||
elsif (word.len > widthArr[i]) { |
|||
widthArr[i] = word.len; |
|||
} |
|||
} |
|||
} |
|||
return 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); |
|||
say f.align(left); |
|||
say f.align(middle); |
|||
say f.align(right);</syntaxhighlight> |
|||
=={{Header|Smalltalk}}== |
|||
the following works with Smalltalk/X, but should also in other dialects (may have to add "centerPadded" to the String class). |
|||
{{works with |Smalltalk/X }} |
|||
<syntaxhighlight lang="smalltalk">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. |
|||
'. |
|||
printSep := |
|||
[:colLengths | |
|||
Stdout nextPut:$+. |
|||
colLengths do:[:len | Stdout next:len put:$-; nextPut:$+ ]. |
|||
Stdout cr. |
|||
]. |
|||
printRows := |
|||
[:text :box :justifyEach | |
|||
lines := StringCollection fromString:text. |
|||
rowSet := lines collect:[:line | line splitBy:$$ ]. |
|||
maxNumCols := (rowSet collect:[:row | row size]) max. |
|||
maxLengths := rowSet |
|||
inject:(Array new:maxNumCols withAll:0) |
|||
into:[:maxesSoFar :row| |
|||
maxesSoFar |
|||
with:(row paddedTo:maxNumCols with:'') |
|||
collect:[:maxLen :col | maxLen max: col size]]. |
|||
rowSet do:[:row | |
|||
|first| |
|||
box ifTrue:[ printSep value:maxLengths ]. |
|||
first := true. |
|||
(box ifTrue:[row paddedTo:maxLengths size with:''] ifFalse:[row]) |
|||
with: (box ifTrue:[maxLengths] ifFalse:[maxLengths to:row size]) |
|||
do:[:col :len | |
|||
first ifTrue:[ box ifTrue:[Stdout nextPutAll:'|']. first := false.]. |
|||
Stdout print:(justifyEach value:col value:len). |
|||
Stdout nextPutAll:(box ifTrue:'|' ifFalse:' ') |
|||
]. |
|||
Stdout cr. |
|||
]. |
|||
box ifTrue:[ printSep value:maxLengths ]. |
|||
]. |
|||
printRightJustified := |
|||
[:text :box | printRows value:text value:box value:[:col :len | (col leftPaddedTo:len)]]. |
|||
printLeftJustified := |
|||
[:text :box | printRows value:text value:box value:[:col :len | (col paddedTo:len)]]. |
|||
printCentered := |
|||
[:text :box | printRows value:text value:box value:[:col :len | col centerPaddedTo:len]]. |
|||
Stdout printCR:'Left justified:'. |
|||
printLeftJustified value:text value:false. |
|||
Stdout cr; printCR:'Right justified:'. |
|||
printRightJustified value:text value:false. |
|||
Stdout cr; printCR:'Centered:'. |
|||
printCentered value:text value:false. |
|||
Stdout cr; printCR:'Left justified with box:'. |
|||
printLeftJustified value:text value:true. |
|||
Stdout cr; printCR:'Right justified with box:'. |
|||
printRightJustified value:text value:true. |
|||
Stdout cr; printCR:'Centered with box:'. |
|||
printCentered value:text value:true.</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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. |
|||
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. |
|||
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. |
|||
Left justified with box: |
|||
+----------+----------+----------+------+------+---------+----------+--------+-------+-------+------+----+ |
|||
|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 with box: |
|||
+----------+----------+----------+------+------+---------+----------+--------+-------+-------+------+----+ |
|||
| 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 with box: |
|||
+----------+----------+----------+------+------+---------+----------+--------+-------+-------+------+----+ |
|||
| 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.| | | | |
|||
+----------+----------+----------+------+------+---------+----------+--------+-------+-------+------+----+</pre> |
|||
=={{header|Snobol}}== |
|||
{{works with|Snobol|4}} |
|||
<syntaxhighlight lang="snobol">* Since we don't know how much text we'll be reading in, |
|||
* we store the words and field widths in tables |
|||
Words = TABLE() |
|||
Widths = TABLE() |
|||
* Match text from start of string to the first dollar sign |
|||
WordPat = POS(0) BREAK('$') . Word LEN(1) REM . Rest |
|||
* We output the results aligned three different ways; these are the |
|||
* labels for those sections of output: |
|||
Labels = ARRAY(3) |
|||
Labels<1> = "Left-justified" |
|||
Labels<2> = "Right-justified" |
|||
Labels<3> = "Centered" |
|||
* There are built-in functions for left- and right- justification, |
|||
* but not necessarily one for centering (depending on |
|||
* implementation). So we define one. |
|||
DEFINE('CPAD(Word,Width)Z,Left') :(END_CPAD) |
|||
CPAD Z = SIZE(Word) |
|||
Left = Z + (Width - Z) / 2 |
|||
CPAD = RPAD(LPAD(Word, Left), Width) :(RETURN) |
|||
END_CPAD |
|||
* Read in our text a line at a time and split into words on '$' |
|||
InLineLoop Line = INPUT :F(DoneReading) |
|||
LineCount = LineCount + 1 |
|||
Column = 0 |
|||
InWordLoop Column = Column + 1 |
|||
* Separate Line into Word, Line=Rest at first dollar sign |
|||
Line WordPat = Rest :S(CheckMax) |
|||
* If there was no '$', the whole line is the next word |
|||
Word = Line |
|||
Line = |
|||
* Keep track of the largest number of columns on any line |
|||
CheckMax LE(Column, MaxColumn) :S(StoreWord) |
|||
MaxColumn = Column |
|||
StoreWord Words<LineCount ',' Column> = Word |
|||
* And the size of the longest word in each column |
|||
GT(SIZE(Word),Widths<Column>) :F(NoNewMaxWidth) |
|||
Widths<Column> = SIZE(Word) |
|||
* Loop if the line isn't empty yet |
|||
NoNewMaxWidth GT(Size(Line)) :S(InWordLoop) F(InLineLoop) |
|||
DoneReading |
|||
* Now we print the results out in the three justification styles |
|||
Style = 0 |
|||
StyleLoop Style = Style + 1 |
|||
GT(Style, 3) :S(END) |
|||
OUTPUT = |
|||
OUTPUT = Labels<Style> ':' |
|||
I = 0 |
|||
OutLineLoop I = I + 1 |
|||
GT(I, LineCount) :S(StyleLoop) |
|||
* Build up the output line by fields starting with the null string |
|||
Line = |
|||
J = 0 |
|||
OutWordLoop J = J + 1 |
|||
GT(J, MaxColumn) :S(PrintLine) |
|||
Word = Words<I ',' J> |
|||
GT(SIZE(Word)) :F(PrintLine) |
|||
* Place the word within the column according to the pass we're on |
|||
EQ(Style, 1) :F(NotLeft) |
|||
* Left-justified |
|||
Word = RPAD(Word, Widths<J>) :(AddWord) |
|||
NotLeft EQ(Style, 2) :F(NotRight) |
|||
* Right-justified |
|||
Word = LPAD(Word, Widths<J>) :(AddWord) |
|||
* Centered |
|||
NotRight Word = CPAD(Word, Widths<J>) |
|||
* Add word to line and loop |
|||
AddWord Line = Line GT(SIZE(Line)) ' ' |
|||
Line = Line Word :(OutWordLoop) |
|||
* Print the line |
|||
PrintLine OUTPUT = Line :(OutLineLoop) |
|||
END |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
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. |
|||
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. |
|||
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.</pre> |
|||
=={{header|SparForte}}== |
|||
As a structured script. |
|||
<syntaxhighlight lang="ada">#!/usr/local/bin/spar |
|||
pragma annotate( summary, "aligncols" ) |
|||
@( description, "Given a text file of many lines, where fields within a line are delineated ") |
|||
@( description, "by a single 'dollar' character, write a program that aligns each column of" ) |
|||
@( description, "fields by ensuring that words in each column are separated by at least one" ) |
|||
@( description, "space. Further, allow for each word in a column to be either left justified," ) |
|||
@( description, "right justified, or center justified within its column. " ) |
|||
@( description, "A modified version of the Ada solution from Rosetta Code" ) |
|||
@( category, "tutorials" ) |
|||
@( author, "Ken O. Burtch" ) |
|||
@( see_also, "http://rosettacode.org/wiki/Align_columns" ); |
|||
pragma license( unrestricted ); |
|||
pragma software_model( nonstandard ); |
|||
pragma restriction( no_external_commands ); |
|||
procedure aligncols is |
|||
Text : constant string := |
|||
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$" & ASCII.NUL & |
|||
"are$delineated$by$a$single$'dollar'$character,$write$a$program" & ASCII.NUL & |
|||
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" & ASCII.NUL & |
|||
"column$are$separated$by$at$least$one$space." & ASCII.NUL & |
|||
"Further,$allow$for$each$word$in$a$column$to$be$either$left$" & ASCII.NUL & |
|||
"justified,$right$justified,$or$center$justified$within$its$column." & ASCII.NUL; |
|||
File : file_type; |
|||
Width : array(1..1000) of natural; |
|||
ch : character; |
|||
Column : positive := 1; |
|||
Start : positive := 1; |
|||
type Alignment is ( Left, Center, Right ); |
|||
s : string; |
|||
padding : natural; |
|||
begin |
|||
-- Zero Widths |
|||
for I in arrays.first( Width )..arrays.last( Width ) loop |
|||
Width(I) := 0; |
|||
end loop; |
|||
-- Determining the widths of columns |
|||
for I in 1..strings.length(Text) loop |
|||
ch := strings.element( Text, I ); |
|||
case ch is |
|||
when '$' | ASCII.NUL => |
|||
Width (Column) := numerics.max(Width (Column), I - Start + 1); |
|||
Start := I + 1; |
|||
if strings.element( Text, I ) = ASCII.NUL then |
|||
Column := 1; |
|||
else |
|||
Column := @+1; |
|||
end if; |
|||
when others => |
|||
null; |
|||
end case; |
|||
end loop; |
|||
create( File, out_file, "columned.txt" ); |
|||
-- Formatting |
|||
for Align in Left..Right loop |
|||
Column := 1; |
|||
Start := 1; |
|||
for I in 1..strings.length(Text) loop |
|||
ch := strings.element( Text, I ); |
|||
case ch is |
|||
when '$' | ASCII.NUL => |
|||
s := strings.slice( Text, Start, I-1 ); |
|||
padding := (Width( Column ) - strings.length(s)); |
|||
case Align is |
|||
when Left => |
|||
s := @ & (padding * ' '); |
|||
when Center => |
|||
declare |
|||
left_padding : constant natural := padding/2; |
|||
right_padding : constant natural := padding - left_padding; |
|||
begin |
|||
s := (left_padding * ' ') & @ & (right_padding * ' '); |
|||
end; |
|||
when Right => |
|||
s := (padding * ' ') & @; |
|||
when others => |
|||
null; |
|||
end case; |
|||
put( File, s ); |
|||
Start := I+1; |
|||
if ch = ASCII.NUL then |
|||
new_line( File ); |
|||
Column := 1; |
|||
else |
|||
Column := @+1; |
|||
end if; |
|||
when others => |
|||
null; |
|||
end case; |
|||
end loop; |
|||
new_line( File ); |
|||
end loop; |
|||
close( File ); |
|||
end aligncols;</syntaxhighlight> |
|||
=={{header|Standard ML}}== |
|||
<syntaxhighlight lang="sml">fun curry f x y = f (x, y) |
|||
fun uncurry f (x, y) = f x y |
|||
fun maxWidths ([], widths) = widths |
|||
| maxWidths (strings, []) = map size strings |
|||
| maxWidths (s :: ss, w :: ws) = Int.max (size s, w) :: maxWidths (ss, ws) |
|||
val alignL = uncurry (StringCvt.padRight #" ") |
|||
and alignR = uncurry (StringCvt.padLeft #" ") |
|||
fun alignC (w, s) = |
|||
alignL (w, alignR ((w + size s) div 2, s)) |
|||
fun formatTable tab = |
|||
let |
|||
val columnWidths = foldl maxWidths [] tab |
|||
in |
|||
fn f => String.concatWith "\n" |
|||
(map (String.concatWith " " o curry (ListPair.map f) columnWidths) tab) |
|||
end |
|||
val readTable = |
|||
map (String.fields (curry op= #"$")) |
|||
o String.tokens (curry op= #"\n") |
|||
o TextIO.inputAll |
|||
(* test stdin with all alignments *) |
|||
val () = print (String.concatWith "\n\n" |
|||
(map (formatTable (readTable TextIO.stdIn)) [alignL, alignC, alignR]) ^ "\n")</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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. |
|||
</pre> |
|||
=={{header|Swift}}== |
|||
{{trans|Rust}} |
|||
<syntaxhighlight lang="swift">import Foundation |
|||
extension String { |
|||
func dropLastIf(_ char: Character) -> String { |
|||
if last == char { |
|||
return String(dropLast()) |
|||
} else { |
|||
return self |
|||
} |
|||
} |
|||
} |
|||
enum Align { |
|||
case left, center, right |
|||
} |
|||
func getLines(input: String) -> [String] { |
|||
input |
|||
.components(separatedBy: "\n") |
|||
.map({ $0.replacingOccurrences(of: " ", with: "").dropLastIf("$") }) |
|||
} |
|||
func getColWidths(from: String) -> [Int] { |
|||
var widths = [Int]() |
|||
let lines = getLines(input: from) |
|||
for line in lines { |
|||
let lens = line.components(separatedBy: "$").map({ $0.count }) |
|||
for (i, len) in lens.enumerated() { |
|||
if i < widths.count { |
|||
widths[i] = max(widths[i], len) |
|||
} else { |
|||
widths.append(len) |
|||
} |
|||
} |
|||
} |
|||
return widths |
|||
} |
|||
func alignCols(input: String, align: Align = .left) -> String { |
|||
let widths = getColWidths(from: input) |
|||
let lines = getLines(input: input) |
|||
var res = "" |
|||
for line in lines { |
|||
for (str, width) in zip(line.components(separatedBy: "$"), widths) { |
|||
let blanks = width - str.count |
|||
let pre: Int, post: Int |
|||
switch align { |
|||
case .left: |
|||
(pre, post) = (0, blanks) |
|||
case .center: |
|||
(pre, post) = (blanks / 2, (blanks + 1) / 2) |
|||
case .right: |
|||
(pre, post) = (blanks, 0) |
|||
} |
|||
res += String(repeating: " ", count: pre) |
|||
res += str |
|||
res += String(repeating: " ", count: post) |
|||
res += " " |
|||
} |
|||
res += "\n" |
|||
} |
|||
return res |
|||
} |
|||
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. |
|||
""" |
|||
print(alignCols(input: input)) |
|||
print() |
|||
print(alignCols(input: input, align: .center)) |
|||
print() |
|||
print(alignCols(input: input, align: .right))</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height: 25em; overflow: scroll">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. </pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
< |
<syntaxhighlight lang="tcl">package require Tcl 8.5 |
||
set text {Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
set text {Given$a$text$file$of$many$lines,$where$fields$within$a$line$ |
||
Line 1,144: | Line 9,818: | ||
} |
} |
||
puts "" |
puts "" |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre>Given a text file of many lines, where fields within a line |
<pre>Given a text file of many lines, where fields within a line |
||
are delineated by a single 'dollar' character, write a program |
are delineated by a single 'dollar' character, write a program |
||
Line 1,167: | Line 9,841: | ||
justified, right justified, or center justified within its column.</pre> |
justified, right justified, or center justified within its column.</pre> |
||
=={{header|Transd}}== |
|||
Transd has built-in support for "left" and "right" formatting, but not "centered", which added quite a bit of code. |
|||
<syntaxhighlight lang="scheme">#lang transd |
|||
MainModule : { |
|||
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.", |
|||
tabl: Table(), |
|||
n: 0, |
|||
colWidths: Vector<Int>(), |
|||
print: (λ centered Bool(false) |
|||
(for n in Seq(0 (num-rows tabl)) do |
|||
(with row (get-row tabl n) |
|||
(for m in Seq(0 (num-cols tabl)) do |
|||
(with wid (+ 1.0 (get colWidths @idx)) |
|||
word (get row m) wl 0.0 lef 0 |
|||
(if centered (= wl (size String(word))) (= lef (/ (- wid wl) 2.0)) |
|||
(textout width: lef "" width: wl word width: (- wid (+ wl lef)) "") |
|||
else |
|||
(textout width: wid (get row m))))) |
|||
(lout "")) |
|||
) |
|||
), |
|||
_start: (λ |
|||
(load-table tabl txt fieldSep: "$" :emptyEls) |
|||
(for i in Seq(0 (num-cols tabl)) do (= n 0) |
|||
(tsd-query tabl |
|||
reduce: [i] |
|||
as: [[String()]] |
|||
using: (λ (set n (max (size (get @row 0)) n)))) |
|||
(append colWidths n) |
|||
) |
|||
(textout :right "") (print) |
|||
(lout :left "") (print) |
|||
(lout "") (print true) |
|||
) |
|||
}</syntaxhighlight>{{out}} |
|||
<pre> |
|||
Given a text file of many lines, where fields within a line |
|||
are delineated by a single 'dollar' character, write a program a line |
|||
that aligns each column of fields by ensuring that words in each |
|||
column are separated by at least one space. that words in each |
|||
Further, allow for each word in a column to be either left |
|||
justified, right justified, or center justified within its column. be either left |
|||
Given a text file of many lines, where fields within a line |
|||
are delineated by a single 'dollar' character, write a program a line |
|||
that aligns each column of fields by ensuring that words in each |
|||
column are separated by at least one space. that words in each |
|||
Further, allow for each word in a column to be either left |
|||
justified, right justified, or center justified within its column. be either left |
|||
Given a text file of many lines, where fields within a line |
|||
are delineated by a single 'dollar' character, write a program a line |
|||
that aligns each column of fields by ensuring that words in each |
|||
column are separated by at least one space. that words in each |
|||
Further, allow for each word in a column to be either left |
|||
justified, right justified, or center justified within its column. be either left |
|||
</pre> |
|||
=={{header|TSE SAL}}== |
|||
<syntaxhighlight lang="tsesal"> |
|||
INTEGER PROC FNBlockChangeColumnAlignLeftB( INTEGER columnTotalI, INTEGER spaceTotalI, INTEGER buffer1I ) |
|||
INTEGER B = FALSE |
|||
INTEGER downB = TRUE |
|||
INTEGER minI = 1 |
|||
INTEGER I = 0 |
|||
INTEGER J = 0 |
|||
INTEGER K = 0 |
|||
INTEGER L = 0 |
|||
INTEGER buffer2I = 0 |
|||
STRING s[255] = "" |
|||
INTEGER wordRightB = FALSE |
|||
STRING s1[255] = Query( WordSet ) |
|||
IF ( NOT ( IsBlockInCurrFile() ) ) Warn( "Please mark a block" ) B = FALSE RETURN( B ) ENDIF // return from the current procedure if no block is marked |
|||
Set( BREAK, ON ) |
|||
PushPosition() |
|||
PushBlock() |
|||
Set( WordSet, ChrSet( "a-zA-Z0-9_,." ) ) |
|||
PushPosition() |
|||
buffer2I = CreateTempBuffer() |
|||
PopPosition() |
|||
PushPosition() |
|||
PushBlock() |
|||
DO 100 TIMES |
|||
AddLine( "", buffer2I ) |
|||
ENDDO |
|||
PopBlock() |
|||
PopPosition() |
|||
GotoBlockBegin() |
|||
I = minI - 1 |
|||
WHILE ( ( IsCursorInBlock() ) AND ( downB ) ) |
|||
IF NOT LFind( "^$", "cgx" ) |
|||
BegLine() |
|||
REPEAT |
|||
s = GetWord() |
|||
IF NOT ( s == "" ) |
|||
s = Trim( s ) |
|||
I = I + 1 |
|||
IF ( I > columnTotalI ) |
|||
I = minI |
|||
ENDIF |
|||
J = Length( s ) |
|||
PushPosition() |
|||
PushBlock() |
|||
GotoBufferId( buffer2I ) |
|||
GotoLine( I ) |
|||
// |
|||
IF ( CurrLineLen() == 0 ) |
|||
BegLine() |
|||
InsertText( Format( Str( J ), " " ), _INSERT_ ) |
|||
ELSE |
|||
K = Val( Trim( GetText( 1, MAXSTRINGLEN ) ) ) |
|||
IF ( J > K ) |
|||
BegLine() |
|||
DelToEol() |
|||
BegLine() |
|||
InsertText( Str( J ), _INSERT_ ) |
|||
ENDIF |
|||
ENDIF |
|||
PopBlock() |
|||
PopPosition() |
|||
wordRightB = WordRight() |
|||
ENDIF |
|||
UNTIL ( s == "" ) OR ( NOT wordRightB ) |
|||
ENDIF |
|||
downB = Down() |
|||
ENDWHILE |
|||
GotoBlockBegin() |
|||
I = minI - 1 |
|||
L = 1 |
|||
K = 1 |
|||
WHILE ( ( IsCursorInBlock() ) AND ( downB ) ) |
|||
IF NOT LFind( "^$", "cgx" ) |
|||
BegLine() |
|||
REPEAT |
|||
B = FALSE |
|||
s = GetWord() |
|||
IF NOT ( s == "" ) |
|||
s = Trim( s ) |
|||
I = I + 1 |
|||
IF ( I > columnTotalI ) |
|||
I = minI |
|||
K = 1 |
|||
L = L + 1 |
|||
ENDIF |
|||
// |
|||
PushPosition() |
|||
PushBlock() |
|||
GotoBufferId( buffer2I ) |
|||
GotoLine( I ) |
|||
J = Val( Trim( GetText( 1, MAXSTRINGLEN ) ) ) |
|||
PopPosition() |
|||
PopBlock() |
|||
PushPosition() |
|||
PushBlock() |
|||
GotoBufferId( buffer1I ) |
|||
GotoLine( L ) |
|||
GotoColumn( K ) |
|||
InsertText( s, _INSERT_ ) |
|||
K = K + J + spaceTotalI |
|||
PopBlock() |
|||
PopPosition() |
|||
wordRightB = WordRight() |
|||
ENDIF |
|||
UNTIL ( s == "" ) OR ( NOT wordRightB ) |
|||
ENDIF |
|||
AddLine( "", buffer1I ) |
|||
downB = Down() |
|||
ENDWHILE |
|||
OneWindow() |
|||
VWindow() |
|||
GotoWindow( 1 ) |
|||
GotoBufferId( buffer2I ) |
|||
GotoWindow( 2 ) |
|||
GotoBufferId( buffer1I ) |
|||
B = TRUE |
|||
Set( WordSet, s1 ) |
|||
PopPosition() |
|||
PopBlock() |
|||
RETURN( B ) |
|||
END |
|||
// |
|||
PROC Main() |
|||
STRING s1[255] = "12" // change this |
|||
STRING s2[255] = "2" // change this |
|||
INTEGER bufferI = 0 |
|||
PushPosition() |
|||
bufferI = CreateTempBuffer() |
|||
PopPosition() |
|||
IF ( NOT ( Ask( "block: change: column: align: left: columnTotalI = ", s1, _EDIT_HISTORY_ ) ) AND ( Length( s1 ) > 0 ) ) RETURN() ENDIF |
|||
IF ( NOT ( Ask( "block: change: column: align: left: spaceTotalI = ", s2, _EDIT_HISTORY_ ) ) AND ( Length( s2 ) > 0 ) ) RETURN() ENDIF |
|||
Message( FNBlockChangeColumnAlignLeftB( Val( s1 ), Val( s2 ), bufferI ) ) // gives e.g. TRUE |
|||
GotoBufferId( bufferI ) |
|||
END |
|||
</syntaxhighlight> |
|||
{{out}} <pre> |
|||
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. |
|||
</pre> |
|||
=={{header|TUSCRIPT}}== |
|||
<syntaxhighlight lang="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) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. $ $ $ |
|||
</pre> |
|||
=={{header|TXR}}== |
|||
<syntaxhighlight lang="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)</syntaxhighlight> |
|||
<pre>$ 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.</pre> |
|||
=={{header|Uiua}}== |
|||
[https://www.uiua.org/pad?src=0_12_0-dev_1__IyBTcGxpdCB0aGUgdGV4dCBhdCAkIGFuZCB0aGVuIGp1c3RpZnkgZWFjaCB3b3JkIDMgd2F5cwoKTiDihpAgeyJHaXZlbiRhJHRleHQkZmlsZSRvZiRtYW55JGxpbmVzLCR3aGVyZSRmaWVsZHMkd2l0aGluJGEkbGluZSQiCiAgICAgImFyZSRkZWxpbmVhdGVkJGJ5JGEkc2luZ2xlJCdkb2xsYXInJGNoYXJhY3Rlciwkd3JpdGUkYSRwcm9ncmFtIgogICAgICJ0aGF0JGFsaWducyRlYWNoJGNvbHVtbiRvZiRmaWVsZHMkYnkkZW5zdXJpbmckdGhhdCR3b3JkcyRpbiRlYWNoJCIKICAgICAiY29sdW1uJGFyZSRzZXBhcmF0ZWQkYnkkYXQkbGVhc3Qkb25lJHNwYWNlLiIKICAgICAiRnVydGhlciwkYWxsb3ckZm9yJGVhY2gkd29yZCRpbiRhJGNvbHVtbiR0byRiZSRlaXRoZXIkbGVmdCQiCiAgICAgImp1c3RpZmllZCwkcmlnaHQkanVzdGlmaWVkLCRvciRjZW50ZXIkanVzdGlmaWVkJHdpdGhpbiRpdHMkY29sdW1uLiJ9CkxzIOKGkCDiiaHijZoo4oqc4pah4omgQCQuKSAgICAgICAgICAgICMgR2V0IHRoZSB3b3JkIGFycmF5cy4KUGFkQyDihpAg4oa7OuKKmSjijIrDtzItKeKKgyjirJpAIOKGmXziipnip7spICMgUGFkIGNlbnRyZS4KUGFkISDihpAg4omhL-KXh-KKguKNieKJoeKJoeKNml4hICAgICAgICAgICMgQXBwbHkgYSBwYWRkaW5nIGZ1bmN0aW9uIHRvIGFsbC4KUHJlcCDihpAgKAogIOKJoeKXh-KsmiIi4oaZL-KGpeKJoeKXh-Knuy4gICMgUGFkIGVhY2ggcm93IHRvIHNhbWUgbGVuZ3RoLgogICsx4omh4peHKC_ihqXiiaHil4fip7spLuKNiSAjIEZpbmQgcmVxdWlyZWQgbGVuZ3RoIGZvciBlYWNoIGNvbHVtbi4KKQriiaEoJnAvJCJfXG5fIilb4oqDKFBhZCHirJpAIOKGmXxQYWQhKOKsmkAg4oaZwq8pfFBhZCFQYWRDKV0gUHJlcCBMcyBOCg== Run it in Uiua Pad!] |
|||
<syntaxhighlight lang="uiua"> |
|||
# Split the text at $ and then justify each word 3 ways |
|||
N ← {"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."} |
|||
Ls ← ≡⍚(⊜□≠@$.) # Get the word arrays. |
|||
PadC ← ↻:⊙(⌊÷2-)⊃(⬚@ ↙|⊙⧻) # Pad centre. |
|||
Pad! ← ≡/◇⊂⍉≡≡⍚^! # Apply a padding function to all. |
|||
Prep ← ( |
|||
≡◇⬚""↙/↥≡◇⧻. # Pad each row to same length. |
|||
+1≡◇(/↥≡◇⧻).⍉ # Find required length for each column. |
|||
) |
|||
≡(&p/$"_\n_")[⊃(Pad!⬚@ ↙|Pad!(⬚@ ↙¯)|Pad!PadC)] Prep Ls N |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
As expected, follow Uiua Pad link to confirm :-). |
|||
=={{header|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.'') |
|||
<syntaxhighlight lang="bash"> |
|||
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 |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<syntaxhighlight lang="sh"> |
|||
$ ./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. |
|||
</syntaxhighlight> |
|||
The centered output will be added later, when I've more time. '' I did this in about 10 minutes.'' |
|||
=== Using <tt>column(1)</tt> === |
|||
Note that the left-justified case can be handled trivially by the <tt>column</tt> command, which ships with modern Linux and macOS systems: |
|||
<syntaxhighlight lang="sh">tr '$' ' ' | column -t</syntaxhighlight> |
|||
{{Out}} |
|||
<pre>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.</pre> |
|||
=={{header|Ursala}}== |
=={{header|Ursala}}== |
||
The algorithm is to lex the text to a list of lists of strings assuming $ as a separator, |
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, |
then pad the lists out to the length of the maximum length list, transpose, |
||
do the same with each column, and transpose again. |
do the same with each column, and transpose again. |
||
nothing further but concatenation is needed. |
For left justification, nothing further but concatenation is needed. |
||
of trailing blanks is moved to the beginning, |
For right justification, each word's string of trailing blanks is moved to the beginning, |
||
trailing blanks are divided equally between the beginning and end of each word. |
and for center justification, the trailing blanks are divided equally between the beginning and end of each word. |
||
<syntaxhighlight lang="ursala">#import std |
|||
<lang Ursala> |
|||
#import std |
|||
text = |
text = |
||
Line 1,195: | Line 10,264: | ||
#show+ |
#show+ |
||
main = mat0 <.just_left,just_center,just_right> text |
main = mat0 <.just_left,just_center,just_right> text</syntaxhighlight> |
||
{{out}} |
|||
</lang> |
|||
output: |
|||
<pre style="height:17ex;overflow:scroll"> |
<pre style="height:17ex;overflow:scroll"> |
||
Given a text file of many lines, where fields within a line |
Given a text file of many lines, where fields within a line |
||
Line 1,219: | Line 10,287: | ||
Further, allow for each word in a column to be either left |
Further, allow for each word in a column to be either left |
||
justified, right justified, or center justified within its column. |
justified, right justified, or center justified within its column. |
||
</pre> |
|||
=={{header|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. |
|||
<syntaxhighlight lang="vb"> |
|||
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 |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|VBScript}}== |
|||
{{trans|Rexx}} |
|||
<syntaxhighlight lang="vb">' Align columns - RC - VBScript |
|||
Const nr=16, nc=16 |
|||
ReDim d(nc),t(nr), wor(nr,nc) |
|||
i=i+1: t(i) = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" |
|||
i=i+1: t(i) = "are$delineated$by$a$single$'dollar'$character,$write$a$program" |
|||
i=i+1: t(i) = "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" |
|||
i=i+1: t(i) = "column$are$separated$by$at$least$one$space." |
|||
i=i+1: t(i) = "Further,$allow$for$each$word$in$a$column$To$be$either$left$" |
|||
i=i+1: t(i) = "justified,$right$justified,$or$center$justified$within$its$column." |
|||
For r=1 to nr |
|||
If t(r)="" Then Exit For |
|||
w=xRTrim(t(r),"$") |
|||
m=Split(w,"$") |
|||
For c=1 To UBound(m)+1 |
|||
wor(r,c)=m(c-1) |
|||
If Len(wor(r,c))>d(c) Then d(c)=Len(wor(r,c)) |
|||
Next 'c |
|||
If c>cols Then cols=c |
|||
Next 'r |
|||
rows=r-1 |
|||
tt=Array("Left","Right","Center") |
|||
For n=1 To 3 |
|||
Wscript.Echo |
|||
Wscript.Echo "*****" & tt(n-1) & "*****" |
|||
For r=1 To rows |
|||
w="" |
|||
For c=1 To cols |
|||
x=wor(r,c): s=Space(d(c)) |
|||
Select Case n |
|||
Case 1: w=w &" "& Left (x & s,d(c)) |
|||
Case 2: w=w &" "& Right (s & x,d(c)) |
|||
Case 3: w=w &" "& xCentre(x,d(c)," ") |
|||
End Select 'n |
|||
Next 'c |
|||
Wscript.Echo Mid(w,2) |
|||
Next 'r |
|||
Next 'n |
|||
Function xCentre(c, n, Pad) |
|||
Dim j |
|||
If n > Len(c) Then |
|||
j = (n - Len(c)) \ 2 |
|||
If (n - Len(c)) Mod 2 <> 0 Then j = j + 1 |
|||
xCentre = Mid(String(j, Pad) & c & String(j, Pad), 1, n) |
|||
Else |
|||
xCentre = c |
|||
End If |
|||
End Function 'xCentre |
|||
Function xRTrim(c, Pad) |
|||
Dim i2, l, cc |
|||
cc = "": l = Len(c) |
|||
If l > 0 Then |
|||
i2 = l |
|||
Do While (Mid(c, i2, 1) = Pad And i2 > 1) |
|||
i2 = i2 - 1 |
|||
Loop |
|||
If i2 = 1 And Mid(c, i2, 1) = Pad Then i2 = 0 |
|||
If i2 > 0 Then cc = Mid(c, 1, i2) |
|||
End If |
|||
xRTrim = cc |
|||
End Function 'xRTrim |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
*****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. |
|||
*****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. |
|||
</pre> |
</pre> |
||
=={{header|Vedit macro language}}== |
=={{header|Vedit macro language}}== |
||
This implementation converts the file currently being edited. The file can then be saved with different filename if required. |
This implementation converts the file currently being edited. The file can then be saved with different filename if required. |
||
<syntaxhighlight lang="vedit">RS(10, "$") // Field separator |
|||
<pre> |
|||
RS(10, "$") // Field separator |
|||
#11 = 1 // Align: 1 = left, 2 = center, 3 = right |
#11 = 1 // Align: 1 = left, 2 = center, 3 = right |
||
Line 1,263: | Line 10,514: | ||
} |
} |
||
Line(1, ERRBREAK) |
Line(1, ERRBREAK) |
||
}</syntaxhighlight> |
|||
} |
|||
</pre> |
|||
{{out}} |
|||
Example output: |
|||
<pre>-- Left: |
|||
<pre style="height:17ex;overflow:scroll"> |
|||
-- Left: |
|||
Given a text file of many lines, where fields within a line |
Given a text file of many lines, where fields within a line |
||
are delineated by a single 'dollar' character, write a program |
are delineated by a single 'dollar' character, write a program |
||
Line 1,290: | Line 10,539: | ||
column are separated by at least one space. |
column are separated by at least one space. |
||
Further, allow for each word in a column to be either left |
Further, allow for each word in a column to be either left |
||
justified, right justified, or center justified within its column. |
justified, right justified, or center justified within its column.</pre> |
||
=={{header|Visual Basic}}== |
|||
<syntaxhighlight lang="vb">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</syntaxhighlight> |
|||
Usage:<syntaxhighlight lang="vb">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</syntaxhighlight> |
|||
{{out}} |
|||
<pre>-- 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.</pre> |
|||
=={{header|Visual Basic .NET}}== |
|||
<syntaxhighlight lang="vb">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</syntaxhighlight> |
|||
{{out}} |
|||
<pre>-- 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.</pre> |
|||
=={{header|V (Vlang)}}== |
|||
Currently (5/2022) V (Vlang) uses string interpolation so `$` have to be escaped. Variables in formatting aren't currently allowed, and if they were only right/left are currently valid options |
|||
<syntaxhighlight lang="v (vlang)"> |
|||
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." |
|||
struct Formatter { |
|||
mut: |
|||
text [][]string |
|||
width []int |
|||
} |
|||
fn new_formatter(text string) Formatter { |
|||
mut f := Formatter{} |
|||
for line in text.split_into_lines() { |
|||
mut words := line.split("\$") |
|||
for words[words.len-1] == "" { |
|||
words = words[..words.len-1] |
|||
} |
|||
f.text << words |
|||
for i, word in words { |
|||
if i == f.width.len { |
|||
f.width << word.len |
|||
} else if word.len > f.width[i] { |
|||
f.width[i] = word.len |
|||
} |
|||
} |
|||
} |
|||
return f |
|||
} |
|||
enum Justify { |
|||
left = 0 |
|||
middle |
|||
right |
|||
} |
|||
fn (f Formatter) print(j Justify) { |
|||
for line in f.text { |
|||
for i, word in line { |
|||
match j { |
|||
.left { |
|||
print('$word${' '.repeat(f.width[i]-word.len)} ') |
|||
} |
|||
.middle { |
|||
mut extra := 0 |
|||
if (f.width[i]%2==1 && word.len%2==0) || (f.width[i]%2==0 && word.len%2==1) { |
|||
extra++ |
|||
} |
|||
print('${' '.repeat((f.width[i]-word.len)/2)}$word${' '.repeat((f.width[i]-word.len)/2+extra)} ') |
|||
} |
|||
.right { |
|||
print('${' '.repeat(f.width[i]-word.len)}$word ') |
|||
} |
|||
} |
|||
} |
|||
println("") |
|||
} |
|||
println("") |
|||
} |
|||
fn main() { |
|||
f := new_formatter(text) |
|||
f.print(Justify.left) |
|||
f.print(Justify.middle) |
|||
f.print(Justify.right) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
</pre> |
</pre> |
||
=={{header|Wren}}== |
|||
{{libheader|Wren-fmt}} |
|||
<syntaxhighlight lang="wren">import "io" for File |
|||
import "./fmt" for Fmt |
|||
var LEFT = 0 |
|||
var RIGHT = 1 |
|||
var CENTER = 2 |
|||
var justStrs = ["LEFT", "RIGHT", "CENTER"] |
|||
// Gets a list of lines in the file with each line split into fields. |
|||
var getLines = Fn.new { |fileName| |
|||
var contents = File.read(fileName) |
|||
var lines = contents.split("\n") // use "\r\n" on Windows |
|||
for (i in 0...lines.count) { |
|||
lines[i] = lines[i].trim().trimEnd("$") |
|||
if (lines[i] == "") { // get rid of final blank line, if any |
|||
lines = lines[0..-2] |
|||
break |
|||
} |
|||
lines[i] = lines[i].split("$") |
|||
} |
|||
return lines |
|||
} |
|||
var alignCols = Fn.new { |lines, just| |
|||
// find maximum number of columns |
|||
var nCols = lines.reduce(0) { |acc, line| (line.count > acc) ? line.count : acc } |
|||
// find maximum width for each column |
|||
var maxWids = List.filled(nCols, 0) |
|||
for (line in lines) { |
|||
for (i in 0...line.count) { |
|||
var width = line[i].count |
|||
if (width > maxWids[i]) maxWids[i] = width |
|||
} |
|||
} |
|||
System.print("With %(justStrs[just]) justification:") |
|||
for (line in lines) { |
|||
for (i in 0...line.count) { |
|||
var width = maxWids[i] + 1 |
|||
if (just == LEFT) { |
|||
System.write(Fmt.s(-width, line[i])) |
|||
} else if (just == RIGHT) { |
|||
System.write(Fmt.s(width, line[i])) |
|||
} else if (just == CENTER) { |
|||
System.write(Fmt.m(width, line[i])) |
|||
} |
|||
} |
|||
System.print() |
|||
} |
|||
System.print() |
|||
} |
|||
var fileName = "align_cols.txt" |
|||
var lines = getLines.call(fileName) |
|||
for (i in 0..2) alignCols.call(lines, i)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
With LEFT 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. |
|||
With RIGHT 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. |
|||
With CENTER 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. |
|||
</pre> |
|||
=={{header|XPL0}}== |
|||
<syntaxhighlight lang "XPL0"> |
|||
string 0; |
|||
def LF=$0A, CR=$0D; |
|||
def Left, Right, Center; |
|||
proc AlignCols(S); \Display string S with its columns aligned |
|||
char S, C, Field(80), ColWidth(80); |
|||
int I, J, N, Just; |
|||
proc Justify; |
|||
int T; |
|||
proc SpOut(M); \Output M space characters |
|||
int M, K; |
|||
for K:= 0 to M-1 do ChOut(0, ^ ); |
|||
proc FieldOut; \Output Field of N characters |
|||
int K; |
|||
for K:= 0 to N-1 do ChOut(0, Field(K)); |
|||
[case Just of |
|||
Left: [FieldOut(N); SpOut(ColWidth(J)-N+1)]; |
|||
Right: [SpOut(ColWidth(J)-N+1); FieldOut(N)]; |
|||
Center:[T:= ColWidth(J)-N+1; |
|||
SpOut(T/2); FieldOut(N); SpOut(T/2 + rem(0))] |
|||
other []; |
|||
]; |
|||
[\Get width (in characters) of each column |
|||
for J:= 0 to 80-1 do ColWidth(J):= 0; |
|||
I:= 0; J:= 0; N:= 0; |
|||
loop [repeat C:= S(I); I:= I+1 until C # CR; |
|||
if N > ColWidth(J) then ColWidth(J):= N; |
|||
case C of |
|||
0: quit; |
|||
^$: [N:= 0; J:= J+1]; |
|||
LF: [N:= 0; J:= J+1; J:= 0] |
|||
other N:= N+1; |
|||
]; |
|||
for Just:= Left to Center do |
|||
[I:= 0; J:= 0; N:= 0; |
|||
loop [repeat C:= S(I); I:= I+1 until C # CR; |
|||
case C of |
|||
0: [Justify(Just); CrLf(0); quit]; |
|||
^$: [Justify(Just); N:= 0; J:= J+1]; |
|||
LF: [Justify(Just); CrLf(0); N:= 0; J:= 0] |
|||
other [Field(N):= C; N:= N+1]; |
|||
]; |
|||
CrLf(0); |
|||
]; |
|||
]; |
|||
AlignCols("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.") |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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. |
|||
</pre> |
|||
=={{header|Yabasic}}== |
|||
{{trans|Run BASIC}} |
|||
<syntaxhighlight lang="yabasic">theString$ = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" |
|||
theString$ = theString$ + "are$delineated$by$a$single$'dollar'$character,$write$a$program" |
|||
theString$ = theString$ + "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" |
|||
theString$ = theString$ + "column$are$separated$by$at$least$one$space." |
|||
theString$ = theString$ + "Further,$allow$for$each$word$in$a$column$to$be$either$left$" |
|||
theString$ = theString$ + "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 |
|||
sub word$(sr$, wn, delim$) |
|||
local i, j, n, sd, sl, sl2 |
|||
local s$, res$, d$ |
|||
d$ = delim$ |
|||
j = wn |
|||
if j = 0 j = j+1 |
|||
res$ = "" : s$ = sr$ |
|||
if d$ = "" d$ = " " |
|||
sd = len(d$) : sl = len(s$) |
|||
do |
|||
n = instr(s$,d$) |
|||
j = j - 1 |
|||
if j = 0 then |
|||
if n = 0 then res$ = s$ else res$ = mid$(s$, 1, n-1) : fi |
|||
return res$ |
|||
fi |
|||
if n = 0 return res$ |
|||
if n = sl-sd then res$ = "" : return res$ : fi |
|||
sl2 = sl-n |
|||
s$ = mid$(s$, n+1, sl2) |
|||
sl = sl2 |
|||
loop |
|||
return res$ |
|||
end sub |
|||
sub shoTable(theString$, align$, across) |
|||
local i, a$, b$ |
|||
print "------------ align:", align$, " -- across:", across, " ------------" |
|||
dim siz(across) |
|||
b$ = " " |
|||
while word$(theString$, i+1, "$") <> "" |
|||
siz(mod(i, across)) = max(siz(mod(i, 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 siz(i) = siz(i)+1 |
|||
next i |
|||
i = 0 |
|||
a$ = word$(theString$, i+1, "$") |
|||
while a$ <> "" |
|||
s = siz(mod(i, across)) - len(a$) |
|||
if align$ = "right" a$ = left$(b$, s) + a$ |
|||
if align$ = "left" a$ = a$ + left$(b$, s) |
|||
if align$ = "center" a$ = left$(b$, int(s / 2)) + a$ + left$(b$, int(s / 2) + (s and 1)) |
|||
print "|", a$; |
|||
i = i + 1 |
|||
if mod(i, across) = 0 print "|" |
|||
a$ = word$(theString$, i+1, "$") |
|||
wend |
|||
print |
|||
end sub</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Same as Run BASIC entry.</pre> |
|||
=={{header|zkl}}== |
|||
<syntaxhighlight lang="zkl">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; |
|||
}</syntaxhighlight> |
|||
<syntaxhighlight lang="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"; |
|||
format(text,-1).print(); |
|||
format(text, 0).print(); |
|||
format(text, 1).print();</syntaxhighlight> |
|||
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. |
|||
{{out}} |
|||
<pre style="height:20ex;overflow:scroll"> |
|||
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. |
|||
</pre> |
|||
=={{header|ZX Spectrum Basic}}== |
|||
The max width (without 'hack') of ZX Spectrum screen is 32 characters. The text sample is adapted for this feature. |
|||
<syntaxhighlight lang="zxbasic"> 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</syntaxhighlight> |
|||
{{out}}Left alignement example: |
|||
<pre>The problem of Speccy |
|||
is the screen. |
|||
Need adapt text sample |
|||
for show the result |
|||
without problem ,right? |
|||
But see the code. </pre> |
|||
{{omit from|PARI/GP|No real capacity for string manipulation}} |
Latest revision as of 08:41, 23 July 2024
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
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 on a plain text editor or basic terminal.
- The minimum space between columns should be computed from the text and not hard-coded.
- It is not a requirement to add separating characters between or around columns.
- Metrics
- Counting
- Word frequency
- Letter frequency
- Jewels and stones
- I before E except after C
- Bioinformatics/base count
- Count occurrences of a substring
- Count how many vowels and consonants occur in a string
- Remove/replace
- XXXX redacted
- Conjugate a Latin verb
- Remove vowels from a string
- String interpolation (included)
- Strip block comments
- Strip comments from a string
- Strip a set of characters from a string
- Strip whitespace from a string -- top and tail
- Strip control codes and extended characters from a string
- Anagrams/Derangements/shuffling
- Word wheel
- ABC problem
- Sattolo cycle
- Knuth shuffle
- Ordered words
- Superpermutation minimisation
- Textonyms (using a phone text pad)
- Anagrams
- Anagrams/Deranged anagrams
- Permutations/Derangements
- Find/Search/Determine
- ABC words
- Odd words
- Word ladder
- Semordnilap
- Word search
- Wordiff (game)
- String matching
- Tea cup rim text
- Alternade words
- Changeable words
- State name puzzle
- String comparison
- Unique characters
- Unique characters in each string
- Extract file extension
- Levenshtein distance
- Palindrome detection
- Common list elements
- Longest common suffix
- Longest common prefix
- Compare a list of strings
- Longest common substring
- Find common directory path
- Words from neighbour ones
- Change e letters to i in words
- Non-continuous subsequences
- Longest common subsequence
- Longest palindromic substrings
- Longest increasing subsequence
- Words containing "the" substring
- Sum of the digits of n is substring of n
- Determine if a string is numeric
- Determine if a string is collapsible
- Determine if a string is squeezable
- Determine if a string has all unique characters
- Determine if a string has all the same characters
- Longest substrings without repeating characters
- Find words which contains all the vowels
- Find words which contain the most consonants
- Find words which contains more than 3 vowels
- Find words whose first and last three letters are equal
- Find words with alternating vowels and consonants
- Formatting
- Substring
- Rep-string
- Word wrap
- String case
- Align columns
- Literals/String
- Repeat a string
- Brace expansion
- Brace expansion using ranges
- Reverse a string
- Phrase reversals
- Comma quibbling
- Special characters
- String concatenation
- Substring/Top and tail
- Commatizing numbers
- Reverse words in a string
- Suffixation of decimal numbers
- Long literals, with continuations
- Numerical and alphabetical suffixes
- Abbreviations, easy
- Abbreviations, simple
- Abbreviations, automatic
- Song lyrics/poems/Mad Libs/phrases
- Mad Libs
- Magic 8-ball
- 99 bottles of beer
- The Name Game (a song)
- The Old lady swallowed a fly
- The Twelve Days of Christmas
- Tokenize
- Text between
- Tokenize a string
- Word break problem
- Tokenize a string with escaping
- Split a character string based on change of character
- Sequences
11l
V 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.’
V parts = txt.split("\n").map(line -> line.rtrim(‘$’).split(‘$’))
V max_widths = [0] * parts[0].len
L(line) parts
L(word) line
max_widths[L.index] = max(max_widths[L.index], word.len)
((String, Int) -> String) ljust = (s, w) -> s‘’(‘ ’ * (w - s.len))
((String, Int) -> String) centr = (s, w) -> (‘ ’ * (w - s.len - (w I/ 2 - s.len I/ 2)))‘’s‘’(‘ ’ * (w I/ 2 - s.len I/ 2))
((String, Int) -> String) rjust = (s, w) -> (‘ ’ * (w - s.len))‘’s
L(justify) [ljust, centr, rjust]
print([‘Left’, ‘Center’, ‘Right’][L.index]‘ column-aligned output:’)
L(line) parts
L(word) line
print(justify(word, max_widths[L.index]), end' ‘ ’)
print()
print(‘- ’ * 52)
360 Assembly
* Align columns 12/04/2019
ALICOL CSECT
USING ALICOL,R13 base register
B 72(R15) skip savearea
DC 17F'0' savearea
SAVE (14,12) save previous context
ST R13,4(R15) link backward
ST R15,8(R13) link forward
LR R13,R15 set addressability
LA R8,1 i=1
DO WHILE=(C,R8,LE,=A(NI)) do r=1 to hbound(t)
LA R7,1 j=1
LA R6,L'T i=length(t)
DO WHILE=(C,R6,GE,=A(1)) do i=length(t) to 1 by -1
LR R1,R8 r
MH R1,=AL2(L'T) ~
LA R4,T-L'T(R1) t(r)
BCTR R4,0 -1
AR R4,R6 +i
MVC CI,0(R4) ci=substr(t(r),i,1)
CLI CI,C' ' if ci=' '
BE ITERI1 then iterate i
CLI CI,C'$' if ci='$'
BE ITERI1 then iterate i
LR R7,R6 j=i
B LEAVEI1 leave i
ITERI1 BCTR R6,0 i--
ENDDO , enddo i
LEAVEI1 LR R1,R8 r
MH R1,=AL2(L'T) ~
LA R4,T-L'T(R1) @t(r)
LA R2,WT @wt
LR R5,R7 j
ICM R5,B'1000',=C' ' padding
LA R3,L'T length(wt)
MVCL R2,R4 wt=substr(t(r),1,j)
LA R0,1 1
ST R0,I0 i0=1
SR R9,R9 c=0
LA R6,1 i=1
DO WHILE=(CR,R6,LE,R7) do i=1 to j
LA R4,WT-1 @wt
AR R4,R6 i
MVC CI(1),0(R4) ci=substr(wt,i,1)
IF CLI,CI,EQ,C'$' THEN if ci='$' then
BAL R14,SEQ call seq
LR R2,R6 i
LA R2,1(R2) +1
ST R2,I0 i0=i+1
ENDIF , endif
LA R6,1(R6) i++
ENDDO , enddo i
BAL R14,SEQ call seq
IF C,R9,GT,COLS THEN if c>cols then
ST R9,COLS cols=c
ENDIF , endif
LA R8,1(R8) r++
ENDDO , enddo r
LR R2,R8 r
BCTR R2,0 -1
ST R2,ROWS rows=r-1
LA R7,1 j=1
DO WHILE=(C,R7,LE,=A(3)) do j=1 to 3
XPRNT =C'--',2 print
LA R8,1 r=1
DO WHILE=(C,R8,LE,ROWS) do r=1 to rows
MVC PG,=CL120' ' pg=' '
LA R0,1 1
ST R0,IB ib=1
LA R9,1 c=1
DO WHILE=(C,R9,LE,COLS) do c=1 to cols
LR R1,R8 r
BCTR R1,0 -1
MH R1,=AL2(NJ) ~
AR R1,R9 c
MH R1,=AL2(L'WOR) ~
LA R4,WOR-L'WOR(R1) @wor(r,c)
MVC W,0(R4) w=wor(r,c)
LA R6,L'W i=length(w)
DO WHILE=(C,R6,GE,=A(1)) do i=length(w) to 1 by -1
LA R4,W-1 @w
AR R4,R6 i
MVC CI,0(R4) ci=substr(w,i,1)
CLI CI,C' ' if ci^=' '
BNE LEAVEI2 then goto leavei2;
BCTR R6,0 i--
ENDDO , enddo i
LEAVEI2 EQU * ~
IF LTR,R6,Z,R6 THEN if i=0 then
LA R10,1 l=1
ELSE , else
LR R10,R6 l=i
ENDIF , endif
IF C,R7,EQ,=F'1' THEN if j=1 then
L R11,IB ibx=ib
ENDIF , endif
IF C,R7,EQ,=F'2' THEN if j=2 then
LR R1,R9 c
SLA R1,2 ~
L R11,WID-L'WID(R1) wid(c)
A R11,IB +ib
SR R11,R10 ibx=ib+wid(c)-l
ENDIF , endif
IF C,R7,EQ,=F'3' THEN if j=3 then
LR R1,R9 c
SLA R1,2 ~
L R11,WID-L'WID(R1) wid(c)
SR R11,R10 -l
SRA R11,1 /2
A R11,IB ibx=ib+(wid(c)-l)/2
ENDIF , endif
LA R2,PG-1 @pg
AR R2,R11 +ibx
LR R3,R10 l
LA R4,W @w
LR R5,R10 l
MVCL R2,R4 substr(pg,ibx,l)=substr(w,1,l)
LR R1,R9 c
SLA R1,2 ~
L R2,WID-L'WID(R1) wid(c)
A R2,IB +ib
LA R2,1(R2) +1
ST R2,IB ib=ib+wid(c)+1
LA R9,1(R9) c++
ENDDO , enddo c
XPRNT PG,L'PG print
LA R8,1(R8) r++
ENDDO , enddo r
LA R7,1(R7) j++
ENDDO , enddo j
L R13,4(0,R13) restore previous savearea pointer
RETURN (14,12),RC=0 restore registers from calling sav
SEQ EQU * --begin seq
LA R9,1(R9) c=c+1
LR R10,R6 i
S R10,I0 l=i-i0
LA R4,WT-1 @wt
A R4,I0 +i0
LR R5,R10 l
ICM R5,B'1000',=C' ' padding
LR R1,R8 r
BCTR R1,0 -1
MH R1,=AL2(NJ) ~
AR R1,R9 +c
MH R1,=AL2(L'WOR) ~
LA R2,WOR-L'WOR(R1) @wor(r,c)
LA R3,L'WOR length(wor)
MVCL R2,R4 wor(r,c)=substr(wt,i0,l)
LR R1,R9 c
SLA R1,2 ~
L R2,WID-L'WID(R1) wid(c)
IF CR,R2,LT,R10 THEN if l>wid(c) then
LR R1,R9 c
SLA R1,2 ~
ST R10,WID-L'WID(R1) wid(c)=l
ENDIF , endif
BR R14 --end seq
NI EQU 6 ni
NJ EQU 12 nj
T DC CL68'Given$a$text$file$of$many$lines,$where$fields$within$a$line$'
DC CL68'are$delineated$by$a$single$''dollar''$character,$write$a$progX
ramm'
DC CL68'that$aligns$each$column$of$fields$by$ensuring$that$words$in$eX
ach$'
DC CL68'column$are$separated$by$at$least$one$space.'
DC CL68'Further,$allow$for$each$word$in$a$column$to$be$either$left$'
DC CL68'justified,$right$justified,$or$center$justified$within$its$coX
lumn.'
WOR DC (NI*NJ)CL10' ' wor(ni,nj) char(10)
WID DC 16F'0' wid(16)
COLS DC F'0'
ROWS DC F'0'
WT DS CL(L'T)
W DS CL(L'WOR)
CI DS CL1
I0 DS F
IB DS F
PG DS CL120
REGEQU
END ALICOL
- Output:
-- Given a text file of many lines, where fields within a line are delineated by a single 'dollar' character, write a programm 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 programm 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 programm 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.
8th
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.|
var, raw-text
[] var, data
var width
: read-and-parse \ --
raw-text @
( "$" s:/ data @ swap a:push drop )
s:eachline ;
: find-widest \ -- n
data @ ( ( swap s:len nip n:max ) swap a:reduce ) 0 a:reduce ;
: print-data \ fmt --
width @ swap s:strfmt >r
data @
(
nip
(
nip
r@ s:strfmt .
) a:each drop
cr
) a:each drop rdrop ;
: app:main
read-and-parse
\ find widest column, and add one for the space:
find-widest n:1+ width !
\ print the data
cr "right:" . cr "%%>%ds" print-data
cr "left:" . cr "%%<%ds" print-data
cr "center:" . cr "%%|%ds" print-data
bye ;
- Output:
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. 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.
AArch64 Assembly
/* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits */
/* program alignColumn64.s */
/*******************************************/
/* Constantes file */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
.equ BUFFERSIZE, 16 * 10
/*********************************/
/* Initialized data */
/*********************************/
.data
szMessLeft: .asciz "LEFT :\n"
szMessRight: .asciz "\nRIGHT :\n"
szMessCenter: .asciz "\nCENTER :\n"
szCarriageReturn: .asciz "\n"
szLine1: .asciz "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
szLine2: .asciz "are$delineated$by$a$single$'dollar'$character,$write$a$program"
szLine3: .asciz "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
szLine4: .asciz "column$are$separated$by$at$least$one$space."
szLine5: .asciz "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
szLine6: .asciz "justified,$right$justified,$or$center$justified$within$its$column."
.align 8
qtbPtLine: .quad szLine1,szLine2,szLine3,szLine4,szLine5,szLine6
.equ NBLINES, (. - qtbPtLine) / 8
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: // entry of program
ldr x0,qAdrqtbPtLine
bl computeMaxiLengthWords
mov x19,x0 // column counter
ldr x0,qAdrszMessLeft
bl affichageMess
ldr x0,qAdrqtbPtLine
mov x1,x19 // column size
bl alignLeft
ldr x0,qAdrszMessRight
bl affichageMess
ldr x0,qAdrqtbPtLine
mov x1,x19 // column size
bl alignRight
ldr x0,qAdrszMessCenter
bl affichageMess
ldr x0,qAdrqtbPtLine
mov x1,x19 // column size
bl alignCenter
100: // standard end of the program
mov x0, #0 // return code
mov x8, #EXIT // request to exit program
svc #0 // perform the system call
qAdrszCarriageReturn: .quad szCarriageReturn
qAdrszMessLeft: .quad szMessLeft
qAdrszMessRight: .quad szMessRight
qAdrszMessCenter: .quad szMessCenter
qAdrqtbPtLine: .quad qtbPtLine
/******************************************************************/
/* compute maxi words */
/******************************************************************/
/* x0 contains adresse pointer array */
computeMaxiLengthWords:
stp fp,lr,[sp,-16]! // save registres
mov x2,#0 // indice pointer array
mov x3,#0 // maxi length words
1:
ldr x1,[x0,x2,lsl #3] // load pointer
mov x4,#0 // length words counter
mov x5,#0 // indice line character
2:
ldrb w6,[x1,x5] // load a line character
cmp x6,#0 // line end ?
beq 4f
cmp x6,#'$' // separator ?
bne 3f
cmp x4,x3
csel x3,x4,x3,gt // if greather replace maxi
mov x4,#-1 // raz length counter
3:
add x4,x4,#1
add x5,x5,#1 // increment character indice
b 2b // and loop
4: // end line
cmp x4,x3 // compare word counter and maxi
csel x3,x4,x3,gt // if greather replace maxi
add x2,x2,#1 // increment indice line pointer
cmp x2,#NBLINES // maxi ?
blt 1b // no -> loop
mov x0,x3 // return maxi length counter
100:
ldp fp,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* align left */
/******************************************************************/
/* x0 contains the address of pointer array*/
/* x1 contains column size */
alignLeft:
stp fp,lr,[sp,-16]! // save registres
sub sp,sp,#BUFFERSIZE // reserve place for output buffer
mov fp,sp
mov x5,x0 // array address
mov x2,#0 // indice array
1:
ldr x3,[x5,x2,lsl #3] // load line pointer
mov x4,#0 // line character indice
mov x7,#0 // output buffer character indice
mov x6,#0 // word lenght
2:
ldrb w0,[x3,x4] // load a character line
strb w0,[fp,x7] // store in buffer
cmp w0,#0 // line end ?
beq 6f
cmp w0,#'$' // separator ?
bne 5f
mov x0,#' '
strb w0,[fp,x7] // replace $ by space
3:
cmp x6,x1 // length word >= length column
bge 4f
add x7,x7,#1
mov x0,#' '
strb w0,[fp,x7] // add space to buffer
add x6,x6,#1
b 3b // and loop
4:
mov x6,#-1 // raz word length
5:
add x4,x4,#1 // increment line indice
add x7,x7,#1 // increment buffer indice
add x6,x6,#1 // increment word length
b 2b
6:
mov x0,#'\n'
strb w0,[fp,x7] // return line
add x7,x7,#1
mov x0,#0
strb w0,[fp,x7] // final zéro
mov x0,fp
bl affichageMess // display output buffer
add x2,x2,#1
cmp x2,#NBLINES
blt 1b
100:
add sp,sp,#BUFFERSIZE
ldp fp,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* align right */
/******************************************************************/
/* x0 contains the address of pointer array*/
/* x1 contains column size */
alignRight:
stp fp,lr,[sp,-16]! // save registres
sub sp,sp,#BUFFERSIZE // reserve place for output buffer
mov fp,sp
mov x5,x0 // array address
mov x2,#0 // indice array
1:
ldr x3,[x5,x2,lsl #3] // load line pointer
mov x4,#0 // line character indice
mov x7,#0 // output buffer character indice
mov x6,#0 // word lenght
mov x8,x3 // word begin address
2: // compute word length
ldrb w0,[x3,x4] // load a character line
cmp w0,#0 // line end ?
beq 3f
cmp w0,#'$' // separator ?
beq 3f
add x4,x4,#1 // increment line indice
add x6,x6,#1 // increment word length
b 2b
3:
cmp x6,#0
beq 4f
sub x6,x1,x6 // compute left spaces to add
4: // loop add spaces to buffer
cmp x6,#0
blt 5f
mov x0,#' '
strb w0,[fp,x7] // add space to buffer
add x7,x7,#1
sub x6,x6,#1
b 4b // and loop
5:
mov x9,#0
6: // copy loop word to buffer
ldrb w0,[x8,x9]
cmp x0,#'$'
beq 7f
cmp x0,#0 // line end
beq 8f
strb w0,[fp,x7]
add x7,x7,#1
add x9,x9,#1
b 6b
7:
add x8,x8,x9
add x8,x8,#1 // new word begin
mov x6,#0 // raz word length
add x4,x4,#1 // increment line indice
b 2b
8:
mov x0,#'\n'
strb w0,[fp,x7] // return line
add x7,x7,#1
mov x0,#0
strb w0,[fp,x7] // final zéro
mov x0,fp
bl affichageMess // display output buffer
add x2,x2,#1
cmp x2,#NBLINES
blt 1b
100:
add sp,sp,#BUFFERSIZE
ldp fp,lr,[sp],16 // restaur des 2 registres
ret
/******************************************************************/
/* align center */
/******************************************************************/
/* x0 contains the address of pointer array*/
/* x1 contains column size */
alignCenter:
stp fp,lr,[sp,-16]! // save registres
sub sp,sp,#BUFFERSIZE // reserve place for output buffer
mov fp,sp
mov x5,x0 // array address
mov x2,#0 // indice array
1:
ldr x3,[x5,x2,lsl #3] // load line pointer
mov x4,#0 // line character indice
mov x7,#0 // output buffer character indice
mov x6,#0 // word length
mov x8,x3 // word begin address
2: // compute word length
ldrb w0,[x3,x4] // load a character line
cmp w0,#0 // line end ?
beq 3f
cmp w0,#'$' // separator ?
beq 3f
add x4,x4,#1 // increment line indice
add x6,x6,#1 // increment word length
b 2b
3:
cmp x6,#0
beq 5f
sub x6,x1,x6 // total spaces number to add
mov x12,x6
lsr x6,x6,#1 // divise by 2 = left spaces number
4:
cmp x6,#0
blt 5f
mov x0,#' '
strb w0,[fp,x7] // add space to buffer
add x7,x7,#1 // increment output indice
sub x6,x6,#1 // decrement number space
b 4b // and loop
5:
mov x9,#0
6: // copy loop word to buffer
ldrb w0,[x8,x9]
cmp x0,#'$' // séparator ?
beq 7f
cmp x0,#0 // line end ?
beq 10f
strb w0,[fp,x7]
add x7,x7,#1
add x9,x9,#1
b 6b
7:
lsr x6,x12,#1 // divise total spaces by 2
sub x6,x12,x6 // and compute number spaces to right side
8: // loop to add right spaces
cmp x6,#0
ble 9f
mov x0,#' '
strb w0,[fp,x7] // add space to buffer
add x7,x7,#1
sub x6,x6,#1
b 8b // and loop
9:
add x8,x8,x9
add x8,x8,#1 // new address word begin
mov x6,#0 // raz word length
add x4,x4,#1 // increment line indice
b 2b // and loop new word
10:
mov x0,#'\n'
strb w0,[fp,x7] // return line
add x7,x7,#1
mov x0,#0
strb w0,[fp,x7] // final zéro
mov x0,fp
bl affichageMess // display output buffer
add x2,x2,#1 // increment line indice
cmp x2,#NBLINES // maxi ?
blt 1b // loop
100:
add sp,sp,#BUFFERSIZE
ldp fp,lr,[sp],16 // restaur des 2 registres
ret
/********************************************************/
/* File Include fonctions */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
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. 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.
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.
Action!
Atari 8-bit computer is able to show only 40 characters per line. The user has to press left/right arrow keys to scroll the content of whole text.
DEFINE LINES_COUNT="10"
DEFINE COLUMNS_COUNT="20"
DEFINE WORDS_COUNT="100"
DEFINE BUFFER_SIZE="2000"
DEFINE LINE_WIDTH="40"
DEFINE PTR="CARD"
PTR ARRAY lines(LINES_COUNT)
BYTE ARRAY wordStart(WORDS_COUNT)
BYTE ARRAY wordLen(WORDS_COUNT)
BYTE ARRAY firstWordInLine(LINES_COUNT)
BYTE ARRAY wordsInLine(LINES_COUNT)
BYTE ARRAY colWidths(COLUMNS_COUNT)
BYTE ARRAY buffer(BUFFER_SIZE)
BYTE lineCount,colCount,wordCount
CHAR sep=['$]
PROC AddLine(CHAR ARRAY line)
lines(lineCount)=line
lineCount==+1
RETURN
PROC InitData()
lineCount=0
AddLine("Given$a$text$file$of$many$lines,$where$fields$within$a$line$")
AddLine("are$delineated$by$a$single$'dollar'$character,$write$a$program")
AddLine("that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$")
AddLine("column$are$separated$by$at$least$one$space.")
AddLine("Further,$allow$for$each$word$in$a$column$to$be$either$left$")
AddLine("justified,$right$justified,$or$center$justified$within$its$column.")
RETURN
PROC ProcessData()
BYTE i,pos,len,start,w,col
CHAR ARRAY line
colCount=0 wordCount=0
FOR i=0 TO lineCount-1
DO
line=lines(i)
len=line(0)
firstWordInLine(i)=wordCount
wordsInLine(i)=0
pos=1 col=0
WHILE pos<=len
DO
start=pos
WHILE pos<=len AND line(pos)#sep
DO pos==+1 OD
w=pos-start
wordStart(wordCount)=start
wordLen(wordCount)=w
wordCount==+1
wordsInLine(i)==+1
IF col=colCount THEN
colWidths(col)=w
colCount==+1
ELSEIF w>colWidths(col) THEN
colWidths(col)=w
FI
col==+1
pos==+1
OD
OD
RETURN
BYTE FUNC GetBufLineLength()
BYTE i,res
res=0
FOR i=0 TO colCount-1
DO
res==+colWidths(i)+1
OD
res==+1
RETURN (res)
BYTE FUNC AtasciiToInternal(CHAR c)
BYTE c2
c2=c&$7F
IF c2<32 THEN
RETURN (c+64)
ELSEIF c2<96 THEN
RETURN (c-32)
FI
RETURN (c)
PROC GenerateLine(BYTE index BYTE align BYTE POINTER p)
BYTE wordIndex,last,left,right,start,len,colW
INT i,j
CHAR ARRAY line
line=lines(index)
wordIndex=firstWordInLine(index)
last=wordIndex+wordsInLine(index)-1
FOR i=0 TO colCount-1
DO
colW=colWidths(i)
p^=124 p==+1
IF wordIndex<=last THEN
start=wordStart(wordIndex)
len=wordLen(wordIndex)
IF align=0 THEN
left=0
right=colW-len
ELSEIF align=1 THEN
left=(colW-len)/2
right=colW-left-len
ELSE
left=colW-len
right=0
FI
p==+left
for j=start TO start+len-1
DO
p^=AtasciiToInternal(line(j))
p==+1
OD
p==+right
ELSE
p==+colW
FI
wordIndex==+1
OD
p^=124
RETURN
PROC FillBuffer(BYTE lineWidth)
BYTE i,align
BYTE POINTER p
p=buffer
Zero(p,BUFFER_SIZE)
FOR align=0 TO 2
DO
FOR i=0 TO lineCount-1
DO
GenerateLine(i,align,p)
p==+lineWidth
OD
OD
RETURN
BYTE FUNC GetMaxOffset()
BYTE res
res=GetBufLineLength()-LINE_WIDTH
RETURN (res)
PROC Update(BYTE offset,lineWidth)
BYTE POINTER srcPtr,dstPtr
BYTE i
srcPtr=buffer+offset
dstPtr=PeekC(88)+3*LINE_WIDTH
FOR i=0 TO 3*lineCount-1
DO
MoveBlock(dstPtr,srcPtr,LINE_WIDTH)
srcPtr==+lineWidth
dstPtr==+LINE_WIDTH
IF i=lineCount-1 OR i=2*lineCount-1 THEN
dstPtr==+LINE_WIDTH
FI
OD
RETURN
PROC Main()
BYTE
lineWidth,offset,maxOffset,k,
CH=$02FC, ;Internal hardware value for last key pressed
CRSINH=$02F0 ;Controls visibility of cursor
CRSINH=1 ;hide cursor
InitData()
ProcessData()
lineWidth=GetBufLineLength()
FillBuffer(lineWidth)
Position(2,1)
Print("Press left/right arrow key to scroll")
maxOffset=lineWidth-LINE_WIDTH
offset=0
Update(offset,lineWidth)
DO
k=CH
IF k#$FF THEN
CH=$FF
FI
IF k=134 AND offset>0 THEN
offset==-1
Update(offset,lineWidth)
ELSEIF k=135 AND offset<maxOffset THEN
offset==+1
Update(offset,lineWidth)
ELSEIF k=28 THEN
EXIT
FI
OD
RETURN
- Output:
Screenshot from Atari 8-bit computer
Press left/right arrow key to scroll |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.| | | |
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.
Aime
data b;
file f;
text n, t;
list c, r, s;
integer a, i, k, m, w;
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(b);
m = 0;
while (f.news(r, 0, 0, "$") ^ -1) {
c.append(r);
m = max(m, ~r);
}
i = 0;
while (i < m) {
w = 0;
for (, r in c) {
if (i < ~r) {
w = max(w, length(r[i]));
}
}
s.append(w + 1);
i += 1;
}
for (k, t in list("left", "center", "right")) {
o_(t, " justified\n");
for (, r in c) {
for (i, n in r) {
m = s[i] - ~n;
o_form("/w~3/~/w~1/", a = (2 - k) * m >> 1, "", m - a, "", n);
}
o_newline();
}
o_newline();
}
- 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.
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
Amazing Hopper
#define IGet(__N__,__X__) [__N__]SGet(__X__)
#include <hbasic.h>
#define MAX_LINE 1000
Begin
Option Stack 15
Declare as Numeric ( fd, i, index, max token )
as Numeric ( num tokens, size Column, tCells )
as Alpha ( line )
as Numeric ( display Left, display Right, display Center )
GetParam(script, file to edit, separator)
// get statistics of file: #lines, #total chars, line more long, and num tokens from first line.
Token Sep( separator )
Stat( file to edit, dats )
// declare arrays to work:
Dim ( IGet(1,dats), Add(IGet(4,dats),10) ) for Fill Array("",cells)
Clear(dats)
MStore ( cells, display Left, display Right, display Center )
// read each line as array, get # of elements, and put into array cells:
Open(OPEN_READ, file to edit ) (fd)
When( File Error ){ Stop }
index=1
While Not Eof(fd)
ReadRow(MAX_LINE)(fd) and Copy to (line); get Length, and Move to (num tokens)
Set Interval [index, 1:num tokens]; Take( line ) and SPut(cells)
When ( var( max token) Is Lt (num tokens) ) { max token = num tokens }
++index
Wend
Close(fd)
// formatting...
For Up( i:=1, max token, 1 )
Set Interval [1:end,i], and Let ( size Column := MaxValue( Len(Get(cells)) ) Plus(1) )
Let ( tCells := Get(cells) )
LPad$( " ", size Column, tCells ), and Put(display Left)
RPad$( " ", size Column, tCells ), and Put(display Right)
CPad$( " ", size Column, tCells ), and Put(display Center)
Next
// display:
Token Sep ("")
Print("Left Pad:\n", display Left, Newl, "Right Pad:\n", display Right, Newl, "Center Pad:\n", display Center,Newl)
End
- Output:
Sample String was saved into "sample.txt" file.
$ hopper src/acolumns.bas sample.txt "$" Left Pad: 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 Pad: 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 Pad: 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. $
APL
align←{
left ← {⍺↑⍵}
right ← {(-⍺)↑⍵}
center ← {⍺↑(-⌊(≢⍵)+(⍺-≢⍵)÷2)↑⍵}
text ← ⊃⎕NGET⍵
words ← ((≠∘'$')⊆⊣)¨(~text∊⎕TC)⊆text
sizes ← 1+⌈⌿↑≢¨¨words
method ← ⍎⍺
↑,/↑(⊂sizes)method¨¨↓↑words
}
- Output:
'left' align 'test.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. 'center' align 'test.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. 'right' align 'test.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.
AppleScript
Probably not the first language in which you would really choose to do this kind of thing, but certainly possible, and can be readily easily assembled from a set of generic primitives.
-- COLUMN ALIGNMENTS ---------------------------------------------------------
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
-- columnsAligned :: EnumValue -> [[String]] -> String
on columnsAligned(eAlign, lstCols)
-- padwords :: Int -> [String] -> [[String]]
script padwords
on |λ|(n, lstWords)
-- pad :: String -> String
script pad
on |λ|(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 |λ|
end script
map(pad, lstWords)
end |λ|
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 |λ|(str)
splitOn(strColDelim, str)
end |λ|
end script
set lstRows to map(_words, splitOn(linefeed, pstrLines))
set nCols to widest(lstRows)
-- fullRow :: [[a]] -> [[a]]
script fullRow
on |λ|(lst)
lst & replicate(nCols - (length of lst), {""})
end |λ|
end script
transpose(map(fullRow, lstRows))
end lineColumns
-- widest [a] -> Int
on widest(xs)
|length|(maximumBy(comparing(my |length|), xs))
end widest
-- TEST ----------------------------------------------------------------------
on run
set lstCols to lineColumns("$", pstrLines)
script testAlignment
on |λ|(eAlign)
columnsAligned(eAlign, lstCols)
end |λ|
end script
intercalate(return & return, ¬
map(testAlignment, {eLeft, eRight, eCenter}))
end run
-- GENERIC FUNCTIONS ---------------------------------------------------------
-- comparing :: (a -> b) -> (a -> a -> Ordering)
on comparing(f)
set mf to mReturn(f)
script
on |λ|(a, b)
set x to mf's |λ|(a)
set y to mf's |λ|(b)
if x < y then
-1
else
if x > y then
1
else
0
end if
end if
end |λ|
end script
end comparing
-- 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 |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- 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
-- length :: [a] -> Int
on |length|(xs)
length of xs
end |length|
-- 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 |λ| : f
end script
end if
end mReturn
-- 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 |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- maximumBy :: (a -> a -> Ordering) -> [a] -> a
on maximumBy(f, xs)
set cmp to mReturn(f)
script max
on |λ|(a, b)
if a is missing value or cmp's |λ|(a, b) < 0 then
b
else
a
end if
end |λ|
end script
foldl(max, missing value, xs)
end maximumBy
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- 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)
if class of a is string then
set out to ""
else
set out to {}
end if
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
-- 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
-- transpose :: [[a]] -> [[a]]
on transpose(xss)
script column
on |λ|(_, iCol)
script row
on |λ|(xs)
item iCol of xs
end |λ|
end script
map(row, xss)
end |λ|
end script
map(column, item 1 of xss)
end transpose
-- [Text] -> Text
on unlines(lstLines)
intercalate(linefeed, lstLines)
end unlines
-- [Text] -> Text
on unwords(lstWords)
intercalate(" ", lstWords)
end unwords
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
on zipWith(f, xs, ys)
set lng to min(length of xs, length of ys)
set lst to {}
tell mReturn(f)
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, item i of ys)
end repeat
return lst
end tell
end zipWith
- 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.
ARM Assembly
/* ARM assembly Raspberry PI */
/* program alignColumn.s */
/* REMARK 1 : this program use routines in a include file
see task Include a file language arm assembly
for the routine affichageMess conversion10
see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes */
/************************************/
.include "../constantes.inc"
.equ BUFFERSIZE, 20 * 10
/*********************************/
/* Initialized data */
/*********************************/
.data
szMessLeft: .asciz "LEFT :\n"
szMessRight: .asciz "\nRIGHT :\n"
szMessCenter: .asciz "\nCENTER :\n"
szCarriageReturn: .asciz "\n"
szLine1: .asciz "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
szLine2: .asciz "are$delineated$by$a$single$'dollar'$character,$write$a$program"
szLine3: .asciz "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
szLine4: .asciz "column$are$separated$by$at$least$one$space."
szLine5: .asciz "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
szLine6: .asciz "justified,$right$justified,$or$center$justified$within$its$column."
itbPtLine: .int szLine1,szLine2,szLine3,szLine4,szLine5,szLine6
.equ NBLINES, (. - itbPtLine) / 4
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: @ entry of program
ldr r0,iAdritbPtLine
bl computeMaxiLengthWords
mov r10,r0 @ column counter
ldr r0,iAdrszMessLeft
bl affichageMess
ldr r0,iAdritbPtLine
mov r1,r10 @ column size
bl alignLeft
ldr r0,iAdrszMessRight
bl affichageMess
ldr r0,iAdritbPtLine
mov r1,r10 @ column size
bl alignRight
ldr r0,iAdrszMessCenter
bl affichageMess
ldr r0,iAdritbPtLine
mov r1,r10 @ column size
bl alignCenter
100: @ standard end of the program
mov r0, #0 @ return code
mov r7, #EXIT @ request to exit program
svc #0 @ perform the system call
iAdrszCarriageReturn: .int szCarriageReturn
iAdrszMessLeft: .int szMessLeft
iAdrszMessRight: .int szMessRight
iAdrszMessCenter: .int szMessCenter
iAdritbPtLine: .int itbPtLine
/******************************************************************/
/* compute maxi words */
/******************************************************************/
/* r0 contains adresse pointer array */
computeMaxiLengthWords:
push {r1-r6,lr} @ save registers
mov r2,#0 @ indice pointer array
mov r3,#0 @ maxi length words
1:
ldr r1,[r0,r2,lsl #2] @ load pointer
mov r4,#0 @ length words counter
mov r5,#0 @ indice line character
2:
ldrb r6,[r1,r5] @ load a line character
cmp r6,#0 @ line end ?
beq 4f
cmp r6,#'$' @ separator ?
bne 3f
cmp r4,r3
movgt r3,r4 @ ig greather replace maxi
mov r4,#-1 @ raz length counter
3:
add r4,r4,#1
add r5,r5,#1 @ increment character indice
b 2b @ and loop
4: @ end line
cmp r4,r3 @ compare word counter and maxi
movgt r3,r4 @ if greather replace maxi
add r2,r2,#1 @ increment indice line pointer
cmp r2,#NBLINES @ maxi ?
blt 1b @ no -> loop
mov r0,r3 @ return maxi length counter
100:
pop {r1-r6,pc}
/******************************************************************/
/* align left */
/******************************************************************/
/* r0 contains the address of pointer array*/
/* r1 contains column size */
alignLeft:
push {r4-r7,fp,lr} @ save registers
sub sp,sp,#BUFFERSIZE @ reserve place for output buffer
mov fp,sp
mov r5,r0 @ array address
mov r2,#0 @ indice array
1:
ldr r3,[r5,r2,lsl #2] @ load line pointer
mov r4,#0 @ line character indice
mov r7,#0 @ output buffer character indice
mov r6,#0 @ word lenght
2:
ldrb r0,[r3,r4] @ load a character line
strb r0,[fp,r7] @ store in buffer
cmp r0,#0 @ line end ?
beq 6f
cmp r0,#'$' @ separator ?
bne 5f
mov r0,#' '
strb r0,[fp,r7] @ replace $ by space
3:
cmp r6,r1 @ length word >= length column
bge 4f
add r7,r7,#1
mov r0,#' '
strb r0,[fp,r7] @ add space to buffer
add r6,r6,#1
b 3b @ and loop
4:
mov r6,#-1 @ raz word length
5:
add r4,r4,#1 @ increment line indice
add r7,r7,#1 @ increment buffer indice
add r6,r6,#1 @ increment word length
b 2b
6:
mov r0,#'\n'
strb r0,[fp,r7] @ return line
add r7,r7,#1
mov r0,#0
strb r0,[fp,r7] @ final zéro
mov r0,fp
bl affichageMess @ display output buffer
add r2,r2,#1
cmp r2,#NBLINES
blt 1b
100:
add sp,sp,#BUFFERSIZE
pop {r4-r7,fp,pc}
/******************************************************************/
/* align right */
/******************************************************************/
/* r0 contains the address of pointer array*/
/* r1 contains column size */
alignRight:
push {r4-r9,fp,lr} @ save registers
sub sp,sp,#BUFFERSIZE @ reserve place for output buffer
mov fp,sp
mov r5,r0 @ array address
mov r2,#0 @ indice array
1:
ldr r3,[r5,r2,lsl #2] @ load line pointer
mov r4,#0 @ line character indice
mov r7,#0 @ output buffer character indice
mov r6,#0 @ word lenght
mov r8,r3 @ word begin address
2: @ compute word length
ldrb r0,[r3,r4] @ load a character line
cmp r0,#0 @ line end ?
beq 3f
cmp r0,#'$' @ separator ?
beq 3f
add r4,r4,#1 @ increment line indice
add r6,r6,#1 @ increment word length
b 2b
3:
cmp r6,#0
beq 4f
sub r6,r1,r6 @ compute left spaces to add
4: @ loop add spaces to buffer
cmp r6,#0
blt 5f
mov r0,#' '
strb r0,[fp,r7] @ add space to buffer
add r7,r7,#1
sub r6,r6,#1
b 4b @ and loop
5:
mov r9,#0
6: @ copy loop word to buffer
ldrb r0,[r8,r9]
cmp r0,#'$'
beq 7f
cmp r0,#0 @ line end
beq 8f
strb r0,[fp,r7]
add r7,r7,#1
add r9,r9,#1
b 6b
7:
add r8,r8,r9
add r8,r8,#1 @ new word begin
mov r6,#0 @ raz word length
add r4,r4,#1 @ increment line indice
b 2b
8:
mov r0,#'\n'
strb r0,[fp,r7] @ return line
add r7,r7,#1
mov r0,#0
strb r0,[fp,r7] @ final zéro
mov r0,fp
bl affichageMess @ display output buffer
add r2,r2,#1
cmp r2,#NBLINES
blt 1b
100:
add sp,sp,#BUFFERSIZE
pop {r4-r9,fp,pc}
/******************************************************************/
/* align center */
/******************************************************************/
/* r0 contains the address of pointer array*/
/* r1 contains column size */
alignCenter:
push {r4-r12,lr} @ save registers
sub sp,sp,#BUFFERSIZE @ reserve place for output buffer
mov fp,sp
mov r5,r0 @ array address
mov r2,#0 @ indice array
1:
ldr r3,[r5,r2,lsl #2] @ load line pointer
mov r4,#0 @ line character indice
mov r7,#0 @ output buffer character indice
mov r6,#0 @ word length
mov r8,r3 @ word begin address
2: @ compute word length
ldrb r0,[r3,r4] @ load a character line
cmp r0,#0 @ line end ?
beq 3f
cmp r0,#'$' @ separator ?
beq 3f
add r4,r4,#1 @ increment line indice
add r6,r6,#1 @ increment word length
b 2b
3:
cmp r6,#0
beq 5f
sub r6,r1,r6 @ total spaces number to add
mov r12,r6
lsr r6,r6,#1 @ divise by 2 = left spaces number
4:
cmp r6,#0
blt 5f
mov r0,#' '
strb r0,[fp,r7] @ add space to buffer
add r7,r7,#1 @ increment output indice
sub r6,r6,#1 @ decrement number space
b 4b @ and loop
5:
mov r9,#0
6: @ copy loop word to buffer
ldrb r0,[r8,r9]
cmp r0,#'$' @ séparator ?
beq 7f
cmp r0,#0 @ line end ?
beq 10f
strb r0,[fp,r7]
add r7,r7,#1
add r9,r9,#1
b 6b
7:
lsr r6,r12,#1 @ divise total spaces by 2
sub r6,r12,r6 @ and compute number spaces to right side
8: @ loop to add right spaces
cmp r6,#0
ble 9f
mov r0,#' '
strb r0,[fp,r7] @ add space to buffer
add r7,r7,#1
sub r6,r6,#1
b 8b @ and loop
9:
add r8,r8,r9
add r8,r8,#1 @ new address word begin
mov r6,#0 @ raz word length
add r4,r4,#1 @ increment line indice
b 2b @ and loop new word
10:
mov r0,#'\n'
strb r0,[fp,r7] @ return line
add r7,r7,#1
mov r0,#0
strb r0,[fp,r7] @ final zéro
mov r0,fp
bl affichageMess @ display output buffer
add r2,r2,#1 @ increment line indice
cmp r2,#NBLINES @ maxi ?
blt 1b @ loop
100:
add sp,sp,#BUFFERSIZE
pop {r4-r12,pc}
/***************************************************/
/* ROUTINES INCLUDE */
/***************************************************/
.include "../affichage.inc"
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. 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.
Arturo
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.
}
output: map split.lines text => [split.by:"$" &]
loop output 'line [
loop line 'word -> prints pad word 12
print ""
]
- 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.
AutoHotkey
Alignment := "L" ; Options: L, R, C
Text =
( LTrim
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.
)
Loop, Parse, Text ; calculate column's width
If A_LoopField in $,`n
If (N > W)
W := N, N := 0
Else
N := 0
Else
++N
Width := ++W
Loop, Parse, Text, `n ; process each line
{
Words := StrSplit(A_LoopField, "$")
For i, Word in Words ; process each word
Line .= Align(Word, Alignment, Width)
Result .= RTrim(Line) . "`n"
Line := ""
}
Clipboard := Result ; present results
MsgBox, The results are in the Clipboard
Align(Pal, How, Width) { ; function for alignment
Length := StrLen(Pal)
If (How = "L")
Return Pal . Spc(Width - Length)
Else If (How = "R")
Return Spc(Width - Length) . Pal
Else If (How = "C")
Return Spc((Width - Length)//2) . Pal . Spc(Width - Length - (Width - Length)//2)
}
Spc(Number) { ; function to concatenate space characters
Loop, %Number%
Ret .= A_Space
Return Ret
}
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.
AWK
# syntax: GAWK -f ALIGN_COLUMNS.AWK ALIGN_COLUMNS.TXT
BEGIN {
colsep = " " # separator between columns
report("raw data")
}
{ 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 {
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) }
Output:
report: raw 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. report: 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. report: 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. report: 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.
BaCon
DECLARE in$[] = { "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." }
OPTION DELIM "$"
CONST items = 6
SUB Print_In_Columns(style)
' Find widest column
FOR y = 0 TO items-1
FOR x = 1 TO AMOUNT(in$[y])
IF LEN(TOKEN$(in$[y], x)) > max THEN max = LEN(TOKEN$(in$[y], x))
NEXT
NEXT
' Print aligned
FOR y = 0 TO items-1
FOR x = 1 TO AMOUNT(in$[y])
PRINT ALIGN$(TOKEN$(in$[y], x), max+1, style);
NEXT
PRINT
NEXT
PRINT
END SUB
Print_In_Columns(0)
Print_In_Columns(1)
Print_In_Columns(2)
- 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.
BASIC
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$
Commodore BASIC
10 rem ********************************
20 rem print words in columns
30 rem commodore basic 2.0
40 rem ********************************
50 print chr$(14) : rem change to upper/lower case set
60 gosub 140 : rem find length of longest word
70 algn$ = "left"
80 gosub 260 : rem print aligned text
90 algn$ = "center"
100 gosub 260
110 algn$ = "right"
120 gosub 260
130 end
140 rem *** find length of longest word
150 mx=0
160 for i=1 to 6
170 read a$
180 n=1
190 for j=1 to len(a$)
200 if mid$(a$,j,1)<>"$" then n=n+1: goto 230
210 if mx<n then mx=n
220 n=1
230 next
240 next
250 return
260 rem print aligned text
270 restore : rem reset data read pointer
280 s$ = " "
290 print : print algn$;"-aligned"
300 c=1 : rem column counter
310 for i=1 to 6
320 read a$
330 n=1
340 for j=1 to len(a$)
350 if mid$(a$,j,1)<>"$" then n=n+1 : goto 380
360 gosub 440 : rem print word
370 n=1
380 next
390 if n>1 then gosub 440
400 next
410 print
420 return
430 rem ********* print word **********
440 b$ = mid$(a$,j-n+1,n-1)
450 b = len(b$)
460 if algn$ = "center" then 520
470 if algn$ = "right" then 570
480 if c+b<40 and c+mx>40 then print b$: c=1: return
490 if c+mx>40 then print : c=1
500 print b$;left$(s$,mx-b);: c=c+mx
510 return
520 if c+mx>40 then print : c=1
530 bb=(mx-b)/2 : ba=bb
540 if bb>1 and int(bb)=bb then ba=bb-1
550 print left$(s$,ba);b$;left$(s$,bb);: c=c+mx
560 return
570 if c+mx>40 then print : c=1
580 print left$(s$,mx-b);b$;: c=c+mx
590 return
600 rem *********** the words *********
610 data "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
620 data "are$delineated$by$a$single$'dollar'$character,$write$a$program"
630 data "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
640 data "column$are$separated$by$at$least$one$space."
650 data "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
660 data "justified,$right$justified,$or$center$justified$within$its$column"
Batch File
@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
- 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.
Beads
beads 1 program 'Align columns'
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.'''
var
words : array^2 of str
widths : array of num
calc div_line
var s = '+'
loop across:widths val:w
s = s & str_repeat('-',w) & '+'
log s
calc show_table(
justify
)
loop across:words index:i
var s = '|'
loop across:widths index:j val:w
var
word = words[i,j]
if word == U
word = ''
case justify
| RIGHT
s = s & pad_left(word,w)
| LEFT
s = s & pad_right(word,w)
| CENTER
w = w - str_len(word)
s = s & str_repeat(' ',idiv(w,2)) & word & str_repeat(' ',idiv(w,2)+mod(w,2))
s = s & '|'
log s
div_line
calc main_init
var w
split_lines_words (text, words, delim:'$')
loop across:words index:i
loop across:words[i] index:j
w = str_len(words[i,j])
widths[j] = max(w,widths[j])
loop across:[LEFT CENTER RIGHT] val:v
log "\n{v} justified\n"
div_line
show_table(v)
- 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.| | | | +----------+----------+----------+------+------+---------+----------+--------+-------+-------+------+----+
BQN
A function which returns a rectangular 2D array which represents the lines.
Split ← (⊢-˜+`׬)∘=⊔⊢
PadRow ← {
w‿t𝕊𝕩: # t → type.
# 0 → left
# 1 → right
# 2 → center
pstyle←t⊑⟨{0‿𝕩},{𝕩‿0},{⟨⌊𝕩÷2,⌈𝕩÷2⟩}⟩
𝕩{(⊣∾𝕨∾⊢)´(Pstyle 𝕩)/¨<w}¨(⌈´-⊢)≠¨𝕩
}
Align ← {{𝕨∾' '∾𝕩}´˘⍉" "‿𝕨⊸PadRow˘⍉>⟨""⟩‿0 PadRow '$' Split¨(@+10) Split 𝕩}
1 Align 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. "
┘
C
See Column Aligner/C
C#
Old version
Uses a delegate, which were added to the language in C# 2, to define left-, right-, or center-justified.
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);
}
}
}
Newer version
Uses features of newer versions, like LINQ, lambdas and switch expressions.
using System;
using System.Linq;
enum Justification { Left, Center, Right }
public class Program
{
static void Main()
{
string 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.";
AlignColumns(text, Justification.Left);
Console.WriteLine();
AlignColumns(text, Justification.Center);
Console.WriteLine();
AlignColumns(text, Justification.Right);
}
public static void AlignColumns(string text, Justification justification) =>
AlignColumns(text.Split(Environment.NewLine), justification);
public static void AlignColumns(string[] lines, Justification justification) =>
AlignColumns(lines.Select(line => line.Split('$')).ToArray(), justification);
public static void AlignColumns(string[][] table, Justification justification)
{
Console.WriteLine(justification + ":");
int columns = table.Max(line => line.Length);
var columnWidths =
Enumerable.Range(0, columns)
.Select(i => table.Max(line => i < line.Length ? line[i].Length : 0)
).ToArray();
foreach (var line in table) {
Console.WriteLine(string.Join(" ",
Enumerable.Range(0, line.Length)
.Select(i => justification switch {
Justification.Left => line[i].PadRight(columnWidths[i]),
Justification.Right => line[i].PadLeft(columnWidths[i]),
_ => line[i].PadLeft(columnWidths[i] / 2).PadRight(columnWidths[i])
})
));
}
}
}
- 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.
C++
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))
COBOL
identification division.
program-id. AlignColumns.
data division.
working-storage section.
*>-> Constants
78 MAX-LINES value 6.
78 MAX-LINE-SIZE value 66.
78 MAX-COLUMNS value 12.
78 MAX-COLUMN-SIZE value 16.
*>-> Indexes
01 w-idx pic is 9(2).
01 w-idy pic is 9(2).
01 w-pos pic is 9(3).
*>-> Data structures
01 w-lines.
05 w-line pic is x(MAX-LINE-SIZE) occurs MAX-LINES.
01 w-column-sizes.
05 w-column-size pic is 99 occurs MAX-COLUMNS value zeros.
01 w-matrix.
05 filler occurs MAX-LINES.
10 filler occurs MAX-COLUMNS.
15 w-content pic is x(MAX-COLUMN-SIZE).
*>-> Output
01 w-line-out pic is x(120).
*>-> Data alignment
01 w-alignment pic is x(1).
88 alignment-left value is "L".
88 alignment-center value is "C".
88 alignment-right value is "R".
procedure division.
main.
move "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" to w-line(1)
move "are$delineated$by$a$single$'dollar'$character,$write$a$program" to w-line(2)
move "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" to w-line(3)
move "column$are$separated$by$at$least$one$space." to w-line(4)
move "Further,$allow$for$each$word$in$a$column$to$be$either$left$" to w-line(5)
move "justified,$right$justified,$or$center$justified$within$its$column." to w-line(6)
perform calculate-size-columns
set alignment-left to true
perform show-content
set alignment-center to true
perform show-content
set alignment-right to true
perform show-content
goback
.
calculate-size-columns.
perform
varying w-idx from 1 by 1
until w-idx > MAX-LINES
unstring w-line(w-idx) delimited by "$" into w-content(w-idx, 1), w-content(w-idx, 2),
w-content(w-idx, 3), w-content(w-idx, 4), w-content(w-idx, 5), w-content(w-idx, 6),
w-content(w-idx, 7), w-content(w-idx, 8), w-content(w-idx, 9), w-content(w-idx, 10),
w-content(w-idx, 11), w-content(w-idx, 12),
perform
varying w-idy from 1 by 1
until w-idy > MAX-COLUMNS
if function stored-char-length(w-content(w-idx, w-idy)) > w-column-size(w-idy)
move function stored-char-length(w-content(w-idx, w-idy)) to w-column-size(w-idy)
end-if
end-perform
end-perform
.
show-content.
move all "-" to w-line-out
display w-line-out
perform
varying w-idx from 1 by 1
until w-idx > MAX-LINES
move spaces to w-line-out
move 1 to w-pos
perform
varying w-idy from 1 by 1
until w-idy > MAX-COLUMNS
call "C$JUSTIFY" using w-content(w-idx, w-idy)(1:w-column-size(w-idy)), w-alignment
move w-content(w-idx, w-idy) to w-line-out(w-pos:w-column-size(w-idy))
compute w-pos = w-pos + w-column-size(w-idy) + 1
end-perform
display w-line-out
end-perform
.
- 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.
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.
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))
D
void main() {
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("$")).array;
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 (immutable just; TypeTuple!(leftJustify, center, rightJustify))
foreach (immutable 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.
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;
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.
EasyLang
global width inp$[] .
proc read . .
repeat
inp$ = input
until inp$ = ""
inp$[] &= inp$
ar$[] = strsplit inp$ "$"
for s$ in ar$[]
width = higher width len s$
.
.
.
read
#
proc out mode . .
for inp$ in inp$[]
ar$[] = strsplit inp$ "$"
for s$ in ar$[]
spc = width - len s$ + 1
if mode = 1
write s$
for i to spc
write " "
.
elif mode = 2
for i to spc
write " "
.
write s$
elif mode = 3
for i to spc div 2
write " "
.
write s$
for i to spc - spc div 2
write " "
.
.
.
print ""
.
.
out 1
print ""
out 2
print ""
out 3
#
input_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.
Elixir
The String module of Elixir doesn't have the function of the center position adjusting. It calls and processes the function of 'Erlang'.
defmodule Align do
def columns(text, alignment) do
fieldsbyrow = String.split(text, "\n", trim: true)
|> Enum.map(fn row -> String.split(row, "$", trim: true) end)
maxfields = Enum.map(fieldsbyrow, fn field -> length(field) end) |> Enum.max
colwidths = Enum.map(fieldsbyrow, fn field -> field ++ List.duplicate("", maxfields - length(field)) end)
|> List.zip
|> Enum.map(fn column ->
Tuple.to_list(column) |> Enum.map(fn col-> String.length(col) end) |> Enum.max
end)
Enum.each(fieldsbyrow, fn row ->
Enum.zip(row, colwidths)
|> Enum.map(fn {field, width} -> adjust(field, width, alignment) end)
|> Enum.join(" ") |> IO.puts
end)
end
defp adjust(field, width, :Left), do: String.pad_trailing(field, width)
defp adjust(field, width, :Right), do: String.pad_leading(field, width)
defp adjust(field, width, _), do: :string.centre(String.to_charlist(field), width)
end
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.
"""
Enum.each([:Left, :Right, :Center], fn alignment ->
IO.puts "\n# #{alignment} Column-aligned output:"
Align.columns(text, alignment)
end)
- 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.
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
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.
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. --------------------------------------------------------------------------------------------------------
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
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...
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
Fortran
For the general situation, a utility has no knowledge of the maximum number of fields in a record nor the maximum length of a record, still less knowledge of the sizes of the fields in the records. Decent file systems (for example, that of the Burroughs 6700) make available the MaxRecordLength of a file when a file is opened, but many systems are less than helpful. It is possible to open a file as UNFORMATTED and then simply read sequences of binary data to be interpreted to taste, but in the ASCII world that means deciding on record markers being CR, CRLF, LF, or LFCR and I have encountered files with mixtures... In any case, a file with a fixed record length will likely not contain any such markers.
The plan here is to read the file to find out. But, given that the maximum record length is unknown, reading records into some storage area is problematical. Some systems can create a "string" variable via the read statement that will be of the proper size, but older Fortran works always with storage sizes fixed at compile time. However, after F77 started being extended, a common extension was the Q-element in FORMAT statements, which instead of interpreting the content of a record, reports instead the number of characters yet unread in a record. Thus, a statement like READ(in,"(Q)") L
will read a record of input and the first action is to place in variable L the number of characters yet to be processed of that record. Since the content of the record is not being transferred, there is no need for a CHARACTER area of sufficient size to receive all of it. Indeed here, nothing is read. As for the LF/CRLF/LFCR/CR issue, with FORMATTED input the file system makes its decision and presents record content without incorporating such out-of-context data.
When data are being read into a CHARACTER variable, once the receiver is filled subsequent data in a long record will be ignored, and if the input record was smaller than the variable, trailing spaces will be supplied to fill out the variable. It is for this reason that the read statement is READ (IN,11,END = 20) L,ACARD(1:L)
so that, on-the-fly, the length of the record is determined, and then only that number of characters are placed in ACARD with no (possibly large number of) trailing spaces being appended. Naturally, subsequent inspection of ACARD will have to be careful not to look beyond character L, where detritus from previous usage will languish.
Once the main programme has ascertained the maximum record length, subroutine RAKE can be invoked with this as a parameter. From F90 on, as introduced by Algol in the 1960s, functions and subroutines have been allowed to declare arrays of a size specified by a variable and so the "surely big enough" issue is reduced. Thus, given a maximum length of M, a record containing M field delimiters can represent M + 1 fields, all null. The last field's delimiter is the end-of-record, so one more. It is also possible to use ALLOCATE(...) to request storage of suitable dimension for a variable within a routine, but that introduces verbiage. So, a programme can request just enough storage for its particular tasks and thereby possibly succeed on a problem too large for an always-big-enough storage scheme, but on the other hand, the fixed storage allocation scheme doesn't suddenly run out in the middle of a job.
Accordingly, a second scan of the records of the text file can be made, with a view to ascertaining the maximum widths for the first, second, etc. columns. This is done by storing in array C the positions of the delimiters in the text, so the content of a field i on a record will be starting with C(I - 1) + 1, and ending with C(I) - 1, - that is, the first character following a delimiter to the last character before a delimiter. In other words, the delimiter is not a part of the field's content. For convenience in this, C(0) = 0, since the first field is number one, and the last field's delimiter is one past the end of the record. Having an array start with non-default bounds is a feature of F90, similarly the array assignment that tracks the maximum field widths in array W. The specification makes no call for leading or trailing spaces in a field's content to be trimmed; if it did then two sets of fingers would be used to mark the first and last position of each text. Happily, there is also no call to recognise quoted texts, that might contain delimiter characters that are not delimiters.
Equipped at last with knowledge of each column's maximum width, yet another pass can be made through the file to produce the output. A feature of the format code Aw is that text is aligned to the right within the width of w. So, concoct a FORMAT text with suitable Aw entries, also augmenting the width by one for each column to meet the requirement that each column's content is separated from the others by at least one space. This concoction is easy enough, and could be improved by taking advantage of the "factoring" that format statements allow so that for example "A7,A7" can be replaced by "2A7", and further, bracketing of sequences is allowed and with repeat counts for them also. Alas, finding the minimum sequence is in general a very difficult problem, so no attempt is made. As for "sufficient storage" for the FORMAT variable, a two-digit width specification seems sufficient so each field's format code would be "Add," - four characters. Only later Fortran allows the I0 format code, meaning that an integer will be written only with sufficient digits, not a fixed "sufficiency" of digits. A pity the code for this isn't just "I" rather than "I0" which implies a width of zero.
A difficulty now arises in terminating the format text with the closing bracket. This is done by searching for the sequence ", " and replacing the comma by the closing bracket. This is present only because format 21 specifies <MF> as a repeat count. If it were say 666 instead, after the last W value was written the format processing would cycle back to its next repetition, write out an "A", then stop since there is no W value to write via the "I0" format code. Thus, the format text ends ",A" and the INDEX fails to find the desired ", ". It could instead search for ",A " (just ",A" would stop on the second field's format code) but ", " seems clear. The <MF> usage is standard only for recent Fortran. Formatted output opportunities are many and options numerous. Other schemes could be used, such as the write statement specifying the text literals in its items, but that would require an implied-DO output list and it seemed nicer to be able to use the array specification W(1:MF) instead.
Given a FORMAT text that produces output in aligned columns makes it easy enough to meet the other requirements. To cause texts to be aligned left, append sufficient spaces to each output text, and for centred text, half that number. This relies on the special intrinsic function REPEAT(text,n) returning a varying number of characters - CHARACTER functions have to return a fixed number of characters, until the standardisation of varying-length strings in F2003 et seq. Earlier Fortrans lack the REPEAT function, but its effect can be gained via something like CHARACTER*66 SPACE, where SPACE is set to spaces, and SPACE(1:N) is used where REPEAT(" ",N) is desired. And if messing with variable FORMAT is unwanted, the REPEAT scheme can be used for the right-justified output also.
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.
Every line of output starts with a space, and if it were to be sent to a lineprinter, this would be used as the carriage control character (meaning, advance one line then print the rest) - the first column does not need to be set off by one space from the previous column, but rather than devise special treatment it is spaced off anyway. The free-format output statements also start with a space. Output:
6 Recs, longest rec. length is 66 Align Left Format(A11,A11,A11,A7,A7,A10,A11,A9,A8,A8,A7,A5,A1) 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 Format(A11,A11,A11,A7,A7,A10,A11,A9,A8,A8,A7,A5,A1) 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 Format(A11,A11,A11,A7,A7,A10,A11,A9,A8,A8,A7,A5,A1) 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.
FreeBASIC
' FB 1.05.0 Win64
Sub Split(s As String, sep As String, result() As String)
Dim As Integer i, j, count = 0
Dim temp As String
Dim As Integer position(Len(s) + 1)
position(0) = 0
For i = 0 To Len(s) - 1
For j = 0 To Len(sep) - 1
If s[i] = sep[j] Then
count += 1
position(count) = i + 1
End If
Next j
Next i
position(count + 1) = Len(s) + 1
Redim result(count)
For i = 1 To count + 1
result(i - 1) = Mid(s, position(i - 1) + 1, position(i) - position(i - 1) - 1)
Next
End Sub
Sub CSet(buffer As String, s As Const String)
Dim As Integer bLength = Len(buffer)
Dim As Integer sLength = Len(s)
Dim As Integer diff, lSpaces
If sLength >= bLength Then
LSet buffer, s
Else
diff = bLength - sLength
lSpaces = diff \ 2
LSet buffer, Space(lSpaces) + s
End If
End Sub
Dim lines() As String
Dim count As Integer = 0
Open "align_columns.txt" For Input As #1
While Not Eof(1)
Redim Preserve lines(count)
Line Input #1, lines(count)
count +=1
Wend
Close #1
Dim As Integer i,j, length, numColumns = 0
Dim As Integer numLines = UBound(lines) + 1
Dim fields() As String
' Work out the maximum number of columns
For i = 0 To numLines - 1
Erase fields
Split RTrim(lines(i), "$"), "$", fields()
length = UBound(fields) + 1
If length > numColumns Then numColumns = length
Next
' Split lines into fields and work out maximum size of each column
Dim matrix(numLines - 1, numColumns - 1) As String
Dim columnSizes(numColumns - 1) As Integer
For i = 0 To numLines - 1
Erase fields
Split RTrim(lines(i), "$"), "$", fields()
For j = 0 To UBound(fields)
matrix(i, j) = fields(j)
length = Len(fields(j))
If length > columnSizes(j) Then columnSizes(j) = length
Next j
Next i
Dim buffer As String
'Separate each column by 2 spaces
Open "align_left_columns.txt" For Output As #1
Open "align_right_columns.txt" For Output As #2
Open "align_center_columns.txt" For Output As #3
For i = 0 To UBound(matrix, 1)
For j = 0 To UBound(matrix, 2)
buffer = Space(columnSizes(j))
LSet buffer, matrix(i, j)
Print #1, buffer;
RSet buffer, matrix(i, j)
Print #2, buffer;
CSet buffer, matrix(i, j)
Print #3, buffer;
If j < UBound(matrix, 2) Then
Print #1, " "; : Print #2, " "; : Print #3, " ";
End If
Next j
Print #1, : Print #2, : Print #3,
Next i
Close #1 : Close #2 : Close #3
- Output:
--- align_columns.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_left_columns.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_right_columns.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_center_columns.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.
FutureBasic
Note: FB's NSLog, used for demonstrations, does not have a center alignment provision. However FB allows advanced alignment and text formatting in normal application development. Simple right and left alignment are shown here.
include "NSLog.incl"
local fn AlignColumn
NSUInteger i
CFStringRef testStr = @"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."
CFArrayRef temp = fn StringComponentsSeparatedByString( testStr, @"$" )
CFMutableArrayRef arr = fn MutableArrayWithArray( temp )
NSUInteger count = fn ArrayCount( arr )
ptr a(50)
NSLog( @"\nLeft aligned:\n" )
NSUInteger lineCheck = 1
for i = 0 to count -1
a( lineCheck ) = (ptr)fn StringUTF8String( arr[i] )
if ( lineCheck == 9 )
NSLog( @"%-12s %-11s %-12s %-11s %-12s %-12s %-12s %-12s %-12s", a(1),a(2),a(3),a(4),a(5),a(6),a(7),a(8),a(9) )
lineCheck = 1
else
lineCheck++
end if
next
NSLog( @"\n\nRight aligned:\n" )
lineCheck = 1
for i = 0 to count -1
a( lineCheck ) = (ptr)fn StringUTF8String( arr[i] )
if ( lineCheck == 9 )
NSLog( @"%12s %11s %12s %11s %12s %12s %12s %12s %12s", a(1),a(2),a(3),a(4),a(5),a(6),a(7),a(8),a(9) )
lineCheck = 1
else
lineCheck++
end if
next
end fn
fn AlignColumn
HandleEvents
- 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.
Gambas
Click this link to run this code
Public Sub Main() 'Written in Gambas 3.9.2 as a Command line Application - 15/03/2017
Dim siCount, siCounter, siLength As Short 'Counters
Dim siLongest As Short = -1 'To store the longest 'Word'
Dim sLine, sRows As New String[] 'Arrays
Dim sTemp, sAlign As String 'Temp strings
Dim sInput As String = "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." 'Main string (with End Of Line characters added)
For Each sTemp In Split(sInput, "\n") 'For each Line (split by End of Line character)..
sLine.add(sTemp) 'Add the Line to sLine array
Next
For siCount = 0 To sLine.Max 'For each of Lines in the array..
For Each sTemp In Split(sLine[siCount], "$") 'For each 'Word' in the Line (Split by the '$')
siLength = Len(sTemp) 'Store the length of the current 'Word'
If siLength > siLongest Then siLongest = siLength 'Make sure siLength has the length of the longest 'Word'
sRows.add(Trim(sTemp)) 'Create an array of the 'Words'
Next
sRows.add("\n") 'Add a End Of Line character to the sRows array
Next
For siCounter = 0 To 2 'For each alignment (Left, Right and Centre)
For Each sTemp In sRows 'For each 'Word' in the sRows array..
If sTemp = "\n" Then 'If it's a End Of Line character then..
Print 'Print
Continue 'Jump to the next iteration of the For Next Loop
Endif
If siCounter = 0 Then Print sTemp & Space(siLongest - Len(sTemp)); 'Print control for Left align
If siCounter = 1 Then Print Space(siLongest - Len(sTemp)) & sTemp; 'Print control for Right align
If siCounter = 2 Then 'Print control for Centre align
siCount = (siLongest - Len(sTemp)) / 2 'Difference between the length of the longest 'Word' and the current 'Word' / 2
sAlign = Space(siCount) & sTemp & Space(siCount) 'Put the string together for printing
If Len(sAlign) < siLongest Then sAlign &= " " 'Check it's the correct length if not add a space on the end
Print sAlign; 'Print the 'Word'
Endif
Next
Print 'Print an empty line between each alignment list
Next
End
- 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.
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.
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.
Harbour
PROCEDURE Main()
LOCAL a := { "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." }
LOCAL e, nMax
// remove trailing dollars
AEval( a, {|e,n| Iif( Right(e,1)=="$", a[n] := hb_StrShrink( e, 1 ), NIL ) } )
// find max word length
nMax := 0
AEval( a, {|e| AEval( hb_Atokens( e, "$"), {|i| nMax := Max( nMax, Len(i) )} ) } )
nMax++
// start printing, padding words as needed
?
? "----Left aligned columns----"
FOR EACH e IN a
?
AEval( hb_Atokens( e, "$"), {|i| QQout( PadR(i, nMax) )} )
NEXT
?
? "----Center aligned columns----"
FOR EACH e IN a
?
AEval( hb_Atokens( e, "$"), {|i| QQout( PadC(i, nMax) )} )
NEXT
?
? "----Right aligned columns----"
FOR EACH e IN a
?
AEval( hb_Atokens( e, "$"), {|i| QQout( PadL(i, nMax) )} )
NEXT
RETURN
Output:
----Left aligned columns----
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 columns----
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 columns----
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.
Haskell
import Data.List (unfoldr, transpose)
import Control.Arrow (second)
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:
*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.
Or, using Text and its functions as an alternative to [Char] strings:
import Prelude as P
import Data.Text as T
(Text, pack, unpack, splitOn, unlines, unwords, length,
justifyLeft, justifyRight, center)
import Data.List (transpose, zip, maximumBy)
import Data.Ord (comparing)
rows :: [[Text]]
rows =
(splitOn (pack "$") . pack) <$>
[ "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."
]
cols :: [[Text]]
cols =
transpose $
((++) <*>
(flip P.replicate (pack []) .
(-) (maximum (P.length <$> rows)) . P.length)) <$>
rows
main :: IO ()
main =
mapM_ putStrLn $
[ (\cols f ->
(unpack . T.unlines) $
T.unwords <$> transpose ((\(xs, n) -> f (n + 1) ' ' <$> xs) <$> cols))
(zip cols ((T.length . maximumBy (comparing T.length)) <$> cols))
] <*>
[justifyLeft, justifyRight, center]
- 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.
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.
Icon and Unicon
An argument of left, center, or right controls the column alignment. The default is left-alignment.
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. ->
J
Here, we rely on J's built-in formatting mechanism for boxed arrays, with spaces to separate the columns.
(J's 9!:n series of conjunctions queries (even) or sets (odd) session parameters. 9!:6 queries the box display characters, and 9!:7 sets them. Here, we use spaces with 9!:7 (discarding the blank rows). Meanwhile 9!:17 determines whether box contents are left justified, center justified or right justified, and we also use that. There's some additional discussion of this approach on the talk page.)
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.
Java
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;
}
}
}
JavaScript
Imperative
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);
Functional
//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');
};
Or (ES5) using transpose and zipWith:
(function (strText) {
'use strict';
// [[a]] -> [[a]]
function transpose(lst) {
return lst[0].map(function (_, iCol) {
return lst.map(function (row) {
return row[iCol];
})
});
}
// (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('$');
}),
lngCols = widest(lstRows),
lstCols = transpose(lstRows.map(function (r) {
return fullRow(r, lngCols)
})),
lstColWidths = lstCols.map(widest);
// THREE PARAGRAPHS, WITH VARIOUS WORD COLUMN ALIGNMENTS:
return [eLeft, eRight, eCenter]
.map(function (eAlign) {
var fPad = function (n, lstWords) {
return padWords(n, lstWords, eAlign);
};
return transpose(
zipWith(fPad, lstColWidths, lstCols)
)
.map(unwords);
})
.map(unlines)
.join('\n\n');
})(
"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."
);
- 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.
jq
The key to the following implementation is the filter named "transpose", which is defined to work on a possibly jagged matrix. It is provided as a built-in in jq 1.5 and later.
# 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.
Jsish
From Javascript ES5 entry.
/* Align columns, in Jsish */
function alignColumns(phrases:array, just:string) {
var x, y, max, diff, left, right, cols=0;
for(x=0; x<phrases.length; x++) {
phrases[x] = phrases[x].split("$");
if (phrases[x].length>cols) cols=phrases[x].length;
}
for (x=0; x<cols; x++) {
max = 0;
for (y=0; y<phrases.length; y++) if (phrases[y][x] && max<phrases[y][x].length) max = phrases[y][x].length;
for (y=0; y<phrases.length; y++) {
if (phrases[y][x]) {
diff = (max-phrases[y][x].length)/2;
left = " ".repeat(Math.floor(diff));
right = " ".repeat(Math.ceil(diff));
if (just == "left") { right += left; left=""; }
if (just == "right") { left += right; right=""; }
phrases[y][x] = left + phrases[y][x] + right;
}
}
}
for (x=0; x<phrases.length; x++) phrases[x] = phrases[x].join(" ");
phrases = phrases.join("\n");
return phrases;
}
if (Interp.conf('unitTest')) {
var phrases = ["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 (var just of ['left', 'center', 'right']) {
var trial = phrases.slice(0);
puts(just);
puts(alignColumns(trial, just), '\n');
}
}
- Output:
prompt$ jsish --U alignColumns.jsi 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.
Julia
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. ---------------------------------------------------------------------------------------------------------
Kotlin
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Paths
enum class AlignFunction {
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, l: Int): String
}
/** Aligns fields into columns, separated by "|".
* @constructor Initializes columns aligner from lines in a list of strings.
* @property lines Lines in a single string. Empty string does form a column.
*/
class ColumnAligner(val lines: List<String>) {
operator fun invoke(a: AlignFunction) : String {
var result = ""
for (lineWords in words) {
for (i in lineWords.indices) {
if (i == 0)
result += '|'
result += a(lineWords[i], column_widths[i])
result += '|'
}
result += '\n'
}
return result
}
private val words = arrayListOf<Array<String>>()
private val column_widths = arrayListOf<Int>()
init {
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
} else {
column_widths[i] = Math.max(column_widths[i], lineWords[i].length)
}
}
}
}
}
fun main(args: Array<String>) {
if (args.isEmpty()) {
println("Usage: ColumnAligner file [L|R|C]")
return
}
val ca = ColumnAligner(Files.readAllLines(Paths.get(args[0]), StandardCharsets.UTF_8))
val alignment = if (args.size >= 2) args[1] else "L"
when (alignment) {
"L" -> print(ca(AlignFunction.LEFT))
"R" -> print(ca(AlignFunction.RIGHT))
"C" -> print(ca(AlignFunction.CENTER))
else -> System.err.println("Error! Unknown alignment: " + alignment)
}
}
Lambdatalk
The input data is a sequence of characters where words are supposed to be separated by $ and lines be ended by \$. A HTML table is used to format the output left, centered or right justified.
{def 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.}
-> txt
{def columns // function's name
{def columns.r // loop function
{lambda {:just :a :b}
{if {A.empty? :a} // end of loop
then :b // return the string
else {columns.r :just // justification
{A.rest :a}. // loop on next char
{if {W.equal? {A.first :a} \} // if end of line
then < tr> :b // open a table row
else {if {W.equal? {A.first :a} $} // if space between words
then < td style="text-align::just;">:b // open a table data with justif
else {A.first :a}:b }} } }}} // else add character
{lambda {:just :txt} // main function
{table // open an HTML table
{columns.r // call the loop function
:just // justification
{A.reverse {A.split ${:txt}}} // split and reverse
. // end point
}}}}
-> columns
{columns left 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..
{columns center txt} and {columns right txt} outputs can be seen in this website: http://lambdaway.free.fr/lambdawalks/?view=align_columns
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.
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
Lua
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")
M2000 Interpreter
Module Align_Columns {
a$={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 cr$=chr$(13), lf$=chr$(10)
def c1=0, cmax=0, p1=-1, i
flush ' empty stack
for i=1 to len(a$)
select case mid$(a$,i,1)
case "$", cr$
if p1<>-1 then data (p1, c1): p1=-1: cmax=max(c1,cmax):c1=0
case lf$
data (-1,0) ' push to end of stack an array of two items (a tuple in m2000)
else case
if p1=-1 then p1=i :c1=1 else c1++
end select
next
if p1<>-1 then push (p1, c1): cmax=max(c1,cmax):c1=0
\\ so now stack of values hold all tuples.
Dim Words(), AlignType$(1 to 3)
AlignType$(1)=lambda$ (a$,wd)->field$(a$, wd)
AlignType$(2)=lambda$ (a$,wd)->{
a$=left$(a$, wd)
=left$(string$(" ", (len(a$)-wd) div 2)+a$+string$(" ",wd),wd)
}
AlignType$(3)= lambda$ (a$,wd)->format$("{0:"+str$(-wd)+"}", a$)
\\ [] return a stack object, reference and leave current stack of values a new stack
\\ Array( stack_object) empty the stack object moving items to an array
Words()=Array([])
document export$
def aline$
cmax++ ' add one space
For al=1 to 3
For i=0 to len(Words())-1
if Words(i)(0)=-1 then
' we use rtrim$() to cut trailing spaces
export$=rtrim$(aline$)+cr$+lf$ : aline$=""
else
aline$+=AlignType$(al)(mid$(a$,Words(i)(0), Words(i)(1)),cmax)
end if
next i
next
\\ export to clipboard
Clipboard export$
Rem Form 140, 60
Rem Print #-2, export$ ' render text to console without using console's columns
}
Align_Columns
- 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.
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).
Mathematica / Wolfram Language
TableForm[StringSplit[StringSplit[a,"\n"],"$"],TableAlignments -> Center]
MATLAB / Octave
center-justified formatting is not implemented here
function r = align_columns(f)
fid = fopen('align_column_data.txt', 'r');
D = {};
M = 0;
while ~feof(fid)
s = fgetl(fid);
strsplit(s,'$');
m = diff([0,find(s=='$')])-1;
M = max([M,zeros(1,length(m)-length(M))], [m,zeros(1,length(M)-length(m))]);
D{end+1}=s;
end
fclose(fid);
fprintf(1,'%%-- right-justified --%%\n')
FMT = sprintf('%%%ds ',M);
for k=1:length(D)
d = strsplit(D{k},'$');
fprintf(1,FMT,d{:});
fprintf(1,'\n');
end
fprintf(1,'%%-- left-justified --%%\n')
FMT = sprintf('%%-%ds ',M);
for k=1:length(D)
d = strsplit(D{k},'$');
fprintf(1,FMT,d{:});
fprintf(1,'\n');
end
end;
- Output:
align_columns %-- 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. %-- 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.
MiniScript
Alignment = {"left": -1, "center": 0, "right": 1}
Align = {}
Align.load = function(contents)
self.lines = contents.split(char(13))
self.rows = []
self.numColumns = 0
for line in self.lines
columns = line.split("$")
if columns.len > self.numColumns then self.numColumns = columns.len
self.rows.push(columns)
end for
self.widths = []
for col in range(0, self.numColumns - 1)
maxWidth = 0
for line in self.rows
if col > line.len - 1 then continue
if line[col].len > maxWidth then maxWidth = line[col].len
end for
self.widths.push(maxWidth)
end for
end function
Align.__getField = function(word, width, alignment)
if alignment == Alignment.left then return (word + " " * width)[:width]
if alignment == Alignment.right then return (" " * width+word)[-width:]
if alignment == Alignment.center then
leftMargin = floor((width - word.len) / 2)
return (" " * leftMargin + word + " " * width)[:width]
end if
end function
Align.output = function(alignment)
for line in self.rows
for c in range(0, line.len - 1)
print self.__getField(line[c], self.widths[c], alignment) + " ", ""
end for
print
end for
end function
txt = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$" + char(13)
txt += "are$delineated$by$a$single$'dollar'$character,$write$a$program" + char(13)
txt += "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" + char(13)
txt += "column$are$separated$by$at$least$one$space." + char(13)
txt += "Further,$allow$for$each$word$in$a$column$to$be$either$left$" + char(13)
txt += "justified,$right$justified,$or$center$justified$within$its$column."
Align.load(txt)
print "Left alignment:"
Align.output(Alignment.left)
print
print "Right alignment:"
Align.output(Alignment.right)
print
print "Centered: "
Align.output(Alignment.center)
- Output:
>miniscript.exe align-columns.ms Left alignment: 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 alignment: 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: 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.
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
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
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.
Nim
from strutils import splitLines, split
from sequtils import mapIt
from strfmt import format, write
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(it.split '$')
var maxs = newSeq[int](max words.mapIt(it.len))
for line in words:
for j,w in line:
maxs[j] = max(maxs[j], w.len+1)
for i, align in ["<",">","^"]:
echo(["Left", "Right", "Center"][i], " column-aligned output:")
for line in words:
for j,w in line:
stdout.write(w.format align & $maxs[j])
stdout.write "\n"
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.
Nit
Source: the official Nit’s repository
# Task: Align columns
#
# Uses `Text::justify` from the standard library.
module align_columns
fun aligner(text: String, left: Float)
do
# Each row is a sequence of fields
var rows = new Array[Array[String]]
for line in text.split('\n') do
rows.add line.split("$")
end
# Compute the final length of each column
var lengths = new Array[Int]
for fields in rows do
var i = 0
for field in fields do
var fl = field.length
if lengths.length <= i or fl > lengths[i] then
lengths[i] = fl
end
i += 1
end
end
# Process each line and align each field
for fields in rows do
var line = new Array[String]
var i = 0
for field in fields do
line.add field.justify(lengths[i], left)
i += 1
end
print line.join(" ")
end
end
var 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."""
aligner(text, 0.0)
aligner(text, 1.0)
aligner(text, 0.5)
- 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.
Oberon-2
works with oo2c version 2.
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.
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.
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);
;;
Oforth
import: mapping
import: file
: <<nbl \ stream n -- stream
#[ ' ' <<c ] times ;
String method: justify( n just -- s )
| l m |
n self size - dup ->l 2 / ->m
String new
just $RIGHT if=: [ l <<nbl self << return ]
just $LEFT if=: [ self << l <<nbl return ]
m <<nbl self << l m - <<nbl
;
: align( file just -- )
| lines maxsize |
#[ wordsWith( '$' ) ] file File new map ->lines
0 #[ apply( #[ size max ] ) ] lines apply ->maxsize
#[ apply( #[ justify( maxsize , just) . ] ) printcr ] lines apply
;
- Output:
>"align.txt" $LEFT align 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 >
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.
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 ---------------------------
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
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}
Pascal
See Delphi
modified to
program Project1;
{$H+}//Use ansistrings
uses
Classes,
SysUtils,
StrUtils;
procedure AlignByColumn(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: TStringList;
TextLines: array of TStringList;
OutPutString, EmptyString, Item: string;
MaxLength, i, j: Int32;
begin
try
MaxLength := 0;
TextLine := TStringList.Create;
TextLine.Text := TextToAlign;
setlength(Textlines, TextLine.Count);
for i := 0 to TextLine.Count - 1 do
begin
Textlines[i] := TStringList.Create;
Textlines[i].Text := AnsiReplaceStr(TextLine[i], '$', #$D#$A);
end;
for i := 0 to High(TextLines) do
for j := 0 to Textlines[i].Count - 1 do
if MaxLength < Length(TextLines[i][j]) then
MaxLength := Length(TextLines[i][j]);
if MaxLength > 0 then
MaxLength := MaxLength + 2; // Add two empty spaces to it
for i := 0 to High(TextLines) do
begin
OutPutString := '';
for j := 0 to Textlines[i].Count - 1 do
begin
EmptyString := StringOfChar(' ', MaxLength);
if j <> 0 then
EmptyString[1] := '|';
Item := TextLines[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;
writeln(OutPutString);
end;
finally
writeln;
FreeAndNil(TextLine);
for i := High(TextLines) downto 0 do
FreeAndNil(TextLines[i]);
end;
end;
begin
AlignByColumn(taLeftJustify);
AlignByColumn(taCenter);
AlignByColumn(taRightJustify);
end.
- 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.
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
Phix
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 = 1, delim 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 = 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 -- (PL if I'd written this, I'd have n-floor(n/2) on the rhs) return repeat(' ', floor(n/2)) & s & repeat(' ', floor(n/2+0.5)) end if end function procedure AlignColumns() integer llij sequence lines, li sequence maxlens = {} lines = repeat(0,length(data)) for i=1 to length(data) do li = split(data[i],'$') lines[i] = li if length(li)>length(maxlens) then maxlens &= repeat(0,length(li)-length(maxlens)) end if for j=1 to length(li) do llij = length(li[j]) if llij>maxlens[j] then maxlens[j] = llij end if end for end for for a=-1 to 1 do -- (alignment = left/centre/right) for i=1 to length(lines) do for j=1 to length(lines[i]) do puts(1, align(lines[i][j],maxlens[j],a) & ' ') end for puts(1,'\n') end for puts(1,'\n') end for if getc(0) then end if end procedure AlignColumns()
- 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.
Phixmonti
include ..\Utilitys.pmt
0 40 repeat var gap
( "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." )
len var lines
def alignWords /# -1/0/1 for left/center/right #/
>ps
lines for
get len for >ps
tps get gap ps> get nip 1 +
tps -1 == if -1 * align else
tps 0 == if tostr align else
tps 1 == if align else
drop drop "Wrong!" exitfor
endif endif endif
print
endfor
drop
nl
endfor
ps> drop
enddef
lines for var i
i get "$" " " subst split
len for var j
j get len dup
gap j get rot
< if swap j set else swap drop endif var gap drop
endfor
i set
endfor
-1 alignWords nl
0 alignWords nl
1 alignWords nl
drop
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(array_key_exists($col, $fields) ? $fields[$col] : 0));
foreach ($fieldsbyrow as &$fields)
$fields[$col] = str_pad(array_key_exists($col, $fields) ? $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);
?>
Picat
import util.
main =>
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.",
Lines = split(Text,"\n"),
Lines = [Line1|_],
N = len(split(strip(Line1,"$ "), "$")), % number of columns
WidthArr = {0 : _ in 1..N},
foreach (Line in Lines)
Words = split(strip(Line,"$ "), "$"),
foreach ({I,Word} in zip(1..N, Words))
WidthArr[I] := max(WidthArr[I], len(Word))
end
end,
foreach (I in 1..N)
WidthArr[I] := WidthArr[I]+1 % separate cols by at least one space
end,
foreach (Align in [left, right, center])
output_lines(Lines,N,WidthArr,Align),
nl,nl
end.
output_lines(Lines,N,WidthArr,Align) =>
foreach (Line in Lines)
Words = split(strip(Line,"$ "), "$"),
foreach ({I,Word} in zip(1..N, Words))
output_word(Word,WidthArr[I],Align)
end,
nl
end.
output_word(Word,Width,left) =>
printf("%-*s",Width,Word).
output_word(Word,Width,right) =>
printf("%*s",Width,Word).
output_word(Word,Width,_) =>
Pad = len(Word)-Width,
Pad1 is Pad div 2,
Pad2 is Pad-Pad1,
printf("%*s%s%*s",Pad1,"",Word,Pad2,"").
- 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.
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.
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;
PowerShell
$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 *
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.
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 .
PureBasic
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
Python
Procedural
Using f-strings
from itertools import zip_longest
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()]
widths = [max(len(word) for word in col)
for col in zip_longest(*parts, fillvalue='')]
for justify in "<_Left ^_Center >_Right".split():
j, jtext = justify.split('_')
print(f"{jtext} column-aligned output:\n")
for line in parts:
print(' '.join(f"{wrd:{j}{wdth}}" for wdth, wrd in zip(widths, line)))
print("- " * 52)
- 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. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Using StringIO
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])
- 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.
Brief native version
Works with Python 2 and 3.
'''
cat <<'EOF' > 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.
EOF
'''
for align in '<^>':
rows = [ line.strip().split('$') for line in open('align_columns.dat') ]
fmts = [ '{:%s%d}' % (align, max( len(row[i]) if i < len(row) else 0 for row in rows ))
for i in range(max(map(len, rows))) ]
for row in rows:
print(' '.join(fmts).format(*(row + [''] * len(fmts))))
print('')
Alternative
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]), end=' ')
print()
print("- " * 52)
Functional
As a fold
A fold/reduce between two transpositions.
(Selection of string justification methods via getattr):
'''Variously aligned columns
from delimited text.
'''
from functools import reduce
from itertools import repeat
# TEST ----------------------------------------------------
# main :: IO ()
def main():
'''Test of three alignments.'''
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.'''
rows = [x.split('$') for x in txt.splitlines()]
table = paddedRows(max(map(len, rows)))('')(rows)
print('\n\n'.join(map(
alignedTable(table)(' '),
[-1, 0, 1] # Left, Center, Right
)))
# alignedTable :: [[String]] -> Alignment -> String -> String
def alignedTable(rows):
'''Tabulation of rows of cells, with cell alignment
specified by:
eAlign -1 = left
eAlign 0 = center
eAlign 1 = right
and separator between columns
supplied by the `sep` argument.
'''
def go(sep, eAlign):
lcr = ['ljust', 'center', 'rjust'][1 + eAlign]
# nextAlignedCol :: [[String]] -> [String] -> [[String]]
def nextAlignedCol(cols, col):
w = max(len(cell) for cell in col)
return cols + [
[getattr(s, lcr)(w, ' ') for s in col]
]
return '\n'.join([
sep.join(cells) for cells in
zip(*reduce(nextAlignedCol, zip(*rows), []))
])
return lambda sep: lambda eAlign: go(sep, eAlign)
# GENERIC -------------------------------------------------
# paddedRows :: Int -> a -> [[a]] -> [[a]]
def paddedRows(n):
'''A list of rows of even length,
in which each may be padded (but
not truncated) to length n with
appended copies of value v.'''
def go(v, xs):
def pad(x):
d = n - len(x)
return (x + list(repeat(v, d))) if 0 < d else x
return [pad(row) for row in xs]
return lambda v: lambda xs: go(v, xs) if xs else []
# MAIN ---
if __name__ == '__main__':
main()
- 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.
q
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." )
ta:{[aln;txt] / tabulate aligned
sl:(count'')s:"$"vs/:txt; / strings and their lengths
cw:{rl#\:max x@/:\:til max rl:count each x}sl; / cell widths
ps:$[aln=`R;-1-cw;1+cw]$''s; / padded strings
ps:$[aln=`C;(neg(cw-sl)div 2)rotate''ps;ps]; / center
1,[;"\n\n"]"\n"sv raze each ps; } / print
- Output:
q)ta[`L]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. q)ta[`R]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. q)ta[`C]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.
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.
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)
Raku
(formerly Perl 6)
Call with parameter left (default), center or right.
my @lines =
q|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.
|.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 }
}
}
Or a more functional version, called like ./align.p6 left input.txt
, which however only supports left and right alignment (not center):
sub MAIN ($alignment where 'left'|'right', $file) {
my @lines := $file.IO.lines.map(*.split('$').cache).cache;
my @widths = roundrobin(|@lines).map(*».chars.max);
my $align = {left=>'-', right=>''}{$alignment};
my $format = @widths.map( '%' ~ ++$ ~ '$' ~ $align ~ * ~ 's' ).join(' ') ~ "\n";
printf $format, |$_ for @lines;
}
RapidQ
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
- Output:
TextLeft contains: 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. TextRight contains: 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. TextCenter contains: 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.
REBOL
REBOL [
Title: "Align Columns"
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]
- 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.
Red
Red [
Title: "Align Columns"
Original-Author: oofoe
]
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.}
; Parse specimen into data grid.
data: copy []
foreach line split text lf [
append/only data split line "$"
]
; Compute independent widths for each column.
widths: copy []
foreach line data [
forall line [
i: index? line
if i > length? widths [append widths 0]
widths/:i: max widths/:i length? line/1
]
]
pad: function [n] [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: function [n s] [
d: n - length? s
h: round/down d / 2
rejoin [pad h s pad d - h]
]
; 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 [newline "Align" i "..." newline] entable data get i]
REXX
(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
(with output)
/*REXX program displays various alignments for words in an array of text strings. */
size= 0; t.=; cols= 0; wid.= 0; @.= /*zero or nullify some variables. */
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\=='' /* [↓] process all the text lines. */
_= strip(t.r,,'$') /*strip leading & trailing dollar signs*/
do c=1 until _=='' /* [↓] process each of the words. */
parse var _ @.r.c '$' _ /*extract the words from a line of text*/
wid.c= max(wid.c, length(@.r.c) ) /*find the maximum 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 the width of the biggest line. */
rows= r - 1 /*adjust ROWS because of the DO loop.*/
do j=1 for 3; say; say /*show two blank lines for a separator.*/
say center(word('left right center', j) "aligned", size+cols-1, "═") /*show title*/
do r=1 for rows; _= /*construct 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 _= _ center(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 all done. */
- output when using the default input:
══════════════════════════════════════════════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.
(boxed output)
Note: this version boxes each column of output to better show the columns.
/*REXX program displays various alignments for words in an array of text strings. */
size= 0; t.=; cols= 0; wid.= 0; @.= /*zero or nullify some variables. */
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\=='' /* [↓] process all the text lines. */
_= strip(t.r,,'$') /*strip leading & trailing dollar signs*/
do c=1 until _=='' /* [↓] process each of the words. */
parse var _ @.r.c '$' _ /*extract the words from a line of text*/
wid.c= max(wid.c, length(@.r.c) ) /*find the maximum 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 the width of the biggest line. */
rows= r - 1 /*adjust ROWS because of the DO loop.*/
do j=1 for 3; say; say /*show two blank lines for a separator.*/
say center(word('left right center', j) "aligned", size+cols+1, "═") /*show title*/
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) /*justify left*/
if j==2 then _= _ || ! || right(x, wid.c) /* " ruggt*/
if j==3 then _= _ || ! || center(x, wid.c) /* " ctr.*/
end /*c*/
if r==0 then do; _= '┌'substr(_, 2, length(_) - 1)"┐" /*top line.*/
bot= '└'substr(_, 2, length(_) - 2)"┘" /*bot " */
end
else _= _ || ! /*append trailing end boxing character.*/
say _
end /*r*/ /* [↑] shows words in boxes. */
say translate(bot, '┴', "┬") /*display the bottom line of the box. */
end /*j*/ /*stick a fork in it, we're all done. */
- output when using the default input:
═══════════════════════════════════════════════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.│ │ │ │ └──────────┴──────────┴──────────┴──────┴──────┴─────────┴──────────┴────────┴───────┴───────┴──────┴────┘
Ruby
J2justifier = {Left: :ljust, Right: :rjust, Center: :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 Symbol; (:Left, :Right, or :Center).
Return the justified output as a string
=end
def aligner(infile, justification = :Left)
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 [:Left, :Right, :Center]
infile = StringIO.new(textinfile)
puts "\n# %s Column-aligned output:" % align
puts aligner(infile, align)
end
- 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.
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.
Rust
use std::iter::{repeat, 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_end_matches('$'))
{
let lens = line.split('$').map(|s| s.chars().count());
for (idx, len) in lens.enumerate() {
if idx < widths.len() {
widths[idx] = std::cmp::max(widths[idx], len);
} else {
widths.push(len);
}
}
}
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_end_matches('$'))
{
for (s, w) in line.split('$').zip(widths.iter()) {
let blank_count = w - s.chars().count();
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));
}
- 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.
Scala
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
Scheme
(import (scheme base)
(scheme write)
(srfi 1)
(except (srfi 13) string-for-each string-map)
(srfi 14))
;; text is a list of lines, alignment is left/right/center
;; displays the aligned text in columns with a single space gap
(define (align-columns text alignment)
(define (split line) ; splits string on $ into list of strings
(string-tokenize line (char-set-complement (->char-set "$"))))
(define (extend lst n) ; extends list to length n, by adding "" to end
(append lst (make-list (- n (length lst)) "")))
(define (align-word word width) ; align single word to fit width
(case alignment
((left) (string-pad-right word width))
((right) (string-pad word width))
((center) (let ((rem (- width (string-length word))))
(string-pad-right (string-pad word (- width (truncate (/ rem 2))))
width)))))
;
(display alignment) (newline)
(let* ((text-list (map split text))
(max-line-len (fold (lambda (text val) (max (length text) val)) 0 text-list))
(text-lines (map (lambda (line) (extend line max-line-len)) text-list))
(min-col-widths (map (lambda (col)
(fold (lambda (line val)
(max (string-length (list-ref line col))
val))
0
text-lines))
(iota max-line-len))))
(map (lambda (line)
(map (lambda (word width)
(display (string-append (align-word word width)
" ")))
line min-col-widths)
(newline))
text-lines))
(newline))
;; show example
(define *example*
'("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 *example* 'left)
(align-columns *example* 'center)
(align-columns *example* 'right)
- 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.
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.
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.
SETL
program align;
magic := false; $ turn off regexp matching in GNU SETL
read_file;
ncols := max/[#line : line in lines];
sizes := [1+max/[#(line(col) ? "") : line in lines] : col in [1..ncols]];
loop for line in lines do
print(+/[align(line(col), sizes(col)) : col in [1..#line]]);
end loop;
read_file::
f := open(command_line(1), "r");
lines := [];
loop doing geta(f, line); while line /= om do
lines with:= split(line, "$");
end loop;
close(f);
proc align(s, n);
case command_line(2) of
("r"): return lpad(s, n);
("l"): return rpad(s, n);
("c"): return center(s, n);
end case;
end proc;
proc center(s, n);
padding := n - #s;
l := " " * ceil(padding/2);
r := " " * floor(padding/2);
return l + s + r;
end proc;
end program;
- Output:
$ setl align.setl test.txt 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. $ setl align.setl test.txt 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. $ setl align.setl test.txt c 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.
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.
Sidef
class Format(text, width) {
method align(j) {
text.map { |row|
row.range.map { |i|
'%-*s ' % (width[i],
'%*s' % (row[i].len + (width[i]-row[i].len * j/2), row[i]));
}.join("");
}.join("\n") + "\n";
}
}
func Formatter(text) {
var textArr = [];
var widthArr = [];
text.each_line {
var words = .split('$');
textArr.append(words);
words.each_kv { |i, word|
if (i == widthArr.len) {
widthArr.append(word.len);
}
elsif (word.len > widthArr[i]) {
widthArr[i] = word.len;
}
}
}
return 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);
say f.align(left);
say f.align(middle);
say f.align(right);
Smalltalk
the following works with Smalltalk/X, but should also in other dialects (may have to add "centerPadded" to the String class).
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.
'.
printSep :=
[:colLengths |
Stdout nextPut:$+.
colLengths do:[:len | Stdout next:len put:$-; nextPut:$+ ].
Stdout cr.
].
printRows :=
[:text :box :justifyEach |
lines := StringCollection fromString:text.
rowSet := lines collect:[:line | line splitBy:$$ ].
maxNumCols := (rowSet collect:[:row | row size]) max.
maxLengths := rowSet
inject:(Array new:maxNumCols withAll:0)
into:[:maxesSoFar :row|
maxesSoFar
with:(row paddedTo:maxNumCols with:'')
collect:[:maxLen :col | maxLen max: col size]].
rowSet do:[:row |
|first|
box ifTrue:[ printSep value:maxLengths ].
first := true.
(box ifTrue:[row paddedTo:maxLengths size with:''] ifFalse:[row])
with: (box ifTrue:[maxLengths] ifFalse:[maxLengths to:row size])
do:[:col :len |
first ifTrue:[ box ifTrue:[Stdout nextPutAll:'|']. first := false.].
Stdout print:(justifyEach value:col value:len).
Stdout nextPutAll:(box ifTrue:'|' ifFalse:' ')
].
Stdout cr.
].
box ifTrue:[ printSep value:maxLengths ].
].
printRightJustified :=
[:text :box | printRows value:text value:box value:[:col :len | (col leftPaddedTo:len)]].
printLeftJustified :=
[:text :box | printRows value:text value:box value:[:col :len | (col paddedTo:len)]].
printCentered :=
[:text :box | printRows value:text value:box value:[:col :len | col centerPaddedTo:len]].
Stdout printCR:'Left justified:'.
printLeftJustified value:text value:false.
Stdout cr; printCR:'Right justified:'.
printRightJustified value:text value:false.
Stdout cr; printCR:'Centered:'.
printCentered value:text value:false.
Stdout cr; printCR:'Left justified with box:'.
printLeftJustified value:text value:true.
Stdout cr; printCR:'Right justified with box:'.
printRightJustified value:text value:true.
Stdout cr; printCR:'Centered with box:'.
printCentered value:text value:true.
- 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. 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. 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. Left justified with box: +----------+----------+----------+------+------+---------+----------+--------+-------+-------+------+----+ |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 with box: +----------+----------+----------+------+------+---------+----------+--------+-------+-------+------+----+ | 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 with box: +----------+----------+----------+------+------+---------+----------+--------+-------+-------+------+----+ | 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.| | | | +----------+----------+----------+------+------+---------+----------+--------+-------+-------+------+----+
Snobol
* Since we don't know how much text we'll be reading in,
* we store the words and field widths in tables
Words = TABLE()
Widths = TABLE()
* Match text from start of string to the first dollar sign
WordPat = POS(0) BREAK('$') . Word LEN(1) REM . Rest
* We output the results aligned three different ways; these are the
* labels for those sections of output:
Labels = ARRAY(3)
Labels<1> = "Left-justified"
Labels<2> = "Right-justified"
Labels<3> = "Centered"
* There are built-in functions for left- and right- justification,
* but not necessarily one for centering (depending on
* implementation). So we define one.
DEFINE('CPAD(Word,Width)Z,Left') :(END_CPAD)
CPAD Z = SIZE(Word)
Left = Z + (Width - Z) / 2
CPAD = RPAD(LPAD(Word, Left), Width) :(RETURN)
END_CPAD
* Read in our text a line at a time and split into words on '$'
InLineLoop Line = INPUT :F(DoneReading)
LineCount = LineCount + 1
Column = 0
InWordLoop Column = Column + 1
* Separate Line into Word, Line=Rest at first dollar sign
Line WordPat = Rest :S(CheckMax)
* If there was no '$', the whole line is the next word
Word = Line
Line =
* Keep track of the largest number of columns on any line
CheckMax LE(Column, MaxColumn) :S(StoreWord)
MaxColumn = Column
StoreWord Words<LineCount ',' Column> = Word
* And the size of the longest word in each column
GT(SIZE(Word),Widths<Column>) :F(NoNewMaxWidth)
Widths<Column> = SIZE(Word)
* Loop if the line isn't empty yet
NoNewMaxWidth GT(Size(Line)) :S(InWordLoop) F(InLineLoop)
DoneReading
* Now we print the results out in the three justification styles
Style = 0
StyleLoop Style = Style + 1
GT(Style, 3) :S(END)
OUTPUT =
OUTPUT = Labels<Style> ':'
I = 0
OutLineLoop I = I + 1
GT(I, LineCount) :S(StyleLoop)
* Build up the output line by fields starting with the null string
Line =
J = 0
OutWordLoop J = J + 1
GT(J, MaxColumn) :S(PrintLine)
Word = Words<I ',' J>
GT(SIZE(Word)) :F(PrintLine)
* Place the word within the column according to the pass we're on
EQ(Style, 1) :F(NotLeft)
* Left-justified
Word = RPAD(Word, Widths<J>) :(AddWord)
NotLeft EQ(Style, 2) :F(NotRight)
* Right-justified
Word = LPAD(Word, Widths<J>) :(AddWord)
* Centered
NotRight Word = CPAD(Word, Widths<J>)
* Add word to line and loop
AddWord Line = Line GT(SIZE(Line)) ' '
Line = Line Word :(OutWordLoop)
* Print the line
PrintLine OUTPUT = Line :(OutLineLoop)
END
- 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. 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. 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.
SparForte
As a structured script.
#!/usr/local/bin/spar
pragma annotate( summary, "aligncols" )
@( description, "Given a text file of many lines, where fields within a line are delineated ")
@( description, "by a single 'dollar' character, write a program that aligns each column of" )
@( description, "fields by ensuring that words in each column are separated by at least one" )
@( description, "space. Further, allow for each word in a column to be either left justified," )
@( description, "right justified, or center justified within its column. " )
@( description, "A modified version of the Ada solution from Rosetta Code" )
@( category, "tutorials" )
@( author, "Ken O. Burtch" )
@( see_also, "http://rosettacode.org/wiki/Align_columns" );
pragma license( unrestricted );
pragma software_model( nonstandard );
pragma restriction( no_external_commands );
procedure aligncols is
Text : constant string :=
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$" & ASCII.NUL &
"are$delineated$by$a$single$'dollar'$character,$write$a$program" & ASCII.NUL &
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$" & ASCII.NUL &
"column$are$separated$by$at$least$one$space." & ASCII.NUL &
"Further,$allow$for$each$word$in$a$column$to$be$either$left$" & ASCII.NUL &
"justified,$right$justified,$or$center$justified$within$its$column." & ASCII.NUL;
File : file_type;
Width : array(1..1000) of natural;
ch : character;
Column : positive := 1;
Start : positive := 1;
type Alignment is ( Left, Center, Right );
s : string;
padding : natural;
begin
-- Zero Widths
for I in arrays.first( Width )..arrays.last( Width ) loop
Width(I) := 0;
end loop;
-- Determining the widths of columns
for I in 1..strings.length(Text) loop
ch := strings.element( Text, I );
case ch is
when '$' | ASCII.NUL =>
Width (Column) := numerics.max(Width (Column), I - Start + 1);
Start := I + 1;
if strings.element( Text, I ) = ASCII.NUL then
Column := 1;
else
Column := @+1;
end if;
when others =>
null;
end case;
end loop;
create( File, out_file, "columned.txt" );
-- Formatting
for Align in Left..Right loop
Column := 1;
Start := 1;
for I in 1..strings.length(Text) loop
ch := strings.element( Text, I );
case ch is
when '$' | ASCII.NUL =>
s := strings.slice( Text, Start, I-1 );
padding := (Width( Column ) - strings.length(s));
case Align is
when Left =>
s := @ & (padding * ' ');
when Center =>
declare
left_padding : constant natural := padding/2;
right_padding : constant natural := padding - left_padding;
begin
s := (left_padding * ' ') & @ & (right_padding * ' ');
end;
when Right =>
s := (padding * ' ') & @;
when others =>
null;
end case;
put( File, s );
Start := I+1;
if ch = ASCII.NUL then
new_line( File );
Column := 1;
else
Column := @+1;
end if;
when others =>
null;
end case;
end loop;
new_line( File );
end loop;
close( File );
end aligncols;
Standard ML
fun curry f x y = f (x, y)
fun uncurry f (x, y) = f x y
fun maxWidths ([], widths) = widths
| maxWidths (strings, []) = map size strings
| maxWidths (s :: ss, w :: ws) = Int.max (size s, w) :: maxWidths (ss, ws)
val alignL = uncurry (StringCvt.padRight #" ")
and alignR = uncurry (StringCvt.padLeft #" ")
fun alignC (w, s) =
alignL (w, alignR ((w + size s) div 2, s))
fun formatTable tab =
let
val columnWidths = foldl maxWidths [] tab
in
fn f => String.concatWith "\n"
(map (String.concatWith " " o curry (ListPair.map f) columnWidths) tab)
end
val readTable =
map (String.fields (curry op= #"$"))
o String.tokens (curry op= #"\n")
o TextIO.inputAll
(* test stdin with all alignments *)
val () = print (String.concatWith "\n\n"
(map (formatTable (readTable TextIO.stdIn)) [alignL, alignC, alignR]) ^ "\n")
- 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.
Swift
import Foundation
extension String {
func dropLastIf(_ char: Character) -> String {
if last == char {
return String(dropLast())
} else {
return self
}
}
}
enum Align {
case left, center, right
}
func getLines(input: String) -> [String] {
input
.components(separatedBy: "\n")
.map({ $0.replacingOccurrences(of: " ", with: "").dropLastIf("$") })
}
func getColWidths(from: String) -> [Int] {
var widths = [Int]()
let lines = getLines(input: from)
for line in lines {
let lens = line.components(separatedBy: "$").map({ $0.count })
for (i, len) in lens.enumerated() {
if i < widths.count {
widths[i] = max(widths[i], len)
} else {
widths.append(len)
}
}
}
return widths
}
func alignCols(input: String, align: Align = .left) -> String {
let widths = getColWidths(from: input)
let lines = getLines(input: input)
var res = ""
for line in lines {
for (str, width) in zip(line.components(separatedBy: "$"), widths) {
let blanks = width - str.count
let pre: Int, post: Int
switch align {
case .left:
(pre, post) = (0, blanks)
case .center:
(pre, post) = (blanks / 2, (blanks + 1) / 2)
case .right:
(pre, post) = (blanks, 0)
}
res += String(repeating: " ", count: pre)
res += str
res += String(repeating: " ", count: post)
res += " "
}
res += "\n"
}
return res
}
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.
"""
print(alignCols(input: input))
print()
print(alignCols(input: input, align: .center))
print()
print(alignCols(input: input, align: .right))
- 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.
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.
Transd
Transd has built-in support for "left" and "right" formatting, but not "centered", which added quite a bit of code.
#lang transd
MainModule : {
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.",
tabl: Table(),
n: 0,
colWidths: Vector<Int>(),
print: (λ centered Bool(false)
(for n in Seq(0 (num-rows tabl)) do
(with row (get-row tabl n)
(for m in Seq(0 (num-cols tabl)) do
(with wid (+ 1.0 (get colWidths @idx))
word (get row m) wl 0.0 lef 0
(if centered (= wl (size String(word))) (= lef (/ (- wid wl) 2.0))
(textout width: lef "" width: wl word width: (- wid (+ wl lef)) "")
else
(textout width: wid (get row m)))))
(lout ""))
)
),
_start: (λ
(load-table tabl txt fieldSep: "$" :emptyEls)
(for i in Seq(0 (num-cols tabl)) do (= n 0)
(tsd-query tabl
reduce: [i]
as: [[String()]]
using: (λ (set n (max (size (get @row 0)) n))))
(append colWidths n)
)
(textout :right "") (print)
(lout :left "") (print)
(lout "") (print true)
)
}
- Output:
Given a text file of many lines, where fields within a line are delineated by a single 'dollar' character, write a program a line that aligns each column of fields by ensuring that words in each column are separated by at least one space. that words in each Further, allow for each word in a column to be either left justified, right justified, or center justified within its column. be either left Given a text file of many lines, where fields within a line are delineated by a single 'dollar' character, write a program a line that aligns each column of fields by ensuring that words in each column are separated by at least one space. that words in each Further, allow for each word in a column to be either left justified, right justified, or center justified within its column. be either left Given a text file of many lines, where fields within a line are delineated by a single 'dollar' character, write a program a line that aligns each column of fields by ensuring that words in each column are separated by at least one space. that words in each Further, allow for each word in a column to be either left justified, right justified, or center justified within its column. be either left
TSE SAL
INTEGER PROC FNBlockChangeColumnAlignLeftB( INTEGER columnTotalI, INTEGER spaceTotalI, INTEGER buffer1I )
INTEGER B = FALSE
INTEGER downB = TRUE
INTEGER minI = 1
INTEGER I = 0
INTEGER J = 0
INTEGER K = 0
INTEGER L = 0
INTEGER buffer2I = 0
STRING s[255] = ""
INTEGER wordRightB = FALSE
STRING s1[255] = Query( WordSet )
IF ( NOT ( IsBlockInCurrFile() ) ) Warn( "Please mark a block" ) B = FALSE RETURN( B ) ENDIF // return from the current procedure if no block is marked
Set( BREAK, ON )
PushPosition()
PushBlock()
Set( WordSet, ChrSet( "a-zA-Z0-9_,." ) )
PushPosition()
buffer2I = CreateTempBuffer()
PopPosition()
PushPosition()
PushBlock()
DO 100 TIMES
AddLine( "", buffer2I )
ENDDO
PopBlock()
PopPosition()
GotoBlockBegin()
I = minI - 1
WHILE ( ( IsCursorInBlock() ) AND ( downB ) )
IF NOT LFind( "^$", "cgx" )
BegLine()
REPEAT
s = GetWord()
IF NOT ( s == "" )
s = Trim( s )
I = I + 1
IF ( I > columnTotalI )
I = minI
ENDIF
J = Length( s )
PushPosition()
PushBlock()
GotoBufferId( buffer2I )
GotoLine( I )
//
IF ( CurrLineLen() == 0 )
BegLine()
InsertText( Format( Str( J ), " " ), _INSERT_ )
ELSE
K = Val( Trim( GetText( 1, MAXSTRINGLEN ) ) )
IF ( J > K )
BegLine()
DelToEol()
BegLine()
InsertText( Str( J ), _INSERT_ )
ENDIF
ENDIF
PopBlock()
PopPosition()
wordRightB = WordRight()
ENDIF
UNTIL ( s == "" ) OR ( NOT wordRightB )
ENDIF
downB = Down()
ENDWHILE
GotoBlockBegin()
I = minI - 1
L = 1
K = 1
WHILE ( ( IsCursorInBlock() ) AND ( downB ) )
IF NOT LFind( "^$", "cgx" )
BegLine()
REPEAT
B = FALSE
s = GetWord()
IF NOT ( s == "" )
s = Trim( s )
I = I + 1
IF ( I > columnTotalI )
I = minI
K = 1
L = L + 1
ENDIF
//
PushPosition()
PushBlock()
GotoBufferId( buffer2I )
GotoLine( I )
J = Val( Trim( GetText( 1, MAXSTRINGLEN ) ) )
PopPosition()
PopBlock()
PushPosition()
PushBlock()
GotoBufferId( buffer1I )
GotoLine( L )
GotoColumn( K )
InsertText( s, _INSERT_ )
K = K + J + spaceTotalI
PopBlock()
PopPosition()
wordRightB = WordRight()
ENDIF
UNTIL ( s == "" ) OR ( NOT wordRightB )
ENDIF
AddLine( "", buffer1I )
downB = Down()
ENDWHILE
OneWindow()
VWindow()
GotoWindow( 1 )
GotoBufferId( buffer2I )
GotoWindow( 2 )
GotoBufferId( buffer1I )
B = TRUE
Set( WordSet, s1 )
PopPosition()
PopBlock()
RETURN( B )
END
//
PROC Main()
STRING s1[255] = "12" // change this
STRING s2[255] = "2" // change this
INTEGER bufferI = 0
PushPosition()
bufferI = CreateTempBuffer()
PopPosition()
IF ( NOT ( Ask( "block: change: column: align: left: columnTotalI = ", s1, _EDIT_HISTORY_ ) ) AND ( Length( s1 ) > 0 ) ) RETURN() ENDIF
IF ( NOT ( Ask( "block: change: column: align: left: spaceTotalI = ", s2, _EDIT_HISTORY_ ) ) AND ( Length( s2 ) > 0 ) ) RETURN() ENDIF
Message( FNBlockChangeColumnAlignLeftB( Val( s1 ), Val( s2 ), bufferI ) ) // gives e.g. TRUE
GotoBufferId( bufferI )
END
- 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.
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. $ $ $
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.
Uiua
# Split the text at $ and then justify each word 3 ways
N ← {"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."}
Ls ← ≡⍚(⊜□≠@$.) # Get the word arrays.
PadC ← ↻:⊙(⌊÷2-)⊃(⬚@ ↙|⊙⧻) # Pad centre.
Pad! ← ≡/◇⊂⍉≡≡⍚^! # Apply a padding function to all.
Prep ← (
≡◇⬚""↙/↥≡◇⧻. # Pad each row to same length.
+1≡◇(/↥≡◇⧻).⍉ # Find required length for each column.
)
≡(&p/$"_\n_")[⊃(Pad!⬚@ ↙|Pad!(⬚@ ↙¯)|Pad!PadC)] Prep Ls N
- Output:
As expected, follow Uiua Pad link to confirm :-).
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.
Using column(1)
Note that the left-justified case can be handled trivially by the column command, which ships with modern Linux and macOS systems:
tr '$' ' ' | column -t
- 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.
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.
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
- 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.
VBScript
' Align columns - RC - VBScript
Const nr=16, nc=16
ReDim d(nc),t(nr), wor(nr,nc)
i=i+1: t(i) = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
i=i+1: t(i) = "are$delineated$by$a$single$'dollar'$character,$write$a$program"
i=i+1: t(i) = "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
i=i+1: t(i) = "column$are$separated$by$at$least$one$space."
i=i+1: t(i) = "Further,$allow$for$each$word$in$a$column$To$be$either$left$"
i=i+1: t(i) = "justified,$right$justified,$or$center$justified$within$its$column."
For r=1 to nr
If t(r)="" Then Exit For
w=xRTrim(t(r),"$")
m=Split(w,"$")
For c=1 To UBound(m)+1
wor(r,c)=m(c-1)
If Len(wor(r,c))>d(c) Then d(c)=Len(wor(r,c))
Next 'c
If c>cols Then cols=c
Next 'r
rows=r-1
tt=Array("Left","Right","Center")
For n=1 To 3
Wscript.Echo
Wscript.Echo "*****" & tt(n-1) & "*****"
For r=1 To rows
w=""
For c=1 To cols
x=wor(r,c): s=Space(d(c))
Select Case n
Case 1: w=w &" "& Left (x & s,d(c))
Case 2: w=w &" "& Right (s & x,d(c))
Case 3: w=w &" "& xCentre(x,d(c)," ")
End Select 'n
Next 'c
Wscript.Echo Mid(w,2)
Next 'r
Next 'n
Function xCentre(c, n, Pad)
Dim j
If n > Len(c) Then
j = (n - Len(c)) \ 2
If (n - Len(c)) Mod 2 <> 0 Then j = j + 1
xCentre = Mid(String(j, Pad) & c & String(j, Pad), 1, n)
Else
xCentre = c
End If
End Function 'xCentre
Function xRTrim(c, Pad)
Dim i2, l, cc
cc = "": l = Len(c)
If l > 0 Then
i2 = l
Do While (Mid(c, i2, 1) = Pad And i2 > 1)
i2 = i2 - 1
Loop
If i2 = 1 And Mid(c, i2, 1) = Pad Then i2 = 0
If i2 > 0 Then cc = Mid(c, 1, i2)
End If
xRTrim = cc
End Function 'xRTrim
- 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. *****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. *****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.
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)
}
- 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.
Visual Basic
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
Usage:
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
- 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.
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
- 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.
V (Vlang)
Currently (5/2022) V (Vlang) uses string interpolation so `$` have to be escaped. Variables in formatting aren't currently allowed, and if they were only right/left are currently valid options
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."
struct Formatter {
mut:
text [][]string
width []int
}
fn new_formatter(text string) Formatter {
mut f := Formatter{}
for line in text.split_into_lines() {
mut words := line.split("\$")
for words[words.len-1] == "" {
words = words[..words.len-1]
}
f.text << words
for i, word in words {
if i == f.width.len {
f.width << word.len
} else if word.len > f.width[i] {
f.width[i] = word.len
}
}
}
return f
}
enum Justify {
left = 0
middle
right
}
fn (f Formatter) print(j Justify) {
for line in f.text {
for i, word in line {
match j {
.left {
print('$word${' '.repeat(f.width[i]-word.len)} ')
}
.middle {
mut extra := 0
if (f.width[i]%2==1 && word.len%2==0) || (f.width[i]%2==0 && word.len%2==1) {
extra++
}
print('${' '.repeat((f.width[i]-word.len)/2)}$word${' '.repeat((f.width[i]-word.len)/2+extra)} ')
}
.right {
print('${' '.repeat(f.width[i]-word.len)}$word ')
}
}
}
println("")
}
println("")
}
fn main() {
f := new_formatter(text)
f.print(Justify.left)
f.print(Justify.middle)
f.print(Justify.right)
}
- 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.
Wren
import "io" for File
import "./fmt" for Fmt
var LEFT = 0
var RIGHT = 1
var CENTER = 2
var justStrs = ["LEFT", "RIGHT", "CENTER"]
// Gets a list of lines in the file with each line split into fields.
var getLines = Fn.new { |fileName|
var contents = File.read(fileName)
var lines = contents.split("\n") // use "\r\n" on Windows
for (i in 0...lines.count) {
lines[i] = lines[i].trim().trimEnd("$")
if (lines[i] == "") { // get rid of final blank line, if any
lines = lines[0..-2]
break
}
lines[i] = lines[i].split("$")
}
return lines
}
var alignCols = Fn.new { |lines, just|
// find maximum number of columns
var nCols = lines.reduce(0) { |acc, line| (line.count > acc) ? line.count : acc }
// find maximum width for each column
var maxWids = List.filled(nCols, 0)
for (line in lines) {
for (i in 0...line.count) {
var width = line[i].count
if (width > maxWids[i]) maxWids[i] = width
}
}
System.print("With %(justStrs[just]) justification:")
for (line in lines) {
for (i in 0...line.count) {
var width = maxWids[i] + 1
if (just == LEFT) {
System.write(Fmt.s(-width, line[i]))
} else if (just == RIGHT) {
System.write(Fmt.s(width, line[i]))
} else if (just == CENTER) {
System.write(Fmt.m(width, line[i]))
}
}
System.print()
}
System.print()
}
var fileName = "align_cols.txt"
var lines = getLines.call(fileName)
for (i in 0..2) alignCols.call(lines, i)
- Output:
With LEFT 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. With RIGHT 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. With CENTER 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.
XPL0
string 0;
def LF=$0A, CR=$0D;
def Left, Right, Center;
proc AlignCols(S); \Display string S with its columns aligned
char S, C, Field(80), ColWidth(80);
int I, J, N, Just;
proc Justify;
int T;
proc SpOut(M); \Output M space characters
int M, K;
for K:= 0 to M-1 do ChOut(0, ^ );
proc FieldOut; \Output Field of N characters
int K;
for K:= 0 to N-1 do ChOut(0, Field(K));
[case Just of
Left: [FieldOut(N); SpOut(ColWidth(J)-N+1)];
Right: [SpOut(ColWidth(J)-N+1); FieldOut(N)];
Center:[T:= ColWidth(J)-N+1;
SpOut(T/2); FieldOut(N); SpOut(T/2 + rem(0))]
other [];
];
[\Get width (in characters) of each column
for J:= 0 to 80-1 do ColWidth(J):= 0;
I:= 0; J:= 0; N:= 0;
loop [repeat C:= S(I); I:= I+1 until C # CR;
if N > ColWidth(J) then ColWidth(J):= N;
case C of
0: quit;
^$: [N:= 0; J:= J+1];
LF: [N:= 0; J:= J+1; J:= 0]
other N:= N+1;
];
for Just:= Left to Center do
[I:= 0; J:= 0; N:= 0;
loop [repeat C:= S(I); I:= I+1 until C # CR;
case C of
0: [Justify(Just); CrLf(0); quit];
^$: [Justify(Just); N:= 0; J:= J+1];
LF: [Justify(Just); CrLf(0); N:= 0; J:= 0]
other [Field(N):= C; N:= N+1];
];
CrLf(0);
];
];
AlignCols("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.")
- 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.
Yabasic
theString$ = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
theString$ = theString$ + "are$delineated$by$a$single$'dollar'$character,$write$a$program"
theString$ = theString$ + "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
theString$ = theString$ + "column$are$separated$by$at$least$one$space."
theString$ = theString$ + "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
theString$ = theString$ + "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
sub word$(sr$, wn, delim$)
local i, j, n, sd, sl, sl2
local s$, res$, d$
d$ = delim$
j = wn
if j = 0 j = j+1
res$ = "" : s$ = sr$
if d$ = "" d$ = " "
sd = len(d$) : sl = len(s$)
do
n = instr(s$,d$)
j = j - 1
if j = 0 then
if n = 0 then res$ = s$ else res$ = mid$(s$, 1, n-1) : fi
return res$
fi
if n = 0 return res$
if n = sl-sd then res$ = "" : return res$ : fi
sl2 = sl-n
s$ = mid$(s$, n+1, sl2)
sl = sl2
loop
return res$
end sub
sub shoTable(theString$, align$, across)
local i, a$, b$
print "------------ align:", align$, " -- across:", across, " ------------"
dim siz(across)
b$ = " "
while word$(theString$, i+1, "$") <> ""
siz(mod(i, across)) = max(siz(mod(i, 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 siz(i) = siz(i)+1
next i
i = 0
a$ = word$(theString$, i+1, "$")
while a$ <> ""
s = siz(mod(i, across)) - len(a$)
if align$ = "right" a$ = left$(b$, s) + a$
if align$ = "left" a$ = a$ + left$(b$, s)
if align$ = "center" a$ = left$(b$, int(s / 2)) + a$ + left$(b$, int(s / 2) + (s and 1))
print "|", a$;
i = i + 1
if mod(i, across) = 0 print "|"
a$ = word$(theString$, i+1, "$")
wend
print
end sub
- Output:
Same as Run BASIC entry.
zkl
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;
}
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";
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.
ZX Spectrum Basic
The max width (without 'hack') of ZX Spectrum screen is 32 characters. The text sample is adapted for this feature.
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
- Output:
Left alignement example
The problem of Speccy is the screen. Need adapt text sample for show the result without problem ,right? But see the code.
- Programming Tasks
- Text processing
- 11l
- 360 Assembly
- 8th
- AArch64 Assembly
- ABAP
- Action!
- Ada
- Simple components for Ada
- Aime
- ALGOL 68
- Amazing Hopper
- APL
- AppleScript
- ARM Assembly
- Arturo
- AutoHotkey
- AutoIt
- AWK
- BaCon
- BASIC
- BBC BASIC
- Commodore BASIC
- Batch File
- Beads
- BQN
- C
- C sharp
- C++
- Clojure
- COBOL
- CoffeeScript
- Common Lisp
- D
- Delphi
- Delphi StdCtrls, Classes, SysUtils, StrUtils, Contnrs
- E
- EasyLang
- Elixir
- Erlang
- Euphoria
- F Sharp
- Factor
- FBSL
- Forth
- Fortran
- FreeBASIC
- FutureBasic
- Gambas
- Go
- Groovy
- Harbour
- Haskell
- HicEst
- Icon
- Unicon
- J
- Java
- Apache Commons Lang
- JavaScript
- Jq
- Jsish
- Julia
- Kotlin
- Lambdatalk
- Lasso
- Liberty BASIC
- Lua
- M2000 Interpreter
- Maple
- Mathematica
- Wolfram Language
- MATLAB
- Octave
- MiniScript
- ML/I
- MUMPS
- Nim
- Nit
- Oberon-2
- OCaml
- Oforth
- OoRexx
- OpenEdge/Progress
- OxygenBasic
- Oz
- Pascal
- Perl
- Phix
- Phixmonti
- PHP
- Picat
- PicoLisp
- PL/I
- PowerShell
- Prolog
- PureBasic
- Python
- Q
- R
- Racket
- Raku
- RapidQ
- REBOL
- Red
- REXX
- Ruby
- Run BASIC
- Rust
- Scala
- Scheme
- Sed
- Seed7
- SETL
- Shiny
- Sidef
- Smalltalk
- Snobol
- SparForte
- Standard ML
- Swift
- Tcl
- Transd
- TSE SAL
- TUSCRIPT
- TXR
- Uiua
- UNIX Shell
- Ursala
- VBA
- VBScript
- Vedit macro language
- Visual Basic
- Visual Basic .NET
- V (Vlang)
- Wren
- Wren-fmt
- XPL0
- Yabasic
- Zkl
- ZX Spectrum Basic
- PARI/GP/Omit
- Pages with too many expensive parser function calls