Skip to content

Instantly share code, notes, and snippets.

@monorkin
Created September 29, 2018 22:38
Show Gist options
  • Save monorkin/047cd217b8999515e4981c5b97652d54 to your computer and use it in GitHub Desktop.
Save monorkin/047cd217b8999515e4981c5b97652d54 to your computer and use it in GitHub Desktop.
def justify(text, width)
return if text.nil? || width.nil? || width.negative?
words = text.split(' ')
rows = group_words_into_rows(words, width)
rows = pad_rows(rows, width)
rows.map(&:join).join("\n")
end
def group_words_into_rows(words, width)
width = 1 if width.zero?
length = 0
rows = words.group_by do |word|
length += 1 unless length.zero?
length += word.length
length / width
end
# Not strictly necessary but ensures a stabile sort
rows.sort_by { |length, row| length }.map { |_, row| row }
end
def pad_rows(rows, width)
padded_rows = rows.map { |row| pad_row(row, width) }
# Last row shouldn't be padded
if rows.count > 1
padded_rows[0..-2] + [rows[-1]]
else
padded_rows
end
end
def pad_row(row, width)
length = row.map(&:length).sum
spaces_count = width - length
positions = row.length - 1
return row if positions <= 0
return row if spaces_count <= 0
spaces_per_position, extra_spaces_for_positions = spaces_count.divmod(positions)
paddings = build_paddings(positions, spaces_per_position, extra_spaces_for_positions)
row.zip(paddings).flatten.compact
end
def build_paddings(positions, spaces_per_position, extra_spaces_for_positions)
spaces = ' ' * spaces_per_position
(1..positions).map do |_|
extra_spaces = if extra_spaces_for_positions.positive?
extra_spaces_for_positions -= 1
' '
else
''
end
spaces + extra_spaces
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment