36 lines
1.5 KiB
Plaintext
36 lines
1.5 KiB
Plaintext
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)
|