90 lines
2 KiB
Text
90 lines
2 KiB
Text
class SmartWordWrap {
|
|
|
|
has width = 80
|
|
|
|
method prepare_words(array, depth=0, callback) {
|
|
|
|
var root = []
|
|
var len = 0
|
|
var i = -1
|
|
|
|
var limit = array.end
|
|
while (++i <= limit) {
|
|
len += (var word_len = array[i].len)
|
|
|
|
if (len > width) {
|
|
if (word_len > width) {
|
|
len -= word_len
|
|
array.splice(i, 1, array[i].split(width)...)
|
|
limit = array.end
|
|
--i; next
|
|
}
|
|
break
|
|
}
|
|
|
|
root << [
|
|
array.first(i+1).join(' '),
|
|
self.prepare_words(array.slice(i+1), depth+1, callback)
|
|
]
|
|
|
|
if (depth.is_zero) {
|
|
callback(root[0])
|
|
root = []
|
|
}
|
|
|
|
break if (++len >= width)
|
|
}
|
|
|
|
root
|
|
}
|
|
|
|
method combine(root, path, callback) {
|
|
var key = path.shift
|
|
path.each { |value|
|
|
root << key
|
|
if (value.is_empty) {
|
|
callback(root)
|
|
}
|
|
else {
|
|
value.each { |item|
|
|
self.combine(root, item, callback)
|
|
}
|
|
}
|
|
root.pop
|
|
}
|
|
}
|
|
|
|
method wrap(text, width) {
|
|
|
|
self.width = width
|
|
var words = (text.kind_of(Array) ? text : text.words)
|
|
|
|
var best = Hash(
|
|
score => Inf,
|
|
value => [],
|
|
)
|
|
|
|
self.prepare_words(words, callback: { |path|
|
|
self.combine([], path, { |combination|
|
|
var score = 0
|
|
combination.first(-1).each { |line|
|
|
score += (width - line.len -> sqr)
|
|
}
|
|
|
|
if (score < best{:score}) {
|
|
best{:score} = score
|
|
best{:value} = []+combination
|
|
}
|
|
})
|
|
})
|
|
|
|
best{:value}.join("\n")
|
|
}
|
|
}
|
|
|
|
var sww = SmartWordWrap()
|
|
|
|
var words = %w(aaa bb cc ddddd)
|
|
var wrapped = sww.wrap(words, 6)
|
|
|
|
say wrapped
|