Skip to content

Instantly share code, notes, and snippets.

@ashutoshraina
Forked from CyrusJavan/justify_text.go
Created October 25, 2020 01:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ashutoshraina/304887c397fad698ad974fde460d1685 to your computer and use it in GitHub Desktop.
Save ashutoshraina/304887c397fad698ad974fde460d1685 to your computer and use it in GitHub Desktop.
Justify Text - techincal interview question and answer written in Golang with many comments explaing the answer.
package main
import (
"fmt"
"strings"
)
func main() {
text := "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras " +
"venenatis, quam et dapibus porttitor, nisi mauris maximus sapien, a " +
"tempor est risus sed felis. Morbi vitae nunc iaculis, eleifend dolor " +
"eget, congue dolor. Ut id convallis augue. Curabitur quis nisi a nulla " +
"tempus aliquet. In non pellentesque elit, eu vulputate elit. " +
"Suspendisse potenti. Fusce elit ipsum, dapibus sed finibus ac, " +
"tincidunt in neque."
maxWidth := 22
fmt.Println(justifyText(text, maxWidth))
}
// Justifying Text: Given an input string and an maxWidth integer, return a string that is the input justified to the given maxWidth.
//
// text="The quick brown fox jumps over the lazy dog”
// maxWidth=16
// Output:
// The quick brown
// fox jumps over
// the lazy dog
func justifyText(text string, maxWidth int) string {
// Split the text into words
words := strings.Split(text, " ")
// Keep track of current line and previous lines
var lines, current string
// Iterate through each word
for _, word := range words {
// If the word fits, add to current
if len(current)+len(word) <= maxWidth {
// All words need a space after, expect for the last word
// we will trim the space for the last word
current += word + " "
continue
}
// Otherwise, word did not fit so lets finish this line
// Trim extra space from the last word
current = current[:len(current)-1]
// Distribute any extra spaces and add current line to previous lines
lines += distributeSpaces(current, maxWidth-len(current))
// The next iteration current line will be this word that did not fit
current = word + " "
}
// return the previous lines and any current line we were working on
return lines + current
}
// distributeSpaces will spread extra amount of whitespaces into the gaps
// between the words in s
func distributeSpaces(s string, extra int) string {
// Nothing to do, return early
if extra < 1 {
return s + "\n"
}
// Split into tokens as it's easier to work with
words := strings.Split(s, " ")
// Edge case where only 1 word is on a line
// we can just put all extra space at the end then return
if len(words) == 1 {
for extra > 0 {
words[0] += " "
extra--
}
return words[0] + "\n"
}
// calculate how many spaces between each word and any extra that dont
// divide evenly into the gaps
gaps := len(words) - 1
spaces := extra + gaps
spacePerGap, extraSpace := spaces/gaps, spaces%gaps
// Distribute the spaces that dont fit evenly
for i := 0; extraSpace > 0; i++ {
words[i] += " "
extraSpace--
}
// Make a tmp spacer for the whitespace that does divide evenly
tmp := ""
for spacePerGap > 0 {
tmp += " "
spacePerGap--
}
// Join the words with the tmp spacer
return strings.Join(words, tmp) + "\n"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment