introduce bitloops
This commit is contained in:
@@ -83,6 +83,9 @@ public record Export() {
|
|||||||
|
|
||||||
record LetterAt(int index, byte letter) {
|
record LetterAt(int index, byte letter) {
|
||||||
|
|
||||||
|
public char human() {
|
||||||
|
return (char) (letter | 64);
|
||||||
|
}
|
||||||
static LetterAt from(int index, byte[] bytes) { return new LetterAt(index, bytes[index]); }
|
static LetterAt from(int index, byte[] bytes) { return new LetterAt(index, bytes[index]); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,18 +238,14 @@ public record Export() {
|
|||||||
return simpel;
|
return simpel;
|
||||||
}
|
}
|
||||||
public ExportedPuzzle exportFormatFromFilled(int difficulty, Rewards rewards) {
|
public ExportedPuzzle exportFormatFromFilled(int difficulty, Rewards rewards) {
|
||||||
var placed = new ArrayList<Placed>();
|
|
||||||
for (var slot : slots) {
|
|
||||||
placed.add(new Placed(slot.assign().w, slot.key(), Gridded.walk((byte) slot.key(), slot.lo(), slot.hi()).toArray()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If nothing placed: return full grid mapped to letters/# only
|
// If nothing placed: return full grid mapped to letters/# only
|
||||||
if (placed.isEmpty()) {
|
if (slots.length == 0) {
|
||||||
return new ExportedPuzzle(grid.exportGrid(clues.c, _ -> '#', '#'), new WordOut[0], difficulty, rewards);
|
return new ExportedPuzzle(grid.exportGrid(clues.c, _ -> '#', '#'), new WordOut[0], difficulty, rewards);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) bounding box around all word cells + arrow cells, with 1-cell margin
|
var placed = Arrays.stream(slots).map(slot -> new Placed(slot.assign().w, slot.key(), Gridded.walk((byte) slot.key(), slot.lo(), slot.hi()).toArray())).toArray(Placed[]::new);
|
||||||
|
|
||||||
|
// 2) bounding box around all word cells + arrow cells, with 1-cell margin
|
||||||
int minR = Integer.MAX_VALUE, minC = Integer.MAX_VALUE;
|
int minR = Integer.MAX_VALUE, minC = Integer.MAX_VALUE;
|
||||||
int maxR = Integer.MIN_VALUE, maxC = Integer.MIN_VALUE;
|
int maxR = Integer.MIN_VALUE, maxC = Integer.MIN_VALUE;
|
||||||
|
|
||||||
@@ -265,23 +264,18 @@ public record Export() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3) map of only used letter cells (everything else becomes '#')
|
// 3) map of only used letter cells (everything else becomes '#')
|
||||||
var letterAt = new HashMap<Integer, Character>();
|
var map = grid.stream(clues.c()).collect(Collectors.toMap(LetterAt::index, LetterAt::human));
|
||||||
grid.forEachLetter(clues.c(), (idx, letter) -> {
|
|
||||||
if (letter == 0) return;
|
|
||||||
letterAt.put(idx, (char) (64 | letter));
|
|
||||||
});
|
|
||||||
|
|
||||||
// 4) render gridv2 over cropped bounds (out-of-bounds become '#')
|
// 4) render gridv2 over cropped bounds (out-of-bounds become '#')
|
||||||
var gridv2 = new String[Math.max(0, maxR - minR + 1)];
|
var gridv2 = new String[Math.max(0, maxR - minR + 1)];
|
||||||
for (int r = minR, i = 0; r <= maxR; r++, i++) {
|
for (int r = minR, i = 0; r <= maxR; r++, i++) {
|
||||||
var row = new StringBuilder(Math.max(0, maxC - minC + 1));
|
var row = new StringBuilder(Math.max(0, maxC - minC + 1));
|
||||||
for (var c = minC; c <= maxC; c++) row.append(letterAt.getOrDefault(Grid.offset(r, c), '#'));
|
for (var c = minC; c <= maxC; c++) row.append(map.getOrDefault(Grid.offset(r, c), '#'));
|
||||||
gridv2[i] = row.toString();
|
gridv2[i] = row.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5) words output with cropped coordinates
|
// 5) words output with cropped coordinates
|
||||||
int MIN_R = minR, MIN_C = minC;
|
int MIN_R = minR, MIN_C = minC;
|
||||||
var wordsOut = placed.stream().map(p -> new WordOut(
|
var wordsOut = Arrays.stream(placed).map(p -> new WordOut(
|
||||||
p.lemma,
|
p.lemma,
|
||||||
p.startRow() - MIN_R,
|
p.startRow() - MIN_R,
|
||||||
p.startCol() - MIN_C,
|
p.startCol() - MIN_C,
|
||||||
|
|||||||
@@ -402,20 +402,19 @@ public class Main {
|
|||||||
}
|
}
|
||||||
static Clues generateNewClues(Rng rng, Opts opts) {
|
static Clues generateNewClues(Rng rng, Opts opts) {
|
||||||
var masker = new Masker(rng, new int[STACK_SIZE], Masker.Clues.createEmpty());
|
var masker = new Masker(rng, new int[STACK_SIZE], Masker.Clues.createEmpty());
|
||||||
var mask = masker.generateMask(opts.clueSize, opts.pop, opts.gens, opts.offspring);
|
return masker.generateMask(opts.clueSize, opts.pop, opts.gens, opts.offspring);
|
||||||
return mask;
|
|
||||||
}
|
}
|
||||||
static PuzzleResult _attempt(Rng rng, Dict dict, Opts opts) {
|
static PuzzleResult _attempt(Rng rng, Dict dict, Opts opts) {
|
||||||
long t0 = System.currentTimeMillis();
|
val multiThreaded = Thread.currentThread().getName().contains("pool");
|
||||||
|
long t0 = System.currentTimeMillis();
|
||||||
TOTAL_ATTEMPTS.incrementAndGet();
|
TOTAL_ATTEMPTS.incrementAndGet();
|
||||||
val mask = generateNewClues(rng, opts);
|
val mask = generateNewClues(rng, opts);
|
||||||
//val mask = generateClues();
|
//val mask = generateClues();
|
||||||
if (mask == null) return null;
|
if (mask == null) return null;
|
||||||
val multiThreaded = Thread.currentThread().getName().contains("pool");
|
|
||||||
var slots = Masker.extractSlots(mask, dict.index());
|
val slotInfo = Masker.slots(mask, dict.index());
|
||||||
val slotInfo = Masker.scoreSlots(slots);
|
var grid = mask.toGrid();
|
||||||
var grid = mask.toGrid();
|
var filled = fillMask(rng, slotInfo, grid, (!Main.VERBOSE || multiThreaded));
|
||||||
var filled = fillMask(rng, slotInfo, grid, multiThreaded);
|
|
||||||
|
|
||||||
if (!multiThreaded) {
|
if (!multiThreaded) {
|
||||||
System.out.print("\r" + Strings.padRight("", 120) + "\r");
|
System.out.print("\r" + Strings.padRight("", 120) + "\r");
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ public record Masker(Rng rng, int[] stack, Clues cache) {
|
|||||||
grid.forEachSlot((key, lo, hi) -> slots[N[0]++] = Slot.from(key, lo, hi, index[Slot.length(lo, hi)]));
|
grid.forEachSlot((key, lo, hi) -> slots[N[0]++] = Slot.from(key, lo, hi, index[Slot.length(lo, hi)]));
|
||||||
return slots;
|
return slots;
|
||||||
}
|
}
|
||||||
|
public static Slotinfo[] slots(Clues mask, DictEntry[] index) {
|
||||||
|
var slots = Masker.extractSlots(mask, index);
|
||||||
|
return Masker.scoreSlots(slots);
|
||||||
|
}
|
||||||
public static Slotinfo[] scoreSlots(Slot[] slots) {
|
public static Slotinfo[] scoreSlots(Slot[] slots) {
|
||||||
val count = new byte[SwedishGenerator.SIZE];
|
val count = new byte[SwedishGenerator.SIZE];
|
||||||
Slotinfo[] slotInfo = new Slotinfo[slots.length];
|
Slotinfo[] slotInfo = new Slotinfo[slots.length];
|
||||||
|
|||||||
@@ -134,6 +134,10 @@ public record SwedishGenerator() {
|
|||||||
public final byte[] g;
|
public final byte[] g;
|
||||||
public long lo, hi;
|
public long lo, hi;
|
||||||
public static int offset(int r, int c) { return r | (c << 3); }
|
public static int offset(int r, int c) { return r | (c << 3); }
|
||||||
|
|
||||||
|
public Grid copy() {
|
||||||
|
return new Grid(g.clone(), lo, hi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static record DictEntry(long[] words, long[][] posBitsets, int length, int numlong) { }
|
public static record DictEntry(long[] words, long[][] posBitsets, int length, int numlong) { }
|
||||||
@@ -258,8 +262,7 @@ public record SwedishGenerator() {
|
|||||||
|
|
||||||
public static FillResult fillMask(final Rng rng, final Slotinfo[] slots,
|
public static FillResult fillMask(final Rng rng, final Slotinfo[] slots,
|
||||||
final Grid grid,
|
final Grid grid,
|
||||||
final boolean multiThreaded) {
|
final boolean NO_LOG) {
|
||||||
val NO_LOG = (!Main.VERBOSE || multiThreaded);
|
|
||||||
val used = new long[2048];
|
val used = new long[2048];
|
||||||
val bitset = new long[2500];
|
val bitset = new long[2500];
|
||||||
val g = grid.g;
|
val g = grid.g;
|
||||||
@@ -388,12 +391,11 @@ public record SwedishGenerator() {
|
|||||||
var tries = Math.min(MAX_TRIES_PER_SLOT, L);
|
var tries = Math.min(MAX_TRIES_PER_SLOT, L);
|
||||||
|
|
||||||
for (var t = 0; t < tries; t++) {
|
for (var t = 0; t < tries; t++) {
|
||||||
var r = rng.nextFloat();
|
//var r = rng.nextFloat();
|
||||||
//int idxInArray = rng.biasedIndexPow3(L - 1);
|
//var idxInArray = (int) (r * r * r * (L - 1));
|
||||||
var arrIndex = (int) (r * r * r * (L - 1));
|
int idxInArray = rng.biasedIndexPow3(L - 1);
|
||||||
var shardIdx = idxs[arrIndex];
|
var w = entry.words[idxs[idxInArray/*(int) (r * r * r * (L - 1))*/]];
|
||||||
var w = entry.words[shardIdx];
|
var lemIdx = Lemma.unpackIndex(w);
|
||||||
var lemIdx = Lemma.unpackIndex(w);
|
|
||||||
if (Bit1029.get(used, lemIdx)) continue;
|
if (Bit1029.get(used, lemIdx)) continue;
|
||||||
low = glo;
|
low = glo;
|
||||||
top = ghi;
|
top = ghi;
|
||||||
@@ -419,10 +421,9 @@ public record SwedishGenerator() {
|
|||||||
|
|
||||||
var tries = Math.min(MAX_TRIES_PER_SLOT, N);
|
var tries = Math.min(MAX_TRIES_PER_SLOT, N);
|
||||||
for (var t = 0; t < tries; t++) {
|
for (var t = 0; t < tries; t++) {
|
||||||
double r = rng.nextFloat();
|
// double r = rng.nextFloat();
|
||||||
var shardIdx = (int) (r * r * r * (N - 1));
|
var w = entry.words[rng.biasedIndexPow3(N - 1)/*(int) (r * r * r * (N - 1))*/];
|
||||||
var w = entry.words[shardIdx];
|
var lemIdx = Lemma.unpackIndex(w);
|
||||||
var lemIdx = Lemma.unpackIndex(w);
|
|
||||||
if (Bit1029.get(used, lemIdx)) continue;
|
if (Bit1029.get(used, lemIdx)) continue;
|
||||||
low = glo;
|
low = glo;
|
||||||
top = ghi;
|
top = ghi;
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ public class MainTest {
|
|||||||
var filled = fillMask(rng, slotInfo, grid, false);
|
var filled = fillMask(rng, slotInfo, grid, false);
|
||||||
Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)");
|
Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)");
|
||||||
Assertions.assertEquals(17, Slotinfo.wordCount(0, slotInfo), "Number of assigned words changed");
|
Assertions.assertEquals(17, Slotinfo.wordCount(0, slotInfo), "Number of assigned words changed");
|
||||||
Assertions.assertEquals("POENIGE", Lemma.asWord(slotInfo[0].assign().w));
|
Assertions.assertEquals("VREEMDS", Lemma.asWord(slotInfo[0].assign().w));
|
||||||
Assertions.assertEquals(-1L, grid.lo);
|
Assertions.assertEquals(-1L, grid.lo);
|
||||||
Assertions.assertEquals(255L, grid.hi);
|
Assertions.assertEquals(255L, grid.hi);
|
||||||
var g = new Gridded(grid);
|
var g = new Gridded(grid);
|
||||||
|
|||||||
Reference in New Issue
Block a user