Skip to content

Instantly share code, notes, and snippets.

@petemcfarlane
Created July 14, 2017 16:52
Show Gist options
  • Save petemcfarlane/cc50ac6bc47d040fcda953abf98908c6 to your computer and use it in GitHub Desktop.
Save petemcfarlane/cc50ac6bc47d040fcda953abf98908c6 to your computer and use it in GitHub Desktop.
-module (textprocessing).
-export ([input/0,format/2,format/3,squeezeWordsIntoLine/2,words/1,justify/2,wordsWithSpaces/3]).
input () ->
"The heat bloomed in December
as the carnival season
kicked into gear.
Nearly helpless with sun and glare, I avoided Rio's brilliant
sidewalks
and glittering beaches,
panting in dark corners
and waiting out the inverted southern summer.".
format(Text, LineLength) ->
Words = words(Text),
Lines = squeezeWordsIntoLine(Words, LineLength),
Out = string:join(Lines, "\n"),
io:format("~s~n",[Out]).
format(Text, LineLength, justify) ->
Words = words(Text),
Lines = squeezeWordsIntoLine(Words, LineLength),
Justified = lists:map(fun (Line) -> justify(Line, LineLength) end, Lines),
Out = string:join(Justified, "\n"),
io:format("~s~n",[Out]);
format(Text, LineLength, rightalign) ->
Words = words(Text),
Lines = squeezeWordsIntoLine(Words, LineLength),
RightAligned = lists:map(fun (Line) -> rightAlign(Line, LineLength) end, Lines),
Out = string:join(RightAligned, "\n"),
io:format("~s~n",[Out]);
format(Text, LineLength, center) ->
Words = words(Text),
Lines = squeezeWordsIntoLine(Words, LineLength),
Centered = lists:map(fun (Line) -> center(Line, LineLength) end, Lines),
Out = string:join(Centered, "\n"),
io:format("~s~n",[Out]).
words(Text) ->
string:lexemes(filterLinebreaks(Text), " ").
filterLinebreaks([]) ->
[];
filterLinebreaks([$\n|Xs]) ->
[" " | filterLinebreaks(Xs)];
filterLinebreaks([X|Xs]) ->
[X | filterLinebreaks(Xs)].
squeezeWordsIntoLine([Word|Words], LineLength) ->
squeezeWordsIntoLine(Words, LineLength, Word).
squeezeWordsIntoLine([Word|Words], LineLength, Line) ->
case length(Line ++ " " ++ Word) =< LineLength of
true -> squeezeWordsIntoLine(Words, LineLength, Line ++ " " ++ Word);
false -> [Line] ++ squeezeWordsIntoLine(Words, LineLength, Word)
end;
squeezeWordsIntoLine([], _, Line) ->
[Line].
wordsWithSpaces([], _SpacesPerWord, _Remainer) ->
[];
wordsWithSpaces([Word], _SpacesPerWord, 0) ->
[Word];
wordsWithSpaces([Word|Words], SpacesPerWord, 0) ->
[ Word,string:copies(" ", SpacesPerWord) | wordsWithSpaces(Words, SpacesPerWord, 0) ];
wordsWithSpaces([Word|Words], SpacesPerWord, Remainder) ->
[ Word,string:copies(" ", SpacesPerWord+1) | wordsWithSpaces(Words, SpacesPerWord, Remainder-1) ].
justify(Line, LineLength) when length(Line) == LineLength ->
Line;
justify(Line, LineLength) ->
Words = string:lexemes(Line, " "),
NumberOfWords = length(Words),
case NumberOfWords of
1 -> Line;
_ ->
WordsLength = lists:foldl(fun(Word, Acc) -> length(Word) + Acc end, 0, Words),
TotalSpacesNeeded = LineLength - WordsLength,
NumberOfWords = length(Words),
SpacesPerWord = TotalSpacesNeeded div (NumberOfWords - 1),
SpareSpaces = TotalSpacesNeeded rem (NumberOfWords - 1),
WordsWithSpaces = wordsWithSpaces(Words, SpacesPerWord, SpareSpaces),
string:join(WordsWithSpaces, "")
end.
rightAlign(Line, LineLength) ->
string:pad(Line, LineLength, leading).
center(Line, LineLength) ->
string:pad(Line, LineLength, both).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment