RosettaCodeData/Task/Align-columns/Elixir/align-columns.elixir

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)