September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -20,3 +20,4 @@ Note that:
|
|||
# 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.
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
-- 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" & ¬
|
||||
|
|
@ -10,29 +12,15 @@ property eLeft : -1
|
|||
property eCenter : 0
|
||||
property eRight : 1
|
||||
|
||||
on run
|
||||
set lstCols to lineColumns("$", pstrLines)
|
||||
|
||||
script testAlignment
|
||||
on lambda(eAlign)
|
||||
columnsAligned(eAlign, lstCols)
|
||||
end lambda
|
||||
end script
|
||||
|
||||
intercalate(return & return, ¬
|
||||
map(testAlignment, {eLeft, eRight, eCenter}))
|
||||
end run
|
||||
|
||||
|
||||
-- columnsAligned :: EnumValue -> [[String]] -> String
|
||||
on columnsAligned(eAlign, lstCols)
|
||||
-- padwords :: Int -> [String] -> [[String]]
|
||||
script padwords
|
||||
on lambda(n, lstWords)
|
||||
on |λ|(n, lstWords)
|
||||
|
||||
-- pad :: String -> String
|
||||
script pad
|
||||
on lambda(str)
|
||||
on |λ|(str)
|
||||
set lngPad to n - (length of str)
|
||||
if eAlign = my eCenter then
|
||||
set lngHalf to lngPad div 2
|
||||
|
|
@ -45,11 +33,11 @@ on columnsAligned(eAlign, lstCols)
|
|||
{replicate(lngPad, space), str, ""}
|
||||
end if
|
||||
end if
|
||||
end lambda
|
||||
end |λ|
|
||||
end script
|
||||
|
||||
map(pad, lstWords)
|
||||
end lambda
|
||||
end |λ|
|
||||
end script
|
||||
|
||||
unlines(map(my unwords, ¬
|
||||
|
|
@ -61,9 +49,9 @@ end columnsAligned
|
|||
on lineColumns(strColDelim, strText)
|
||||
-- _words :: Text -> [Text]
|
||||
script _words
|
||||
on lambda(str)
|
||||
on |λ|(str)
|
||||
splitOn(strColDelim, str)
|
||||
end lambda
|
||||
end |λ|
|
||||
end script
|
||||
|
||||
set lstRows to map(_words, splitOn(linefeed, pstrLines))
|
||||
|
|
@ -71,9 +59,9 @@ on lineColumns(strColDelim, strText)
|
|||
|
||||
-- fullRow :: [[a]] -> [[a]]
|
||||
script fullRow
|
||||
on lambda(lst)
|
||||
on |λ|(lst)
|
||||
lst & replicate(nCols - (length of lst), {""})
|
||||
end lambda
|
||||
end |λ|
|
||||
end script
|
||||
|
||||
transpose(map(fullRow, lstRows))
|
||||
|
|
@ -81,19 +69,56 @@ end lineColumns
|
|||
|
||||
-- widest [a] -> Int
|
||||
on widest(xs)
|
||||
script maxLen
|
||||
on lambda(a, x)
|
||||
set lng to length of x
|
||||
cond(lng > a, lng, a)
|
||||
end lambda
|
||||
end script
|
||||
|
||||
foldl(maxLen, 0, xs)
|
||||
|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
|
||||
|
||||
-- GENERIC LIBRARY FUNCTIONS
|
||||
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)
|
||||
|
|
@ -103,52 +128,22 @@ on intercalate(strText, lstText)
|
|||
return strJoined
|
||||
end intercalate
|
||||
|
||||
-- Text -> Text -> [Text]
|
||||
on splitOn(strDelim, strMain)
|
||||
set {dlm, my text item delimiters} to {my text item delimiters, strDelim}
|
||||
set lstParts to text items of strMain
|
||||
set my text item delimiters to dlm
|
||||
return lstParts
|
||||
end splitOn
|
||||
-- length :: [a] -> Int
|
||||
on |length|(xs)
|
||||
length of xs
|
||||
end |length|
|
||||
|
||||
-- [Text] -> Text
|
||||
on unlines(lstLines)
|
||||
intercalate(linefeed, lstLines)
|
||||
end unlines
|
||||
|
||||
-- [Text] -> Text
|
||||
on unwords(lstWords)
|
||||
intercalate(" ", lstWords)
|
||||
end unwords
|
||||
|
||||
-- transpose :: [[a]] -> [[a]]
|
||||
on transpose(xss)
|
||||
script column
|
||||
on lambda(_, iCol)
|
||||
script row
|
||||
on lambda(xs)
|
||||
item iCol of xs
|
||||
end lambda
|
||||
end script
|
||||
|
||||
map(row, xss)
|
||||
end lambda
|
||||
end script
|
||||
|
||||
map(column, item 1 of xss)
|
||||
end transpose
|
||||
|
||||
-- foldl :: (a -> b -> a) -> a -> [b] -> a
|
||||
on foldl(f, startValue, xs)
|
||||
tell mReturn(f)
|
||||
set v to startValue
|
||||
set lng to length of xs
|
||||
repeat with i from 1 to lng
|
||||
set v to lambda(v, item i of xs, i, xs)
|
||||
end repeat
|
||||
return v
|
||||
end tell
|
||||
end foldl
|
||||
-- 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)
|
||||
|
|
@ -156,34 +151,36 @@ on map(f, xs)
|
|||
set lng to length of xs
|
||||
set lst to {}
|
||||
repeat with i from 1 to lng
|
||||
set end of lst to lambda(item i of xs, i, xs)
|
||||
set end of lst to |λ|(item i of xs, i, xs)
|
||||
end repeat
|
||||
return lst
|
||||
end tell
|
||||
end map
|
||||
|
||||
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
on zipWith(f, xs, ys)
|
||||
set lng to length of xs
|
||||
if lng is not length of ys then return missing value
|
||||
-- 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
|
||||
|
||||
tell mReturn(f)
|
||||
set lst to {}
|
||||
repeat with i from 1 to lng
|
||||
set end of lst to lambda(item i of xs, item i of ys)
|
||||
end repeat
|
||||
return lst
|
||||
end tell
|
||||
end zipWith
|
||||
foldl(max, missing value, xs)
|
||||
end maximumBy
|
||||
|
||||
-- cond :: Bool -> a -> a -> a
|
||||
on cond(bool, f, g)
|
||||
if bool then
|
||||
f
|
||||
-- min :: Ord a => a -> a -> a
|
||||
on min(x, y)
|
||||
if y < x then
|
||||
y
|
||||
else
|
||||
g
|
||||
x
|
||||
end if
|
||||
end cond
|
||||
end min
|
||||
|
||||
-- Egyptian multiplication - progressively doubling a list, appending
|
||||
-- stages of doubling to an accumulator where needed for binary
|
||||
|
|
@ -191,7 +188,11 @@ end cond
|
|||
|
||||
-- replicate :: Int -> a -> [a]
|
||||
on replicate(n, a)
|
||||
set out to cond(class of a is string, "", {})
|
||||
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
|
||||
|
||||
|
|
@ -203,14 +204,49 @@ on replicate(n, a)
|
|||
return out & dbl
|
||||
end replicate
|
||||
|
||||
-- Lift 2nd class handler function into 1st class script wrapper
|
||||
-- mReturn :: Handler -> Script
|
||||
on mReturn(f)
|
||||
if class of f is script then
|
||||
f
|
||||
else
|
||||
script
|
||||
property lambda : f
|
||||
end script
|
||||
end if
|
||||
end mReturn
|
||||
-- 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
|
||||
|
|
|
|||
66
Task/Align-columns/BASIC/align-columns-2.basic
Normal file
66
Task/Align-columns/BASIC/align-columns-2.basic
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
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"
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
defmodule Align do
|
||||
def columns(text, alignment) do
|
||||
fieldsbyrow = String.split(text, "\n", trim: true)
|
||||
|> Enum.map(fn line -> String.split(line, "$", trim: true) end)
|
||||
|> 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
|
||||
|
|
@ -15,9 +15,9 @@ defmodule Align do
|
|||
end)
|
||||
end
|
||||
|
||||
defp adjust(field, width, :Left), do: String.ljust(field, width)
|
||||
defp adjust(field, width, :Right), do: String.rjust(field, width)
|
||||
defp adjust(field, width, _), do: :string.centre(String.to_char_list(field), width)
|
||||
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 = """
|
||||
|
|
|
|||
44
Task/Align-columns/Gambas/align-columns.gambas
Normal file
44
Task/Align-columns/Gambas/align-columns.gambas
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
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
|
||||
26
Task/Align-columns/Haskell/align-columns-1.hs
Normal file
26
Task/Align-columns/Haskell/align-columns-1.hs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
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)
|
||||
35
Task/Align-columns/Haskell/align-columns-2.hs
Normal file
35
Task/Align-columns/Haskell/align-columns-2.hs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
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]
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import Data.List
|
||||
import Control.Monad
|
||||
import Control.Arrow
|
||||
|
||||
dat = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$\n" ++
|
||||
"are$delineated$by$a$single$'dollar'$character,$write$a$program\n" ++
|
||||
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$\n" ++
|
||||
"column$are$separated$by$at$least$one$space.\n" ++
|
||||
"Further,$allow$for$each$word$in$a$column$to$be$either$left$\n" ++
|
||||
"justified,$right$justified,$or$center$justified$within$its$column.\n"
|
||||
|
||||
brkdwn = takeWhile (not.null) . unfoldr (Just . second (drop 1) . span ('$'/=))
|
||||
|
||||
format j ls = map (unwords. zipWith align colw) rows
|
||||
where
|
||||
rows = map brkdwn $ lines ls
|
||||
colw = map (maximum. map length) . transpose $ rows
|
||||
align cw w =
|
||||
case j of
|
||||
'c' -> (replicate l ' ') ++ w ++ (replicate r ' ')
|
||||
'r' -> (replicate dl ' ') ++ w
|
||||
'l' -> w ++ (replicate dl ' ')
|
||||
where
|
||||
dl = cw-length w
|
||||
(l,r) = (dl `div` 2, dl-l)
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
package column_alignment
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
|
||||
enum class Align_function {
|
||||
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)) };
|
||||
|
|
@ -16,8 +14,8 @@ enum class Align_function {
|
|||
* @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 Column_aligner(val lines: List<String>) {
|
||||
operator fun invoke(a: Align_function) : String {
|
||||
class ColumnAligner(val lines: List<String>) {
|
||||
operator fun invoke(a: AlignFunction) : String {
|
||||
var result = ""
|
||||
for (lineWords in words) {
|
||||
for (i in lineWords.indices) {
|
||||
|
|
@ -38,26 +36,28 @@ class Column_aligner(val lines: List<String>) {
|
|||
lines.forEach {
|
||||
val lineWords = java.lang.String(it).split("\\$")
|
||||
words += lineWords
|
||||
for (i in lineWords.indices)
|
||||
if (i >= column_widths.size)
|
||||
for (i in lineWords.indices) {
|
||||
if (i >= column_widths.size) {
|
||||
column_widths += lineWords[i].length
|
||||
else
|
||||
} else {
|
||||
column_widths[i] = Math.max(column_widths[i], lineWords[i].length)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
if (args.size < 1)
|
||||
if (args.isEmpty()) {
|
||||
println("Usage: ColumnAligner file [L|R|C]")
|
||||
else {
|
||||
val ca = Column_aligner(Files.readAllLines(Paths.get(args[0]), StandardCharsets.UTF_8))
|
||||
val alignment = if (args.size >= 2) args[1] else "L"
|
||||
when (alignment) {
|
||||
"L" -> print(ca(Align_function.LEFT))
|
||||
"R" -> print(ca(Align_function.RIGHT))
|
||||
"C" -> print(ca(Align_function.CENTER))
|
||||
else -> System.err.println("Error! Unknown alignment: " + alignment)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import strutils, sequtils, strfmt
|
||||
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
|
||||
|
|
@ -7,16 +9,17 @@ column$are$separated$by$at$least$one$space.
|
|||
Further,$allow$for$each$word$in$a$column$to$be$either$left$
|
||||
justified,$right$justified,$or$center$justified$within$its$column."""
|
||||
|
||||
var words = textinfile.splitLines.mapIt(seq[string], it.split '$')
|
||||
var maxs = newSeq[int](max words.mapIt(int, it.len))
|
||||
var words = textinfile.splitLines.mapIt(it.split '$')
|
||||
var maxs = newSeq[int](max words.mapIt(it.len))
|
||||
|
||||
for l in words:
|
||||
for j,w in l:
|
||||
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 l in words:
|
||||
for j,w in l:
|
||||
stdout.write w.format align & $maxs[j]
|
||||
for line in words:
|
||||
for j,w in line:
|
||||
stdout.write(w.format align & $maxs[j])
|
||||
stdout.write "\n"
|
||||
stdout.write "\n"
|
||||
|
|
|
|||
49
Task/Align-columns/Nit/align-columns.nit
Normal file
49
Task/Align-columns/Nit/align-columns.nit
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# 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)
|
||||
74
Task/Align-columns/OoRexx/align-columns.rexx
Normal file
74
Task/Align-columns/OoRexx/align-columns.rexx
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
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
|
||||
|
|
@ -1,34 +1,32 @@
|
|||
/*REXX program displays various alignments for words in a text string.*/
|
||||
cols=0; size=0; wid.=0; t.=; @.= /*zero|nullify some variables*/
|
||||
/* [↓] some "text" lines. */
|
||||
/*REXX program displays various alignments for words in an array of text strings. */
|
||||
cols=0; size=0; wid.=0; t.=; @.= /*zero or nullify some variables. */
|
||||
/* [↓] some "text" lines. */
|
||||
t.1 = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
|
||||
t.2 = "are$delineated$by$a$single$'dollar'$character,$write$a$program"
|
||||
t.3 = "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
|
||||
t.4 = "column$are$separated$by$at$least$one$space."
|
||||
t.5 = "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
|
||||
t.6 = "justified,$right$justified,$or$center$justified$within$its$column."
|
||||
/* [↑] a null line is the end*/
|
||||
do r=1 while t.r\=='' /* [↓] process all text lines*/
|
||||
_=strip(t.r,,'$') /*strip leading & trailing $.*/
|
||||
do c=1 until _=='' /* [↓] process each word. */
|
||||
parse var _ @.r.c '$' _
|
||||
wid.c=max(wid.c, length(@.r.c)) /*max word width.*/
|
||||
/* [↑] a null line is the end of text.*/
|
||||
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 '$' _
|
||||
wid.c=max(wid.c, length(@.r.c)) /*find the maximum word width. */
|
||||
end /*c*/
|
||||
cols=max(cols,c) /*use the maximum COLS found.*/
|
||||
cols=max(cols,c) /*use the maximum COLS found. */
|
||||
end /*r*/
|
||||
|
||||
do k=1 for cols; size=size+wid.k; end /*find width of biggest line.*/
|
||||
rows=r-1 /*adjust ROWS because of DO.*/
|
||||
do j=1 for 3; say; say /*show 2 blank lines for sep.*/
|
||||
say center(word('left right center', j) "aligned", size+cols-1, "═")
|
||||
|
||||
do r=1 for rows; _= /*build row by row*/
|
||||
do c=1 for cols; x=@.r.c /* " col " col*/
|
||||
if j==1 then _=_ left(x, wid.c) /*justified left.*/
|
||||
if j==2 then _=_ right(x, wid.c) /* " right.*/
|
||||
if j==3 then _=_ centre(x, wid.c) /* " center.*/
|
||||
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 _=_ centre(x, wid.c) /* " center. */
|
||||
end /*c*/
|
||||
say substr(_,2) /*ignore the leading extra blank.*/
|
||||
say substr(_, 2) /*ignore the leading extra blank. */
|
||||
end /*r*/
|
||||
end /*j*/
|
||||
/*stick a fork in it, we're done.*/
|
||||
end /*j*/ /*stick a fork in it, we're all done. */
|
||||
|
|
|
|||
|
|
@ -1,40 +1,39 @@
|
|||
/*REXX program displays various alignments for words in a text string.*/
|
||||
cols=0; size=0; wid.=0; t.=; @.= /*zero|nullify some variables*/
|
||||
/* [↓] some "text" lines. */
|
||||
/*REXX pgm displays various (boxed) alignments for words in an array of text strings. */
|
||||
cols=0; size=0; wid.=0; t.=; @.= /*zero or nullify some variables. */
|
||||
/* [↓] some "text" lines. */
|
||||
t.1 = "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
|
||||
t.2 = "are$delineated$by$a$single$'dollar'$character,$write$a$program"
|
||||
t.3 = "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
|
||||
t.4 = "column$are$separated$by$at$least$one$space."
|
||||
t.5 = "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
|
||||
t.6 = "justified,$right$justified,$or$center$justified$within$its$column."
|
||||
/* [↑] a null line is the end*/
|
||||
do r=1 while t.r\=='' /* [↓] process all text lines*/
|
||||
_=strip(t.r,,'$') /*strip leading & trailing $.*/
|
||||
do c=1 until _=='' /* [↓] process each word. */
|
||||
parse var _ @.r.c '$' _
|
||||
wid.c=max(wid.c, length(@.r.c)) /*max word width.*/
|
||||
/* [↑] a null line is the end of text.*/
|
||||
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 '$' _
|
||||
wid.c=max(wid.c, length(@.r.c)) /*find the maximum word width. */
|
||||
end /*c*/
|
||||
cols=max(cols,c) /*use the maximum COLS found.*/
|
||||
cols=max(cols,c) /*use the maximum COLS found. */
|
||||
end /*r*/
|
||||
|
||||
do k=1 for cols; size=size+wid.k; end /*find width of biggest line.*/
|
||||
rows=r-1 /*adjust ROWS because of DO.*/
|
||||
do j=1 for 3; say; say /*show 2 blank lines for sep.*/
|
||||
say center(word('left right center', j) "aligned", size+cols+1, "═")
|
||||
do 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)
|
||||
if j==2 then _=_ || ! || right(x,wid.c)
|
||||
if j==3 then _=_ || ! || centre(x,wid.c)
|
||||
do r=0 to rows; _=; !='│'; if r==0 then !='┬'
|
||||
do c=1 for cols; x=@.r.c
|
||||
if r==0 then x=copies("─", wid.c +1)
|
||||
if j==1 then _=_ || ! || left(x, wid.c)
|
||||
if j==2 then _=_ || ! || right(x, wid.c)
|
||||
if j==3 then _=_ || ! || centre(x, wid.c)
|
||||
end /*c*/
|
||||
if r==0 then do; _= '┌'substr(_,2,length(_)-1)"┐"
|
||||
bot= '└'substr(_,2,length(_)-2)"┘"
|
||||
end
|
||||
else _=_ || !
|
||||
if r==0 then do; _= '┌'substr(_, 2, length(_) -1)"┐"
|
||||
bot= '└'substr(_, 2, length(_) -2)"┘"
|
||||
end
|
||||
else _=_ || !
|
||||
say _
|
||||
end /*r*/
|
||||
/* [↑] shows words in boxes.*/
|
||||
say translate(bot,'┴',"┬")
|
||||
end /*j*/
|
||||
end /*r*/ /* [↑] shows words in boxes. */
|
||||
say translate(bot, '┴', "┬")
|
||||
end /*j*/ /*stick a fork in it, we're all done. */
|
||||
|
|
|
|||
53
Task/Align-columns/Scheme/align-columns.ss
Normal file
53
Task/Align-columns/Scheme/align-columns.ss
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
(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)
|
||||
75
Task/Align-columns/Sed/align-columns.sed
Normal file
75
Task/Align-columns/Sed/align-columns.sed
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#!/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
|
||||
}
|
||||
16
Task/Align-columns/Zkl/align-columns-1.zkl
Normal file
16
Task/Align-columns/Zkl/align-columns-1.zkl
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
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;
|
||||
}
|
||||
11
Task/Align-columns/Zkl/align-columns-2.zkl
Normal file
11
Task/Align-columns/Zkl/align-columns-2.zkl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
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();
|
||||
Loading…
Add table
Add a link
Reference in a new issue