Compare commits
4 commits
472106ba3a
...
500dcc1b9a
Author | SHA1 | Date | |
---|---|---|---|
500dcc1b9a | |||
45a9ae4f20 | |||
6aab6e4b96 | |||
79dbff72c1 |
4 changed files with 87 additions and 13 deletions
10
README.md
Normal file
10
README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Crossword generator
|
||||
|
||||
### Usage
|
||||
See `src/main/java/eu/m724/crossword/Main.java`
|
||||
|
||||
### Speed
|
||||
Generally, slow. \
|
||||
Compared to mining:
|
||||
- difficulty: the "tighter", the slower. It has to fit the words on the surface somehow, it bruteforces a good placement, if it's more crowded it'll have to try harder
|
||||
- luck
|
|
@ -80,6 +80,11 @@ public class Generator {
|
|||
}
|
||||
System.out.println("Possible placements: " + possiblePlacements.size() + " * 2");
|
||||
|
||||
int totalCharacters = Arrays.stream(words).map(w -> w.length() + 1).reduce(0, Integer::sum);
|
||||
if (totalCharacters > possiblePlacements.size()) {
|
||||
System.out.printf("Warning: there might be no solution (%d > %d)", totalCharacters, possiblePlacements.size());
|
||||
}
|
||||
|
||||
/*for (Word word : words) {
|
||||
PlacedWord placedWord = null;
|
||||
|
||||
|
@ -144,11 +149,14 @@ public class Generator {
|
|||
|
||||
List<Vec> currentPossiblePlacements = new ArrayList<>(possiblePlacements);
|
||||
shuffle(currentPossiblePlacements);
|
||||
//Collections.shuffle(currentPossiblePlacements);
|
||||
|
||||
boolean vertical = random.nextBoolean();
|
||||
Word word = words[wordIndex];
|
||||
|
||||
// TODO optimize. maybe make this a list. and consider if this is really necessary.
|
||||
Map<Integer, List<PlacedWord>> rankedPlacements = new LinkedHashMap<>();
|
||||
int hi = -1;
|
||||
|
||||
for (int i=0; i<2; i++) { // repeating twice to pass horizontal and vertical
|
||||
vertical = !vertical;
|
||||
|
||||
|
@ -162,10 +170,24 @@ public class Generator {
|
|||
}
|
||||
|
||||
PlacedWord candidate = new PlacedWord(placement, vertical, word);
|
||||
int placementResult = grid.canPlace(candidate);
|
||||
|
||||
if (grid.canPlace(candidate)) {
|
||||
System.out.println(" Found candidate");
|
||||
if (placementResult != -1) {
|
||||
//System.out.println(" Found candidate");
|
||||
rankedPlacements.computeIfAbsent(placementResult, k -> new ArrayList<>()).add(candidate);
|
||||
if (placementResult > hi) hi = placementResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("hi " + hi);
|
||||
|
||||
for (int i=hi; i>=0; i--) {
|
||||
//List<PlacedWord> candidates = rankedPlacements.getOrDefault(i, new ArrayList<>());
|
||||
//System.out.println(" Candidates: " + candidates.size());
|
||||
for (PlacedWord candidate : rankedPlacements.getOrDefault(i, new ArrayList<>())) {
|
||||
Set<PlacedWord> potentialChain = new HashSet<>(placedChain);
|
||||
|
||||
potentialChain.add(candidate);
|
||||
|
||||
Grid newGrid = grid.clone();
|
||||
|
@ -176,15 +198,51 @@ public class Generator {
|
|||
|
||||
// if it's null it means there's no good placement, and we should continue searching at this depth
|
||||
if (newChain != null) {
|
||||
System.out.println(" Unfolding"); // is that a correct word?
|
||||
System.out.println(" Done here");
|
||||
return newChain;
|
||||
} else {
|
||||
System.out.println(" Looking further");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*for (int i=0; i<2; i++) { // repeating twice to pass horizontal and vertical
|
||||
vertical = !vertical;
|
||||
|
||||
for (Vec placement : currentPossiblePlacements) {
|
||||
if (vertical) {
|
||||
int y = placement.y();
|
||||
if (y == 0 || y + word.length() >= height) continue;
|
||||
} else {
|
||||
int x = placement.x();
|
||||
if (x == 0 || x + word.length() >= width) continue;
|
||||
}
|
||||
|
||||
PlacedWord candidate = new PlacedWord(placement, vertical, word);
|
||||
|
||||
if (grid.canPlace(candidate) != -1) {
|
||||
//System.out.println(" Found candidate");
|
||||
Set<PlacedWord> potentialChain = new HashSet<>(placedChain);
|
||||
potentialChain.add(candidate);
|
||||
|
||||
Grid newGrid = grid.clone();
|
||||
newGrid.placeWord(candidate);
|
||||
|
||||
Set<PlacedWord> newChain = follow(newGrid, potentialChain, wordIndex + 1);
|
||||
//System.out.println("Back to depth " + wordIndex);
|
||||
|
||||
// if it's null it means there's no good placement, and we should continue searching at this depth
|
||||
if (newChain != null) {
|
||||
//System.out.println(" Unfolding"); // is that a correct word?
|
||||
return newChain;
|
||||
} else {
|
||||
//System.out.println(" Looking further");
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
System.out.println(" No solution");
|
||||
// no placement at this depth
|
||||
return null;
|
||||
|
|
|
@ -46,9 +46,11 @@ public class Grid implements Cloneable {
|
|||
* Can a word be placed, will it not collide
|
||||
*
|
||||
* @param word The word
|
||||
* @return can it be placed
|
||||
* @return can it be placed. -1 = no, 0 = yes, >0 = yes and will be over n characters
|
||||
*/
|
||||
public boolean canPlace(PlacedWord word) {
|
||||
public int canPlace(PlacedWord word) {
|
||||
int cols = 0;
|
||||
|
||||
int x = word.pos().x();
|
||||
int y = word.pos().y();
|
||||
|
||||
|
@ -67,12 +69,16 @@ public class Grid implements Cloneable {
|
|||
c = word.word().text().charAt(i);
|
||||
}
|
||||
|
||||
if (charArray[_x][_y] != 0 && charArray[_x][_y] != c) {
|
||||
return false;
|
||||
if (charArray[_x][_y] != 0) {
|
||||
if (charArray[_x][_y] != c) {
|
||||
return -1;
|
||||
} else {
|
||||
cols++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return cols;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,7 +2,7 @@ package eu.m724.crossword;
|
|||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
CrosswordBuilder builder = new CrosswordBuilder(12, 12, "crossword")
|
||||
CrosswordBuilder builder = new CrosswordBuilder(20, 20, "crossword")
|
||||
.addWord("cat", "Furry feline pet")
|
||||
.addWord("owl", "Nocturnal bird of prey")
|
||||
.addWord("kite", "Flying toy on a string")
|
||||
|
|
Loading…
Reference in a new issue