Last active
October 12, 2018 19:56
-
-
Save JochemKuijpers/208acec59dc17e2b5afd84eb3922b150 to your computer and use it in GitHub Desktop.
Letter Clock generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.*; | |
public class Main { | |
public static void main(String[] args) { | |
int targetRows = 16; | |
int width = 16; | |
long tries = 0; | |
double bestScore = 0; | |
List<String> words = new ArrayList<>(); | |
List<String> result = new ArrayList<>(); | |
while (true) { | |
tries++; | |
System.out.printf("\rattempt: #%d", tries); | |
words.clear(); | |
result.clear(); | |
double score = generateWords(words); | |
int length = 0; | |
String currentRow = ""; | |
for (String word : words) { | |
// ignore space at the beginning of the word if the word starts a new row | |
boolean postfixWhitespace = word.endsWith(" "); | |
if (currentRow.length() == 0 && word.startsWith(" ")) { | |
word = word.substring(1); | |
} | |
if (postfixWhitespace) { | |
word = word.substring(0, word.length() - 1); | |
} | |
// place the next word on this row with as much overlap as possible | |
for (int i = word.length(); i >= 0; i--) { | |
// but if that isn't possible, move to the next row. | |
if (currentRow.length() + (word.length() - i) > width) { | |
result.add(currentRow); | |
length += currentRow.length(); | |
currentRow = ""; | |
i = 0; | |
if (word.startsWith(" ")) { | |
word = word.substring(1); | |
} | |
} | |
// find as much overlap as possible (by i decreasing form word.length() to 0) | |
if (currentRow.endsWith(word.substring(0, i))) { | |
currentRow += word.substring(i); | |
break; | |
} | |
} | |
// add whitespace if the current word ended with whitespace | |
if (currentRow.length() < width && postfixWhitespace) { | |
currentRow += " "; | |
} | |
} | |
result.add(currentRow); | |
length += currentRow.length() * 0.1; | |
score += length; | |
if (result.size() <= targetRows) { | |
if (score > bestScore) { | |
bestScore = score; | |
System.out.printf("\nFound a solution! %2d characters, %2d rows, score: %8.2f\n", length, result.size(), score); | |
for (String line : result) { | |
for (int c : line.chars().toArray()) { | |
System.out.print((char) c + " "); | |
} | |
System.out.print('\n'); | |
} | |
System.out.println("- - - - - - - - - - - - - - - -\n"); | |
} | |
} | |
} | |
} | |
private static double generateWords(List<String> words) { | |
Random random = new Random(System.nanoTime()); | |
double score = 0.0; | |
// greeting | |
words.add(" GOEDE "); | |
List<String> orderedDayParts = Arrays.asList("MORGEN", "MIDDAG", "AVOND", "NACHT"); | |
List<String> dayParts = new ArrayList<>(orderedDayParts); | |
Collections.shuffle(dayParts); | |
score += scoreShuffledList(orderedDayParts, dayParts); | |
words.addAll(dayParts); | |
words.addAll(Arrays.asList(" ", " HET ", " IS ")); | |
// day | |
words.addAll(Arrays.asList("MA", "DI", "WO", "DO", "VR", "ZA", "ZO")); | |
words.add(" "); | |
// day of month | |
List<String> orderedDom = Arrays.asList("10", "11", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"); | |
List<String> dom = new ArrayList<>(orderedDom); | |
Collections.shuffle(dom); | |
score += scoreShuffledList(orderedDom, dom); | |
words.addAll(dom); | |
words.add(" "); | |
// month | |
List<String> orderedMonths = Arrays.asList("JAN", "FEB", "MAA", "APR", "MEI", "JUN", "JUL", "AUG", "SEP", "OKT", "NOV", "DEC"); | |
List<String> months = new ArrayList<>(orderedMonths); | |
Collections.shuffle(months); | |
score += scoreShuffledList(orderedMonths, months); | |
words.addAll(months); | |
words.add(" "); | |
// weather | |
if (random.nextBoolean()) { | |
words.addAll(Arrays.asList(" HET ", " WEER ", " IS ")); | |
} else { | |
words.addAll(Arrays.asList(" HET ", " WEER: ")); | |
} | |
List<String> weather = Arrays.asList("REGENACHTIG", "ONBEWOLKT"); // BEWOLKT is a substring of ONBEWOLKT | |
words.addAll(weather); | |
// 5/10/15 | |
words.addAll(Arrays.asList(" HET ", " IS ")); | |
if (random.nextBoolean()) { | |
List<String> minutes = Arrays.asList("VIJF", "TIEN", "KWART"); | |
Collections.shuffle(minutes); | |
words.addAll(minutes); | |
} else { | |
words.add("VIJFTIEN"); | |
} | |
words.add(" "); | |
// past/to | |
List<String> pastto = Arrays.asList("VOOR", "OVER"); | |
Collections.shuffle(pastto); | |
words.addAll(pastto); | |
words.add(" HALF "); | |
// uren | |
List<String> orderedHours = Arrays.asList("EEN", "TWEE", "DRIE", "VIER", "VIJF", "ZES", "ZEVEN", "ACHT", "NEGEN", "TIEN", "ELF", "TWAALF"); | |
List<String> hours = new ArrayList<>(orderedHours); | |
Collections.shuffle(hours); | |
score += scoreShuffledList(orderedHours, hours); | |
words.addAll(hours); | |
return score; | |
} | |
private static double scoreShuffledList(List<String> orderedList, List<String> shuffledList) { | |
// compute the number of items in original place | |
double score = 0.0; | |
for (int i = 0; i < orderedList.size(); i++) { | |
int difference = Math.abs(i - shuffledList.indexOf(orderedList.get(i))); | |
score -= Math.pow(difference, 1.5) + 10 * difference; | |
} | |
score /= orderedList.size(); | |
return score; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment