From 2e9c90dbca5f23dcffde518d77f60f1a4fc41ee3 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 18:47:49 +0200 Subject: [PATCH] add move guesser interface --- src/lib/{guesser.ts => guesser/base.ts} | 34 +++++++++++++++++-------- src/lib/guesser/guesser.ts | 6 +++++ src/lib/lib.ts | 2 +- src/lib/runner.ts | 4 +-- src/manual_proxy.ts | 4 +-- src/simulation.ts | 4 +-- 6 files changed, 37 insertions(+), 17 deletions(-) rename src/lib/{guesser.ts => guesser/base.ts} (80%) create mode 100644 src/lib/guesser/guesser.ts diff --git a/src/lib/guesser.ts b/src/lib/guesser/base.ts similarity index 80% rename from src/lib/guesser.ts rename to src/lib/guesser/base.ts index 841dc88..c03bbdc 100644 --- a/src/lib/guesser.ts +++ b/src/lib/guesser/base.ts @@ -1,12 +1,9 @@ import { assertExists } from "https://deno.land/std@0.224.0/assert/assert_exists.ts"; -import { Awaitable, enumerate, range } from "./utils.ts"; -import { Dict } from "./dict.ts"; -import { GuessResult } from "./game/game.ts"; - -export interface Guessing { - guess(try_: (guess: string, known: string) => Awaitable): Promise; -} +import { Awaitable, enumerate, range, zip } from "../utils.ts"; +import { Dict } from "../dict.ts"; +import { GuessResult } from "../game/game.ts"; +import { Guessing } from "./guesser.ts"; type Knowledge = { letter: string; @@ -15,7 +12,7 @@ type Knowledge = { not_at: Set; }; -export class Guesser implements Guessing { +export class BaseGuesser implements Guessing { length; dict; informations; @@ -33,6 +30,9 @@ export class Guesser implements Guessing { const res = this.expected_result(); if (res.completed) return await try_(res.result, res.result); + const possibilities = [...this.possible_words()]; + if (possibilities.length === 1) return await try_(possibilities[0], res.result); + const words = [...this.dict.words.values()]; const scored = words.map((word) => [this.info_score_for(word), word] as const); const best_score = scored.reduce((acc, [next]) => Math.max(acc, next), 0); @@ -93,8 +93,9 @@ export class Guesser implements Guessing { if (information.exists === false) continue; if (information.at.has(index)) continue; if (information.not_at.has(index)) continue; - if (information.exists === "unknown") total += this.length; - if (information.exists === true) total += this.length * this.length; + + if (information.exists === "unknown") total += this.length ** 1; + if (information.exists === true) total += this.length ** 2; } const different_letters = new Set([...word]); total += different_letters.size; @@ -110,6 +111,19 @@ export class Guesser implements Guessing { const completed = !result.includes("."); return { completed, result }; } + + *possible_words() { + for (const word of this.dict.words.values()) if (this.matches_expected(word)) yield word; + } + + matches_expected(word: string) { + const expected = this.expected_result(); + for (const [act, exp] of zip(word, expected.result)) { + if (exp === ".") continue; + if (act !== exp) return false; + } + return true; + } } function pick_random_common_word(bests: string[]) { diff --git a/src/lib/guesser/guesser.ts b/src/lib/guesser/guesser.ts new file mode 100644 index 0000000..5fba2ac --- /dev/null +++ b/src/lib/guesser/guesser.ts @@ -0,0 +1,6 @@ +import { GuessResult } from "../game/game.ts"; +import { Awaitable } from "../utils.ts"; + +export interface Guessing { + guess(try_: (guess: string, known: string) => Awaitable): Promise; +} diff --git a/src/lib/lib.ts b/src/lib/lib.ts index bd84cb1..cc2c7a7 100644 --- a/src/lib/lib.ts +++ b/src/lib/lib.ts @@ -1,5 +1,5 @@ export { Dict } from "./dict.ts"; -export { Guesser } from "./guesser.ts"; +export { BaseGuesser } from "./guesser/base.ts"; export { Simulator } from "./game/simulator.ts"; export { ManualProxy } from "./game/proxy.ts"; export { Runner } from "./runner.ts"; diff --git a/src/lib/runner.ts b/src/lib/runner.ts index cf01559..8d20cad 100644 --- a/src/lib/runner.ts +++ b/src/lib/runner.ts @@ -1,6 +1,6 @@ import { assertExists } from "https://deno.land/std@0.224.0/assert/assert_exists.ts"; -import { Guessing } from "./guesser.ts"; +import { Guessing } from "./guesser/guesser.ts"; import { Gaming, GuessResult } from "./game/game.ts"; import { last, wait } from "./utils.ts"; @@ -55,7 +55,7 @@ interface LoggingStrategy { } export class VerboseLogging implements LoggingStrategy { - on_start(length: number) {} + on_start(_length: number) {} on_guess(known: string, guess: string, result: GuessResult): void { console.log(" Knows:", known); diff --git a/src/manual_proxy.ts b/src/manual_proxy.ts index 4ffaf87..8617604 100755 --- a/src/manual_proxy.ts +++ b/src/manual_proxy.ts @@ -2,7 +2,7 @@ import { Command } from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts"; -import { Dict, Guesser, ManualProxy, Runner } from "./lib/lib.ts"; +import { BaseGuesser, Dict, ManualProxy, Runner } from "./lib/lib.ts"; import { initialize_prompt } from "./lib/prompt.ts"; import { VerboseLogging } from "./lib/runner.ts"; @@ -24,7 +24,7 @@ async function main() { if (args.options.file !== undefined) dict = await Dict.from_text_file(args.options.file, init.length); for (const [index, letter] of init.constraints) dict.constraint(index, letter); - const guesser = new Guesser(dict); + const guesser = new BaseGuesser(dict); const game = new ManualProxy(init.length); const runner = new Runner(game, guesser, new VerboseLogging()); diff --git a/src/simulation.ts b/src/simulation.ts index fa3a695..69e59c9 100755 --- a/src/simulation.ts +++ b/src/simulation.ts @@ -2,7 +2,7 @@ import { Command } from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts"; -import { Dict, Guesser, Runner, Simulator } from "./lib/lib.ts"; +import { BaseGuesser, Dict, Runner, Simulator } from "./lib/lib.ts"; import { TableLogging } from "./lib/runner.ts"; import { francais } from "../data/data.ts"; @@ -28,7 +28,7 @@ async function main() { let dict = Dict.from_lines(francais, args.options.length); if (args.options.file !== undefined) dict = await Dict.from_text_file(args.options.file, args.options.length); - const guesser = new Guesser(dict); + const guesser = new BaseGuesser(dict); const game = Simulator.from_dict_rand(dict); console.log("Target is", game.word); console.log();