Gather data
This commit is contained in:
@@ -137,7 +137,6 @@ public class Main {
|
||||
System.out.printf(Locale.ROOT, " %-14s: %s%n", "wordsPath", o.wordsPath);
|
||||
System.out.printf(Locale.ROOT, " %-14s: %.2f%n", "minSimplicity", o.minSimplicity);
|
||||
System.out.printf(Locale.ROOT, " %-14s: %d%n", "threads", o.threads);
|
||||
System.out.printf(Locale.ROOT, " %-14s: %d%n", "maxTries", o.tries);
|
||||
}
|
||||
|
||||
private static String fmtPoint(int r, int c) { return String.format(Locale.ROOT, "(%d,%d)", r, c); }
|
||||
@@ -181,8 +180,7 @@ public class Main {
|
||||
|
||||
Defaults:
|
||||
--pop 18
|
||||
--gens 600
|
||||
--tries = threads
|
||||
--gens 500
|
||||
--words nl_score_hints.csv
|
||||
--min-simplicity 0 (no limit)
|
||||
--threads %d
|
||||
@@ -245,33 +243,62 @@ public class Main {
|
||||
|
||||
section("Search");
|
||||
|
||||
var deadline = System.currentTimeMillis() + 40_000;
|
||||
var fillTimeout = 20_000;
|
||||
|
||||
if (opts.threads > 1) {
|
||||
info("mode : multi-threaded (" + opts.threads + ")");
|
||||
var executor = Executors.newFixedThreadPool(opts.threads);
|
||||
var executor = Executors.newFixedThreadPool(opts.threads);
|
||||
var completionService = new ExecutorCompletionService<PuzzleResult>(executor);
|
||||
int submitted = 0;
|
||||
|
||||
try {
|
||||
var tasks = new ArrayList<Callable<PuzzleResult>>();
|
||||
for (var i = 1; i <= opts.tries; i++) {
|
||||
final var attempt = i;
|
||||
tasks.add(() -> {
|
||||
// Keep at least some tasks in flight
|
||||
for (int i = 0; i < opts.threads; i++) {
|
||||
final int attempt = ++submitted;
|
||||
completionService.submit(() -> {
|
||||
var threadRng = new Rng(opts.seed + attempt);
|
||||
var mask = generateMask(threadRng, dict.lenCounts(), opts.pop, opts.gens, false);
|
||||
var filled = fillMask(threadRng, mask, dict.index(), dict.words(), 200, 30000, false);
|
||||
var filled = fillMask(threadRng, mask, dict.index(), dict.words(), 200, fillTimeout, false);
|
||||
|
||||
if (filled.ok && (opts.minSimplicity <= 0 || filled.simplicity >= opts.minSimplicity)) {
|
||||
info("status : SOLVED");
|
||||
info("foundAtTry : " + attempt);
|
||||
return new PuzzleResult(dict, mask, filled);
|
||||
}
|
||||
throw new RuntimeException("No solution in try " + attempt);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
return executor.invokeAny(tasks);
|
||||
|
||||
while (System.currentTimeMillis() < deadline) {
|
||||
var future = completionService.poll(deadline - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
|
||||
if (future == null) break;
|
||||
|
||||
var result = future.get();
|
||||
if (result != null) {
|
||||
info("status : SOLVED");
|
||||
return result;
|
||||
}
|
||||
|
||||
// Submit another task if we still have time
|
||||
if (System.currentTimeMillis() < deadline) {
|
||||
final int attempt = ++submitted;
|
||||
completionService.submit(() -> {
|
||||
var threadRng = new Rng(opts.seed + attempt);
|
||||
var mask = generateMask(threadRng, dict.lenCounts(), opts.pop, opts.gens, false);
|
||||
var filled = fillMask(threadRng, mask, dict.index(), dict.words(), 200, fillTimeout, false);
|
||||
|
||||
if (filled.ok && (opts.minSimplicity <= 0 || filled.simplicity >= opts.minSimplicity)) {
|
||||
return new PuzzleResult(dict, mask, filled);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
warn("status : UNSOLVED (timeout)");
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
warn("status : INTERRUPTED");
|
||||
} catch (ExecutionException e) {
|
||||
// all failed
|
||||
warn("status : UNSOLVED");
|
||||
warn("status : ERROR (" + e.getMessage() + ")");
|
||||
} finally {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
@@ -279,13 +306,15 @@ public class Main {
|
||||
|
||||
} else {
|
||||
info("mode : single-threaded");
|
||||
var rng = new Rng(opts.seed);
|
||||
var rng = new Rng(opts.seed);
|
||||
int attempt = 0;
|
||||
|
||||
for (var attempt = 1; attempt <= opts.tries; attempt++) {
|
||||
info("try : " + attempt + "/" + opts.tries);
|
||||
while (System.currentTimeMillis() < deadline) {
|
||||
attempt++;
|
||||
info("try : " + attempt + " (remaining: " + (deadline - System.currentTimeMillis()) / 1000 + "s)");
|
||||
|
||||
var mask = generateMask(rng, dict.lenCounts(), opts.pop, opts.gens, true);
|
||||
var filled = fillMask(rng, mask, dict.index(), dict.words(), 200, 30000, true);
|
||||
var filled = fillMask(rng, mask, dict.index(), dict.words(), 200, fillTimeout, true);
|
||||
|
||||
if (filled.ok && (opts.minSimplicity <= 0 || filled.simplicity >= opts.minSimplicity)) {
|
||||
info("status : SOLVED");
|
||||
@@ -301,7 +330,7 @@ public class Main {
|
||||
}
|
||||
}
|
||||
|
||||
info("status : UNSOLVED");
|
||||
info("status : UNSOLVED (timeout)");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -397,7 +426,7 @@ public class Main {
|
||||
|
||||
info("Rebuilding index from: " + PUZZLE_DIR);
|
||||
|
||||
List<String> records = new ArrayList<>();
|
||||
var records = new ArrayList<String>();
|
||||
try (var stream = Files.list(PUZZLE_DIR)) {
|
||||
stream.filter(p -> p.toString().endsWith(".json") && !p.getFileName().toString().equals("index.json"))
|
||||
.sorted(Comparator.comparing(Path::getFileName).reversed())
|
||||
|
||||
Reference in New Issue
Block a user