mirror of
https://github.com/fooflington/wordsearch.git
synced 2025-01-22 01:09:54 +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