diff --git a/book/src/com/github/donkirkby/vograbulary/VograbularyBook.java b/book/src/com/github/donkirkby/vograbulary/VograbularyBook.java index 171f671..6017768 100644 --- a/book/src/com/github/donkirkby/vograbulary/VograbularyBook.java +++ b/book/src/com/github/donkirkby/vograbulary/VograbularyBook.java @@ -10,6 +10,7 @@ import java.util.List; import com.github.donkirkby.vograbulary.poemsorting.Poem; +import com.github.donkirkby.vograbulary.poemsorting.PoemDisplay; public class VograbularyBook { public static void main(String[] args) { @@ -63,29 +64,26 @@ private static void populate(PrintWriter writer) { title, solutionPositions.get(i) + 1); writer.printf("\\poemtitle{%s}\n", title); - writer.write("\\begin{verse}\n"); - Poem sorted = poem.sortWords(); - for (String line : sorted.getLines()) { - String[] words = line.split(" "); - for (int wordIndex = 0; wordIndex < words.length; wordIndex++) { - String word = words[wordIndex]; - writer.write("\\(\\def\\stacktype{L}\\rule{0pt}{\\baselineskip}\n"); - for (int charIndex = 0; charIndex < word.length(); charIndex++) { - String cString = word.substring(charIndex, charIndex+1); - char c = cString.charAt(0); - if (c < 'a' || 'z' < c) { - writer.write(cString); - } - else { - writer.printf("\\stackunder{\\Huge{\\_}}{%s}\n", cString); - } - } - writer.printf( - "\\)%s\n", - wordIndex == words.length-1 ? "\\\\" : "\\rule{5pt}{0pt}"); + writer.printf("\\begin{verbatim}\n"); + PoemDisplay display = new PoemDisplay(poem, 60); + for (int lineIndex = 0; lineIndex < display.getBodyLineCount(); lineIndex++) { + writer.write("\n\n"); + for (int charIndex = 0; charIndex < display.getWidth(); charIndex++) { + writer.write(display.getBody(lineIndex, charIndex)); + } + writer.write('\n'); + } + for (int charIndex = 0; charIndex < display.getWidth(); charIndex++) { + writer.write("-"); + } + writer.write('\n'); + for (int lineIndex = 0; lineIndex < display.getClueLineCount(); lineIndex++) { + for (int charIndex = 0; charIndex < display.getWidth(); charIndex++) { + writer.write(display.getClue(lineIndex, charIndex)); } + writer.write('\n'); } - writer.write("\\end{verse}"); + writer.write("\\end{verbatim}"); } writer.write("\\newpage\\Large\\textbf{Solutions}\n"); for (int i = 0; i < poemCount; i++) { diff --git a/core/src/com/github/donkirkby/vograbulary/poemsorting/PoemDisplay.java b/core/src/com/github/donkirkby/vograbulary/poemsorting/PoemDisplay.java new file mode 100644 index 0000000..c72ca95 --- /dev/null +++ b/core/src/com/github/donkirkby/vograbulary/poemsorting/PoemDisplay.java @@ -0,0 +1,86 @@ +package com.github.donkirkby.vograbulary.poemsorting; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class PoemDisplay { + private int width; + private int clueLineCount; + private List bodyLines = new ArrayList(); + private List clueColumns = new ArrayList(); + + public PoemDisplay(Poem poem, int width) { + List poemLines = new ArrayList(); + Poem sortedPoem = poem.sortWords(); + final int poemLineCount = poem.getLines().size(); + for (int poemLineIndex = 0; poemLineIndex < poemLineCount; poemLineIndex++) { + String poemLine = poem.getLines().get(poemLineIndex); + String sortedLine = sortedPoem.getLines().get(poemLineIndex); + String indent = ""; + int start = 0; + int lastBreak = 0; + for (int charIndex = 0; charIndex < poemLine.length(); charIndex++) { + boolean shouldAdd; + if (charIndex == poemLine.length() - 1) { + shouldAdd = true; + lastBreak = poemLine.length(); + } + else { + if (poemLine.charAt(charIndex) == ' ') { + lastBreak = charIndex; + } + shouldAdd = charIndex - start >= width; + } + if (shouldAdd) { + poemLines.add(indent + poemLine.substring(start, lastBreak)); + bodyLines.add(indent + sortedLine.substring(start, lastBreak)); + start = lastBreak+1; + indent = " "; + } + } + } + this.width = 0; + for (String line : bodyLines) { + this.width = Math.max(this.width, line.length()); + } + char column[] = new char[bodyLines.size()]; + for (int charIndex = 0; charIndex < this.width; charIndex++) { + int letterCount = 0; + for (int lineIndex = 0; lineIndex < poemLines.size(); lineIndex++) { + final String line = poemLines.get(lineIndex); + char c = charIndex < line.length() + ? Character.toLowerCase(line.charAt(charIndex)) + : ' '; + if ('a' <= c && c <= 'z') { + column[letterCount++] = c; + } + } + Arrays.sort(column, 0, letterCount); + clueColumns.add(new String(column, 0, letterCount)); + clueLineCount = Math.max(clueLineCount, letterCount); + } + } + + public int getWidth() { + return width; + } + + public int getBodyLineCount() { + return bodyLines.size(); + } + + public char getBody(int lineIndex, int charIndex) { + String line = bodyLines.get(lineIndex); + return charIndex < line.length() ? line.charAt(charIndex) : ' '; + } + + public int getClueLineCount() { + return clueLineCount; + } + + public char getClue(int lineIndex, int charIndex) { + String line = charIndex < clueColumns.size() ? clueColumns.get(charIndex) : ""; + return lineIndex < line.length() ? line.charAt(lineIndex) : ' '; + } +} diff --git a/vograbulary-test/src/com/github/donkirkby/vograbulary/poemsorting/PoemDisplayTest.java b/vograbulary-test/src/com/github/donkirkby/vograbulary/poemsorting/PoemDisplayTest.java new file mode 100644 index 0000000..3047f76 --- /dev/null +++ b/vograbulary-test/src/com/github/donkirkby/vograbulary/poemsorting/PoemDisplayTest.java @@ -0,0 +1,63 @@ +package com.github.donkirkby.vograbulary.poemsorting; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.util.List; + +import org.junit.Test; + +public class PoemDisplayTest { + @Test + public void display() { + List poems = Poem.load( + "Guess I'm a poet,", + "I didn't know it."); + int width = 15; + String expectedDisplay = + "egssu i'm a \n" + + " eopt, \n" + + "i ddin't know\n" + + " it. \n" + + "gudidnetmkaow\n" + + "i esioit n \n" + + " pt \n" + + " s \n"; + PoemDisplay display = new PoemDisplay(poems.get(0), width); + + assertThat("display", buildTextDisplay(display), is(expectedDisplay)); + } + + @Test + public void displayBlankColumn() { + List poems = Poem.load( + "Guess I'm a poet,", + "I did not know it."); + int width = 20; + String expectedDisplay = + "egssu i'm a eopt, \n" + + "i ddi not know it.\n" + + "gudid iom anooeit \n" + + "i ess n t k pw t \n"; + PoemDisplay display = new PoemDisplay(poems.get(0), width); + + assertThat("display", buildTextDisplay(display), is(expectedDisplay)); + } + + private String buildTextDisplay(PoemDisplay display) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < display.getBodyLineCount(); i++) { + for (int j = 0; j < display.getWidth(); j++) { + builder.append(display.getBody(i, j)); + } + builder.append('\n'); + } + for (int i = 0; i < display.getClueLineCount(); i++) { + for (int j = 0; j < display.getWidth(); j++) { + builder.append(display.getClue(i, j)); + } + builder.append('\n'); + } + return builder.toString(); + } +}