Rosetta Code

Align columns

Align Rosetta Code's dollar-delimited sample text into left, right, and centered columns.

Medium View source
Source rosettacode/popular/align_columns.vibe
# title: Align columns
# source: https://rosettacode.org/wiki/Align_columns
# category: Rosetta Code
# difficulty: Medium
# summary: Align Rosetta Code's dollar-delimited sample text into left, right, and centered columns.
# tags: popular, text-processing, formatting, columns
# vibe: 0.2

def trim_trailing_dollars(line)
  while line.end_with?("$")
    line = line.delete_suffix("$")
  end
  line
end

def split_columns(line)
  trim_trailing_dollars(line).split("$")
end

def column_widths(rows)
  widths = []
  rows.each do |row|
    column = 0
    while column < row.size
      while widths.size <= column
        widths = widths + [0]
      end
      current = widths[column]
      width = row[column].length
      if current == nil || width > current
        widths[column] = width
      end
      column = column + 1
    end
  end
  widths
end

def spaces(count)
  buffer = ""
  index = 0
  while index < count
    buffer = buffer + " "
    index = index + 1
  end
  buffer
end

def left_justify(text, width)
  text + spaces(width - text.length)
end

def right_justify(text, width)
  spaces(width - text.length) + text
end

def center_justify(text, width)
  padded = text
  add_left = false
  while padded.length < width
    if add_left
      padded = " " + padded
      add_left = false
    else
      padded = padded + " "
      add_left = true
    end
  end
  padded
end

def justify(text, width, alignment)
  if alignment == "left"
    left_justify(text, width)
  elsif alignment == "right"
    right_justify(text, width)
  else
    center_justify(text, width)
  end
end

def render_row(row, widths, alignment)
  line = ""
  column = 0
  while column < widths.size
    value = ""
    if column < row.size
      value = row[column]
    end
    line = line + justify(value, widths[column], alignment)
    if column < widths.size - 1
      line = line + " "
    end
    column = column + 1
  end
  line.rstrip
end

def align_columns(lines, alignment)
  rows = []
  lines.each do |line|
    rows = rows + [split_columns(line)]
  end

  widths = column_widths(rows)
  aligned = []
  rows.each do |row|
    aligned = aligned + [render_row(row, widths, alignment)]
  end
  aligned
end

def sample_lines
  [
    "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."
  ]
end

def run
  lines = sample_lines
  rows = []
  lines.each do |line|
    rows = rows + [split_columns(line)]
  end
  widths = column_widths(rows)
  {
    widths: widths,
    left: render_row(rows[0], widths, "left"),
    right: render_row(rows[0], widths, "right"),
    center: render_row(rows[0], widths, "center")
  }
end
Output
Press run to execute run from this example.
rosetta-code popular text-processing formatting columns browser-runner