Text wrapping
終わってたけど 「プログラミングGroovy」のカバーに載せる短いプログラム - Togetter みて考えたもの。
「プログラミングGROOVY」と表示するプログラム。無茶な 3 行だったのできれいにした。
本当は Groovy のロゴをどこかの API でアスキーアートに変換してコマンドプロンプトに表示したかった。
アスキーアートの生成は仲若重人氏の Java のものを Groovy に書き換えただけ。
最初に見つけたのはこれだったけど 3 行まで遠すぎるので途中でやめた。
import java.awt.* import java.awt.image.PixelGrabber as PG import java.awt.image.BufferedImage as BI "プログラミングGROOVY".each { c, w=25, h=25 -> new BI(w, h, BI.TYPE_INT_RGB).with { img -> img.createGraphics().with { g -> g.font = new Font(null, Font.BOLD, [w,h].min()) g.drawString(c, 0, h) } new PG(img, 0, 0, w, h, false).with { pg -> pg.grabPixels() pg.pixels.collect{ it ? '@' : '_' }.join() =~ /.{1,$w}/ }.each { sleep(50) println it } } }
改行処理は最近みた問題から
Wrap the string "The quick brown fox jumps over the lazy dog. " repeated ten times to a max width of 78 chars, starting each line with "> ", yielding this result:
> The quick brown fox jumps over the lazy dog. The quick brown fox jumps
> over the lazy dog. The quick brown fox jumps over the lazy dog. The
> quick brown fox jumps over the lazy dog. The quick brown fox jumps
> over the lazy dog. The quick brown fox jumps over the lazy dog. The
> quick brown fox jumps over the lazy dog. The quick brown fox jumps
> over the lazy dog. The quick brown fox jumps over the lazy dog. The
> quick brown fox jumps over the lazy dog.
問題は 78 文字になっているが、result にあわせて 70 文字で処理した。
expected = [ "> The quick brown fox jumps over the lazy dog. The quick brown fox jumps", "> over the lazy dog. The quick brown fox jumps over the lazy dog. The", "> quick brown fox jumps over the lazy dog. The quick brown fox jumps", "> over the lazy dog. The quick brown fox jumps over the lazy dog. The", "> quick brown fox jumps over the lazy dog. The quick brown fox jumps", "> over the lazy dog. The quick brown fox jumps over the lazy dog. The", "> quick brown fox jumps over the lazy dog.", ] input = "The quick brown fox jumps over the lazy dog. " // Java, Scala, Groovy の回答だったもの // WordUtils を使う @Grab(group='commons-lang', module='commons-lang', version='2.6') import org.apache.commons.lang.WordUtils assert expected == WordUtils.wrap((input * 10).trim(), 70).readLines().collect { "> " + it } // tokenize を使う assert expected == (input * 10).tokenize().inject([] as LinkedList) { acc, v -> if (acc.empty) return acc + v def s = acc.removeLast() acc += ((s + " " + v).size() > 70) ? [s, v] : s + " " + v }.collect { "> " + it } // 正規表現を使う assert expected == (input * 10 =~ /.{1,70} /).collect { "> " + it.trim() }
Groovy にはこの処理に適した String#eachMatch があるが Matcher#iterator を利用すれば他にもいろいろできる*1。
groovy:000> "abc" =~ /./ ===> java.util.regex.Matcher[pattern=. region=0,3 lastmatch=]