mirror of
https://github.com/fooflington/wordsearch.git
synced 2025-01-22 09:19:55 +00:00
initial working import!
This commit is contained in:
commit
865b8df406
19
uk/org/mafoo/wordsearch/Bounds.java
Executable file
19
uk/org/mafoo/wordsearch/Bounds.java
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
package uk.org.mafoo.wordsearch;
|
||||||
|
|
||||||
|
class Bounds {
|
||||||
|
int min_y;
|
||||||
|
int max_y;
|
||||||
|
int min_x;
|
||||||
|
int max_x;
|
||||||
|
|
||||||
|
protected Bounds(int min_y, int max_y, int min_x, int max_x) {
|
||||||
|
this.min_y = min_y;
|
||||||
|
this.max_y = max_y;
|
||||||
|
this.min_x = min_x;
|
||||||
|
this.max_x = max_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "[" + min_x + " < x < " + max_x + " & " + min_y + " < y < " + max_y +"]";
|
||||||
|
}
|
||||||
|
}
|
7
uk/org/mafoo/wordsearch/CouldNotPlaceWordException.java
Executable file
7
uk/org/mafoo/wordsearch/CouldNotPlaceWordException.java
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
package uk.org.mafoo.wordsearch;
|
||||||
|
|
||||||
|
class CouldNotPlaceWordException extends Exception {
|
||||||
|
protected CouldNotPlaceWordException() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
37
uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java
Executable file
37
uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
package uk.org.mafoo.wordsearch;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/20327958/random-number-with-probabilities#20328491
|
||||||
|
|
||||||
|
public class DistributedRandomNumberGenerator {
|
||||||
|
|
||||||
|
private HashMap<Integer, Double> distribution;
|
||||||
|
private double distSum;
|
||||||
|
|
||||||
|
public DistributedRandomNumberGenerator() {
|
||||||
|
distribution = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNumber(int value, double distribution) {
|
||||||
|
if (this.distribution.get(value) != null) {
|
||||||
|
distSum -= this.distribution.get(value);
|
||||||
|
}
|
||||||
|
this.distribution.put(value, distribution);
|
||||||
|
distSum += distribution;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDistributedRandomNumber() {
|
||||||
|
double rand = Math.random();
|
||||||
|
double ratio = 1.0f / distSum;
|
||||||
|
double tempDist = 0;
|
||||||
|
for (Integer i : distribution.keySet()) {
|
||||||
|
tempDist += distribution.get(i);
|
||||||
|
if (rand / ratio <= tempDist) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
319
uk/org/mafoo/wordsearch/GridFactory.java
Executable file
319
uk/org/mafoo/wordsearch/GridFactory.java
Executable file
@ -0,0 +1,319 @@
|
|||||||
|
package uk.org.mafoo.wordsearch;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
class GridFactory {
|
||||||
|
|
||||||
|
static Random rnd = new Random();
|
||||||
|
static final int MAX_TRIES = 500;
|
||||||
|
|
||||||
|
/* https://www.math.cornell.edu/~mec/2003-2004/cryptography/subs/frequencies.html */
|
||||||
|
static DistributedRandomNumberGenerator drng = new DistributedRandomNumberGenerator();
|
||||||
|
static {
|
||||||
|
drng.addNumber(0, 0.0812d); // A
|
||||||
|
drng.addNumber(1, 0.0149d); // B
|
||||||
|
drng.addNumber(2, 0.0271d); // C
|
||||||
|
drng.addNumber(3, 0.0432d); // D
|
||||||
|
drng.addNumber(4, 0.1202d); // E
|
||||||
|
drng.addNumber(5, 0.0230d); // F
|
||||||
|
drng.addNumber(6, 0.0203d); // G
|
||||||
|
drng.addNumber(7, 0.0592d); // H
|
||||||
|
drng.addNumber(8, 0.0731d); // I
|
||||||
|
drng.addNumber(9, 0.0010d); // J
|
||||||
|
drng.addNumber(10, 0.0069d); // K
|
||||||
|
drng.addNumber(11, 0.0398d); // L
|
||||||
|
drng.addNumber(12, 0.0261d); // M
|
||||||
|
drng.addNumber(13, 0.0695d); // N
|
||||||
|
drng.addNumber(14, 0.0768d); // O
|
||||||
|
drng.addNumber(15, 0.0182d); // P
|
||||||
|
drng.addNumber(16, 0.0011d); // Q
|
||||||
|
drng.addNumber(17, 0.0602d); // R
|
||||||
|
drng.addNumber(18, 0.0628d); // S
|
||||||
|
drng.addNumber(19, 0.0910d); // T
|
||||||
|
drng.addNumber(20, 0.0288d); // U
|
||||||
|
drng.addNumber(21, 0.0111d); // V
|
||||||
|
drng.addNumber(22, 0.0209d); // W
|
||||||
|
drng.addNumber(23, 0.0017d); // X
|
||||||
|
drng.addNumber(24, 0.0211d); // Y
|
||||||
|
drng.addNumber(25, 0.0007d); // Z
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char[] chars = new char[] {
|
||||||
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
|
||||||
|
};
|
||||||
|
|
||||||
|
private static char getRandomChar() {
|
||||||
|
return chars[drng.getDistributedRandomNumber()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Test invocation
|
||||||
|
char[][] g = makeGrid(new String[] {
|
||||||
|
"Aberdeenshire",
|
||||||
|
"Anglesey",
|
||||||
|
"Angus",
|
||||||
|
"Antrim",
|
||||||
|
"Argyll",
|
||||||
|
"Armagh",
|
||||||
|
"Ayrshire",
|
||||||
|
"Banffshire",
|
||||||
|
"Bedfordshire",
|
||||||
|
"Berkshire",
|
||||||
|
"Berwickshire",
|
||||||
|
"Brecknockshire",
|
||||||
|
"Buckinghamshire",
|
||||||
|
"Buteshire",
|
||||||
|
"Caernarfonshire",
|
||||||
|
"Caithness",
|
||||||
|
"Cambridgeshire",
|
||||||
|
"Cardiganshire",
|
||||||
|
"Carmarthenshire",
|
||||||
|
"Cheshire",
|
||||||
|
"Clackmannanshire",
|
||||||
|
"Cornwall",
|
||||||
|
"Cromartyshire",
|
||||||
|
"Cumberland",
|
||||||
|
"Denbighshire",
|
||||||
|
"Derbyshire",
|
||||||
|
"Devon",
|
||||||
|
"Dorset",
|
||||||
|
"Down",
|
||||||
|
"Dumbartonshire",
|
||||||
|
"Dumfriesshire",
|
||||||
|
"Durham",
|
||||||
|
"East Lothian",
|
||||||
|
"Essex",
|
||||||
|
"Fermanagh",
|
||||||
|
"Fife",
|
||||||
|
"Flintshire",
|
||||||
|
"Glamorgan",
|
||||||
|
"Gloucestershire",
|
||||||
|
"Hampshire",
|
||||||
|
"Herefordshire",
|
||||||
|
"Hertfordshire",
|
||||||
|
"Huntingdonshire",
|
||||||
|
"Invernessshire",
|
||||||
|
"Kent",
|
||||||
|
"Kincardineshire",
|
||||||
|
"Kirkcudbrightshire",
|
||||||
|
"Lanarkshire",
|
||||||
|
"Lancashire",
|
||||||
|
"Leicestershire",
|
||||||
|
"Lincolnshire",
|
||||||
|
"Londonderry",
|
||||||
|
"Merionethshire",
|
||||||
|
"Middlesex",
|
||||||
|
"Midlothian",
|
||||||
|
"Monmouthshire",
|
||||||
|
"Montgomeryshire",
|
||||||
|
"Morayshire",
|
||||||
|
"Nairnshire",
|
||||||
|
"Norfolk",
|
||||||
|
"Northamptonshire",
|
||||||
|
"Northumberland",
|
||||||
|
"Nottinghamshire",
|
||||||
|
"Orkney",
|
||||||
|
"Oxfordshire",
|
||||||
|
"Peeblesshire",
|
||||||
|
"Pembrokeshire",
|
||||||
|
"Perthshire",
|
||||||
|
"Radnorshire",
|
||||||
|
"Renfrewshire",
|
||||||
|
"Rossshire",
|
||||||
|
"Roxburghshire",
|
||||||
|
"Rutland",
|
||||||
|
"Selkirkshire",
|
||||||
|
"Shetland",
|
||||||
|
"Shropshire",
|
||||||
|
"Somerset",
|
||||||
|
"Staffordshire",
|
||||||
|
"Stirlingshire",
|
||||||
|
"Suffolk",
|
||||||
|
"Surrey",
|
||||||
|
"Sussex",
|
||||||
|
"Sutherland",
|
||||||
|
"Tyrone",
|
||||||
|
"Warwickshire",
|
||||||
|
"West Lothian",
|
||||||
|
"Westmorland",
|
||||||
|
"Wigtownshire",
|
||||||
|
"Wiltshire",
|
||||||
|
"Worcestershire",
|
||||||
|
"Yorkshire",
|
||||||
|
}, Integer.parseInt(args[0]), Integer.parseInt(args[1]));
|
||||||
|
dump2d(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Direction { N, NE, E, SE, S, SW, W, NW; };
|
||||||
|
private static Direction[] directions = new Direction[] { Direction.N, Direction.NE, Direction.E, Direction.SE, Direction.S, Direction.SW, Direction.W, Direction.NW };
|
||||||
|
private static Direction getDirection() {
|
||||||
|
return directions[rnd.nextInt(directions.length-1)];
|
||||||
|
// return rnd.nextBoolean() ? Direction.E : Direction.S;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bounds getBounds(int height, int width, Direction direction, int length) {
|
||||||
|
// height_min
|
||||||
|
if(length > height || length > width) {
|
||||||
|
throw new RuntimeException("Word too long, cannot continue!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Bounds b = new Bounds(0, height, 0, width);
|
||||||
|
length--; // arrays, duh
|
||||||
|
|
||||||
|
if(
|
||||||
|
direction == Direction.N ||
|
||||||
|
direction == Direction.NE ||
|
||||||
|
direction == Direction.NW
|
||||||
|
) {
|
||||||
|
b.min_y = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(
|
||||||
|
direction == Direction.W ||
|
||||||
|
direction == Direction.NW ||
|
||||||
|
direction == Direction.SW
|
||||||
|
) {
|
||||||
|
b.min_x = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(
|
||||||
|
direction == Direction.E ||
|
||||||
|
direction == Direction.NE ||
|
||||||
|
direction == Direction.SE
|
||||||
|
) {
|
||||||
|
b.max_x = width - length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(
|
||||||
|
direction == Direction.S ||
|
||||||
|
direction == Direction.SW ||
|
||||||
|
direction == Direction.SE
|
||||||
|
) {
|
||||||
|
b.max_y = height - length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
assert b.max_x > b.min_x;
|
||||||
|
assert b.max_y > b.min_y;
|
||||||
|
assert b.min_x < b.max_x;
|
||||||
|
assert b.min_y < b.max_y;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int move_y(int y, Direction d) {
|
||||||
|
if(
|
||||||
|
d == Direction.N ||
|
||||||
|
d == Direction.NE ||
|
||||||
|
d == Direction.NW
|
||||||
|
) {
|
||||||
|
y--;
|
||||||
|
} else if (
|
||||||
|
d == Direction.S ||
|
||||||
|
d == Direction.SE ||
|
||||||
|
d == Direction.SW
|
||||||
|
) {
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int move_x(int x, Direction d) {
|
||||||
|
if(
|
||||||
|
d == Direction.E ||
|
||||||
|
d == Direction.NE ||
|
||||||
|
d == Direction.SE
|
||||||
|
) {
|
||||||
|
x++;
|
||||||
|
} else if (
|
||||||
|
d == Direction.W ||
|
||||||
|
d == Direction.NW ||
|
||||||
|
d == Direction.SW
|
||||||
|
) {
|
||||||
|
x--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static char[][] makeGrid(String[] words, int height, int width) {
|
||||||
|
char[][] grid = new char[height][width];
|
||||||
|
|
||||||
|
// Place words at random?
|
||||||
|
for (String word : words) {
|
||||||
|
int tries = 0;
|
||||||
|
while(true) {
|
||||||
|
try {
|
||||||
|
grid = placeWord(word, grid);
|
||||||
|
break;
|
||||||
|
} catch (CouldNotPlaceWordException e) {
|
||||||
|
if(tries > MAX_TRIES) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
tries++;
|
||||||
|
// System.out.println("[" + word + "] Crossed over... retrying");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill rest of grid
|
||||||
|
for (int y=0; y<height; y++) {
|
||||||
|
for (int x=0; x<width; x++) {
|
||||||
|
if (grid[y][x] == Character.UNASSIGNED)
|
||||||
|
// grid[y][x] = '_';
|
||||||
|
grid[y][x] = getRandomChar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char[][] placeWord(String word, char[][] grid) throws CouldNotPlaceWordException {
|
||||||
|
Direction direction = getDirection();
|
||||||
|
Bounds b = getBounds(grid.length, grid[0].length, direction, word.length());
|
||||||
|
// System.out.println("[" + word + "] bounds: " + b);
|
||||||
|
|
||||||
|
int x = rnd.nextInt(b.max_x - b.min_x) + b.min_x;
|
||||||
|
int y = rnd.nextInt(b.max_y - b.min_y) + b.min_y;
|
||||||
|
|
||||||
|
// System.out.println("[" + word + "] Placing @ " + x + "," + y + " going " + direction);
|
||||||
|
char[][] tempgrid = clone2d(grid);
|
||||||
|
for( char c : word.toUpperCase().toCharArray() ) {
|
||||||
|
if(c==' ') continue;
|
||||||
|
if(grid[y][x] != Character.UNASSIGNED) {
|
||||||
|
if (grid[y][x] != c) {
|
||||||
|
throw new CouldNotPlaceWordException();
|
||||||
|
} else {
|
||||||
|
// System.out.println("**** SUCCESSFUL CROSSED WORD ****");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tempgrid[y][x] = c;
|
||||||
|
x = move_x(x, direction);
|
||||||
|
y = move_y(y, direction);
|
||||||
|
|
||||||
|
}
|
||||||
|
return tempgrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char[][] clone2d(char[][] source) {
|
||||||
|
// dump2d(source);
|
||||||
|
char[][] clone = source.clone();
|
||||||
|
|
||||||
|
for(int i=0; i<source.length; i++) {
|
||||||
|
clone[i] = source[i].clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// dump2d(clone);
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void dump2d(char[][] g) {
|
||||||
|
for(char[] row : g) {
|
||||||
|
for(char c : row) {
|
||||||
|
// System.out.print("|");
|
||||||
|
System.out.print(c != Character.UNASSIGNED ? c : " ");
|
||||||
|
}
|
||||||
|
System.out.println("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user