]> gitweb.factorcode.org Git - factor.git/blob - extra/rosetta-code/align-columns/align-columns.factor
84c70190ff4dc60f04cb322221e31779dc25f1e5
[factor.git] / extra / rosetta-code / align-columns / align-columns.factor
1 ! Copyright (c) 2012 Anonymous
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: fry io kernel math math.functions math.order sequences
4 splitting strings ;
5 IN: rosetta.align-columns
6
7 ! http://rosettacode.org/wiki/Align_columns
8
9 ! Given a text file of many lines, where fields within a line
10 ! are delineated by a single 'dollar' character, write a program
11 ! that aligns each column of fields by ensuring that words in each
12 ! column are separated by at least one space. Further, allow for
13 ! each word in a column to be either left justified, right
14 ! justified, or center justified within its column.
15
16 ! Use the following text to test your programs:
17
18 ! Given$a$text$file$of$many$lines,$where$fields$within$a$line$
19 ! are$delineated$by$a$single$'dollar'$character,$write$a$program
20 ! that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
21 ! column$are$separated$by$at$least$one$space.
22 ! Further,$allow$for$each$word$in$a$column$to$be$either$left$
23 ! justified,$right$justified,$or$center$justified$within$its$column.
24
25 ! Note that:
26
27 ! * The example input texts lines may, or may not, have trailing
28 !   dollar characters.
29 ! * All columns should share the same alignment.
30 ! * Consecutive space characters produced adjacent to the end of
31 !   lines are insignificant for the purposes of the task.
32 ! * Output text will be viewed in a mono-spaced font on a plain
33 !   text editor or basic terminal.
34 ! * The minimum space between columns should be computed from
35 !   the text and not hard-coded.
36 ! * It is not a requirement to add separating characters between
37 !   or around columns.
38
39 CONSTANT: example-text "Given$a$text$file$of$many$lines,$where$fields$within$a$line$
40 are$delineated$by$a$single$'dollar'$character,$write$a$program
41 that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
42 column$are$separated$by$at$least$one$space.
43 Further,$allow$for$each$word$in$a$column$to$be$either$left$
44 justified,$right$justified,$or$center$justified$within$its$column."
45
46 : split-and-pad ( text -- lines )
47     split-lines [ "$" split harvest ] map
48     dup longest length
49     '[ _ "" pad-tail ] map ;
50
51 : column-widths ( columns -- widths )
52     [ longest length ] map ;
53
54 SINGLETONS: +left+ +middle+ +right+ ;
55
56 GENERIC: align-string ( str n alignment -- str' )
57
58 M: +left+ align-string  drop CHAR: space pad-tail ;
59 M: +right+ align-string drop CHAR: space pad-head ;
60
61 M: +middle+ align-string
62     drop
63     over length - 2 /
64     [ floor CHAR: space <string> ]
65     [ ceiling CHAR: space <string> ] bi surround ;
66
67 : align-columns ( columns alignment -- columns' )
68     [ dup column-widths ] dip '[
69         [ _ align-string ] curry map
70     ] 2map ;
71
72 : print-aligned ( text alignment -- )
73     [ split-and-pad flip ] dip align-columns flip
74     [ [ write bl ] each nl ] each ;
75
76 ! USAGE: example-text +left+ print-aligned