From e5b23bfd165461be012c8a64f37bcbb3205a9447 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 16:38:45 +0200 Subject: [PATCH 01/10] fix incorrect prunning of composite words --- src/lib/dict.ts | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/lib/dict.ts b/src/lib/dict.ts index 8e08a95..8bc4c5d 100644 --- a/src/lib/dict.ts +++ b/src/lib/dict.ts @@ -17,8 +17,8 @@ export class Dict { for (const word of content.split("\n")) { const word_ = word.trim().toLowerCase(); if (word_.length !== length) continue; - for (const forbidden of [" ", "-", "."]) if (word_.includes(forbidden)) continue; - words.add(remove_accent(word_)); + if (contains_any(word_, [" ", "-", "."])) continue; + words.add(remove_accents(word_)); } return new Dict(words, length); } @@ -27,3 +27,22 @@ export class Dict { return `Dict { ${this.words.size} words }`; } } + +export function contains_any(text: string, words: string[]) { + for (const word of words) if (text.includes(word)) return true; + return false; +} + +export function remove_accents(text: string) { + const accents = [ + ...[["à", "a"], ["â", "a"], ["ä", "a"]], + ...[["ç", "c"]], + ...[["é", "e"], ["è", "e"], ["ê", "e"], ["ë", "e"]], + ...[["î", "i"], ["ï", "i"]], + ...[["ô", "o"], ["ö", "o"]], + ...[["û", "u"]], + ]; + let result = text; + for (const [accent, alternative] of accents) result = result.replaceAll(accent, alternative); + return result; +} From dc32188c91c35431942f1eeae34447c41e919cc9 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 16:39:15 +0200 Subject: [PATCH 02/10] remove old mains --- main.ts | 245 ---------------------------------------------------- src/main.ts | 40 --------- 2 files changed, 285 deletions(-) delete mode 100755 main.ts delete mode 100755 src/main.ts diff --git a/main.ts b/main.ts deleted file mode 100755 index 3e206ee..0000000 --- a/main.ts +++ /dev/null @@ -1,245 +0,0 @@ -#!/usr/bin/env -S deno run --allow-read - -import { assertExists } from "https://deno.land/std@0.224.0/assert/assert_exists.ts"; - -async function main() { - const length = 6; - const dict = await Dict.from_file("./data/liste_francais.txt", length); - console.log(dict); - const history = new History(dict); - const game = Game.from_dict_rand(dict); - console.log("Target is", game.word); - let index = 0; - while (true) { - index += 1; - const found = await history.next_guess((guess) => { - console.log("Guessing", guess); - const result = game.try_guess(guess); - console.log(format_result(result)); - return result; - }); - if (found !== undefined) { - console.log("Found", found, "in", index); - break; - } - await wait(500); - } -} - -type GuessResult = { kind: "success" } | { kind: "failure"; informations: Info[] }; - -function format_result(result: GuessResult) { - if (result.kind === "success") return `success`; - let line = "failure: "; - for (const info of result.informations) line += info.kind === "abscent" ? "-" : info.kind === "somewhere" ? "+" : "#"; - return line; -} - -class Dict { - words; - letters; - length; - - constructor(words: Set, length: number) { - this.words = words; - this.length = length; - this.letters = new Set([...words.values()].map((w) => w.split("")).flat()); - } - - static async from_file(path: string, length: number) { - const words = new Set(); - const content = await Deno.readTextFile(path); - for (const word of content.split("\n")) { - const word_ = word.trim().toLowerCase(); - if (word_.length !== length) continue; - for (const forbidden of [" ", "-", "."]) if (word_.includes(forbidden)) continue; - words.add(remove_accent(word_)); - } - return new Dict(words, length); - } - - [Symbol.for("Deno.customInspect")]() { - return `Dict { ${this.words.size} words }`; - } -} - -type Knowledge = { - letter: string; - at: Set; - not_at: Set; -}; - -class History { - length; - dict; - informations; - - constructor(dict: Dict) { - this.length = dict.length; - this.dict = dict; - this.informations = new Map(); - for (const letter of dict.letters.values()) { - this.informations.set(letter, { letter, at: new Set(), not_at: new Set() }); - } - } - - async next_guess(operation: (guess: string) => GuessResult | Promise) { - const res = this.expected_result(); - console.log("knows: ", res.known); - if (res.completed) return operation(res.known); - - const words = [...this.dict.words.values()]; - const scored = words.map((word) => [this.info_for(word), word] as const); - const sorted = scored.toSorted(([sa], [sb]) => sb - sa); - const [_score, guess] = sorted[0]; - - const result = await operation(guess); - if (result.kind === "success") return guess; - - for (const [letter, new_info] of zip(guess, result.informations)) { - // - } - } - - learn_letter_at(letter: string, at: number) { - const letter_info = this.informations.get(letter); - assertExists(letter_info); - letter_info.at.add(at); - for (const l of this.informations.keys()) { - if (letter === l) continue; - this.learn_letter_not_at(l, at); - } - } - - learn_letter_not_at(letter: string, at: number) { - const letter_info = this.informations.get(letter); - assertExists(letter_info); - letter_info.not_at.add(at); - } - - info_for(word: string) { - let total = 0; - for (const [index, letter] of enumerate(word)) { - const information = this.informations.get(letter); - if (information === undefined) { - total += 1; - continue; - } - - if () - - if (information.kind === "abscent") { - continue; - } - - if (information.kind === "present") { - const known_pos = information.not_at.has(index); - if (!known_pos) total += this.length; // note : not 1 to priorize locating known letters. - continue; - } - } - return total; - } - - expected_result() { - const known_arr = [...range(0, this.length)].map(() => null as string | null); - for (const [letter, info] of this.informations.entries()) { - if (info.kind !== "known") continue; - for (const i of info.at.values()) known_arr[i] = letter; - } - - const known = known_arr.map((l) => l === null ? "." : l).join(""); - if (known.includes(".")) return { completed: false as const, known }; - const guess = known_arr as string[]; - return { completed: true as const, known, guess }; - } -} - -type Info = { kind: "abscent" } | { kind: "somewhere" } | { kind: "there" }; - -function remove_accent(text: string) { - const accents = [ - ["à", "a"], - ["â", "a"], - ["ä", "a"], - ["é", "e"], - ["è", "e"], - ["ê", "e"], - ["ë", "e"], - ["î", "i"], - ["ï", "i"], - ["ô", "o"], - ["ö", "o"], - ["û", "u"], - ]; - let result = text; - for (const [accent, alternative] of accents) result = result.replaceAll(accent, alternative); - return result; -} - -function* enumerate(iterator: Iterable) { - let index = 0; - for (const item of iterator) yield [index++, item] as const; -} - -function* zip(iterable_a: Iterable, iterable_b: Iterable) { - const iter_a = iterable_a[Symbol.iterator](); - const iter_b = iterable_b[Symbol.iterator](); - while (true) { - const next_a = iter_a.next().value; - const next_b = iter_b.next().value; - if (next_a === undefined) return; - if (next_b === undefined) return; - yield [next_a as A, next_b as B] as const; - } -} - -class Game { - word; - - constructor(word: string) { - this.word = word; - } - - static from_dict_rand(dict: Dict) { - const index = Math.floor(Math.random() * dict.words.size); - const word = [...dict.words.values()][index]; - return new Game(word); - } - - try_guess(guess: string): GuessResult { - if (guess === this.word) return { kind: "success" }; - const rest_actual = [...this.word].map((letter) => letter as (string | null)); - const rest_guess = [...guess].map((letter) => letter as (string | null)); - const info = [...range(0, this.word.length)].map(() => null) as (Info | null)[]; - - for (const [index, [guessed, actual]] of enumerate(zip(rest_guess, rest_actual))) { - if (guessed !== actual) continue; - rest_actual[index] = null; - rest_guess[index] = null; - info[index] = { kind: "known", at: new Set([index]) }; - } - - for (const [index, guessed] of enumerate(rest_guess)) { - if (guessed === null) continue; - if (!rest_actual.includes(guessed)) continue; - info[index] = { kind: "present", not_at: new Set([index]) }; - rest_guess[index] = null; - // note : removes only one. - rest_actual[rest_actual.indexOf(guessed)] = null; - } - - const informations = info.map((i) => i != undefined ? i : ({ kind: "abscent" }) as Info); - return { kind: "failure", informations }; - } -} - -function* range(from: number, to: number) { - while (from < to) yield from++; -} - -async function wait(ms: number) { - await new Promise((resolver) => setTimeout(resolver, ms)); -} - -if (import.meta.main) await main(); diff --git a/src/main.ts b/src/main.ts deleted file mode 100755 index 8990a82..0000000 --- a/src/main.ts +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env -S deno run --allow-read - -import { GuessResult } from "./lib/game/game.ts"; -import { Dict, Gueser, Simulator } from "./lib/lib.ts"; -import { wait } from "./lib/utils.ts"; - -async function main() { - const length = 6; - const dict = await Dict.from_file("./data/liste_francais.txt", length); - console.log(dict); - const guesser = new Gueser(dict); - const game = Simulator.from_dict_rand(dict); - console.log("Target is", game.word); - let index = 0; - while (true) { - console.log(); - index += 1; - const found = await guesser.next_guess((guess, known) => { - console.log("knows: ", known); - console.log("Guessing:", guess); - const result = game.try_guess(guess); - console.log(format_result(result)); - return result; - }); - if (found !== undefined) { - console.log("Found", found, "in", index); - break; - } - await wait(500); - } -} - -function format_result(result: GuessResult) { - if (result.kind === "success") return `success`; - let line = "failure: "; - for (const info of result.informations) line += info.kind === "abscent" ? "-" : info.kind === "somewhere" ? "+" : "#"; - return line; -} - -if (import.meta.main) await main(); From 72c7373343096db1517eda06cff4ed4caf786f7d Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 16:39:42 +0200 Subject: [PATCH 03/10] clean dead code --- src/lib/dict.ts | 2 -- src/lib/utils.ts | 25 ++++++------------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/lib/dict.ts b/src/lib/dict.ts index 8bc4c5d..539e0c4 100644 --- a/src/lib/dict.ts +++ b/src/lib/dict.ts @@ -1,5 +1,3 @@ -import { remove_accent } from "./utils.ts"; - export class Dict { words; letters; diff --git a/src/lib/utils.ts b/src/lib/utils.ts index cf2ebfd..be4f837 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -23,23 +23,10 @@ export async function wait(ms: number) { await new Promise((resolver) => setTimeout(resolver, ms)); } -export function remove_accent(text: string) { - const accents = [ - ["à", "a"], - ["â", "a"], - ["ä", "a"], - ["ç", "c"], - ["é", "e"], - ["è", "e"], - ["ê", "e"], - ["ë", "e"], - ["î", "i"], - ["ï", "i"], - ["ô", "o"], - ["ö", "o"], - ["û", "u"], - ]; - let result = text; - for (const [accent, alternative] of accents) result = result.replaceAll(accent, alternative); - return result; +export type Awaitable = T | Promise; + +export function last(iterable: Iterable) { + let last = undefined as T | undefined; + for (const item of iterable) last = item; + return last; } From aa98d8805bf88265cf1298ef0938676aecc6e86e Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 16:40:11 +0200 Subject: [PATCH 04/10] add abstracted guesser interface --- src/lib/guesser.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/lib/guesser.ts b/src/lib/guesser.ts index 6ba23d9..c0afca6 100644 --- a/src/lib/guesser.ts +++ b/src/lib/guesser.ts @@ -1,9 +1,13 @@ import { assertExists } from "https://deno.land/std@0.224.0/assert/assert_exists.ts"; -import { enumerate, range } from "./utils.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; +} + type Knowledge = { letter: string; at: Set; @@ -11,7 +15,7 @@ type Knowledge = { not_at: Set; }; -export class Gueser { +export class Guesser implements Guessing { length; dict; informations; @@ -25,9 +29,9 @@ export class Gueser { } } - async next_guess(operation: (guess: string, known: string) => GuessResult | Promise) { + async guess(try_: (guess: string, known: string) => Awaitable) { const res = this.expected_result(); - if (res.completed) return operation(res.result, res.result); + if (res.completed) return await try_(res.result, res.result); const words = [...this.dict.words.values()]; const scored = words.map((word) => [this.info_score_for(word), word] as const); @@ -35,8 +39,8 @@ export class Gueser { const bests = scored.filter(([s]) => s === best_score).map(([_, word]) => word); const guess = pick_random_common_word(bests); - const result = await operation(guess, res.result); - if (result.kind === "success") return guess; + const result = await try_(guess, res.result); + if (result.kind === "success") return result; for (const [index, info] of enumerate(result.informations)) { const letter = guess[index]; if (info.kind === "there") this.learn_letter_at(letter, index); @@ -46,6 +50,7 @@ export class Gueser { this.learn_letter_not_at(letter, index); } } + return null; } learn_does_not_exist(letter: string) { From 5d2ca505d7caa2c0def0268d84dd8051a762242e Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 16:40:38 +0200 Subject: [PATCH 05/10] add game interface for genericity over simulation / actual play --- src/lib/game/game.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib/game/game.ts b/src/lib/game/game.ts index be79b9d..e6acbe4 100644 --- a/src/lib/game/game.ts +++ b/src/lib/game/game.ts @@ -1,3 +1,10 @@ +import { Awaitable } from "../utils.ts"; + export type Info = { kind: "abscent" } | { kind: "somewhere" } | { kind: "there" }; export type GuessResult = { kind: "success" } | { kind: "failure"; informations: Info[] }; + +export interface Gaming { + length(): number; + guess(guess: string, known: string): Awaitable; +} From 1156752e0acb0420aac55aea9bfcdf55db908c96 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 16:40:51 +0200 Subject: [PATCH 06/10] add TUSMO simulator --- src/lib/game/simulator.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/lib/game/simulator.ts b/src/lib/game/simulator.ts index b71a82d..7b4d247 100644 --- a/src/lib/game/simulator.ts +++ b/src/lib/game/simulator.ts @@ -1,8 +1,8 @@ import { Dict } from "../dict.ts"; import { enumerate, range, zip } from "../utils.ts"; -import { GuessResult, Info } from "./game.ts"; +import { Gaming, GuessResult, Info } from "./game.ts"; -export class Simulator { +export class Simulator implements Gaming { word; constructor(word: string) { @@ -15,10 +15,10 @@ export class Simulator { return new Simulator(word); } - try_guess(guess: string): GuessResult { - if (guess === this.word) return { kind: "success" }; + guess(guess_: string, _known: string): GuessResult { + if (guess_ === this.word) return { kind: "success" }; const rest_actual = [...this.word].map((letter) => letter as (string | null)); - const rest_guess = [...guess].map((letter) => letter as (string | null)); + const rest_guess = [...guess_].map((letter) => letter as (string | null)); const info = [...range(0, this.word.length)].map(() => null) as (Info | null)[]; for (const [index, [guessed, actual]] of enumerate(zip(rest_guess, rest_actual))) { @@ -40,4 +40,8 @@ export class Simulator { const informations = info.map((i) => i != undefined ? i : ({ kind: "abscent" }) as Info); return { kind: "failure", informations }; } + + length(): number { + return this.word.length; + } } From ba87099e0e47b8045c57c689ecc36c384cc0b18e Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 16:41:06 +0200 Subject: [PATCH 07/10] add runner wrapping game execution --- src/lib/runner.ts | 91 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/lib/runner.ts diff --git a/src/lib/runner.ts b/src/lib/runner.ts new file mode 100644 index 0000000..cf01559 --- /dev/null +++ b/src/lib/runner.ts @@ -0,0 +1,91 @@ +import { assertExists } from "https://deno.land/std@0.224.0/assert/assert_exists.ts"; + +import { Guessing } from "./guesser.ts"; +import { Gaming, GuessResult } from "./game/game.ts"; +import { last, wait } from "./utils.ts"; + +export class Runner { + game; + guesser; + delay_ms; + turns; + logging; + + constructor(game: Ga, guesser: Gu, logging: LoggingStrategy, delay_ms = 0) { + this.game = game; + this.guesser = guesser; + this.delay_ms = delay_ms; + this.turns = [] as Turn[]; + this.logging = logging; + } + + async play_all() { + this.logging.on_start(this.game.length()); + while (true) { + const result = await this.guesser.guess(async (guess, known) => { + const result = await this.game.guess(guess, known); + this.turns.push({ guess, result }); + this.logging.on_guess(known, guess, result); + return result; + }); + if (result !== null) break; + await wait(this.delay_ms); + } + this.logging.on_finish(this.turns); + } +} + +type Turn = { guess: string; result: GuessResult }; + +function format_result(result: GuessResult) { + if (result.kind === "success") return "success"; + let line = ""; + for (const info of result.informations) { + if (info.kind === "abscent") line += "."; + if (info.kind === "somewhere") line += "*"; + if (info.kind === "there") line += "#"; + } + return line; +} + +interface LoggingStrategy { + on_start(length: number): void; + on_guess(known: string, guess: string, result: GuessResult): void; + on_finish(turns: Turn[]): void; +} + +export class VerboseLogging implements LoggingStrategy { + on_start(length: number) {} + + on_guess(known: string, guess: string, result: GuessResult): void { + console.log(" Knows:", known); + console.log("Guessing:", guess); + console.log(" Got:", format_result(result)); + console.log(); + } + + on_finish(turns: Turn[]): void { + const last_ = last(turns); + assertExists(last_); + console.log("Stopped on", last_.guess, "."); + console.log("With", last_.result.kind, "."); + console.log("In", turns.length, "steps"); + } +} + +export class TableLogging implements LoggingStrategy { + on_start(length: number): void { + const pad = (title: string) => title.padEnd(length); + console.log(`${pad("known")}\t${pad("guess")}\t${pad("result")}`); + console.log(); + } + on_guess(known: string, guess: string, result: GuessResult): void { + console.log(`${known}\t${guess}\t${format_result(result)}`); + } + on_finish(turns: Turn[]): void { + const last_ = last(turns); + assertExists(last_); + console.log(); + console.log(last_.result.kind, "in", turns.length, "steps"); + } +} From bbc4e53a9ac53d542a053f426bdf6eee78a3dd5f Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 16:41:13 +0200 Subject: [PATCH 08/10] fix imports --- src/lib/lib.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/lib.ts b/src/lib/lib.ts index e5f3473..3ad2e8e 100644 --- a/src/lib/lib.ts +++ b/src/lib/lib.ts @@ -1,3 +1,4 @@ export { Dict } from "./dict.ts"; -export { Gueser } from "./guesser.ts"; +export { Guesser } from "./guesser.ts"; export { Simulator } from "./game/simulator.ts"; +export { Runner } from "./runner.ts"; From 43c835d1eb374f908239d6fdeb469552046d8cde Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 16:41:29 +0200 Subject: [PATCH 09/10] add entrypoint for simulations --- src/simulation.ts | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100755 src/simulation.ts diff --git a/src/simulation.ts b/src/simulation.ts new file mode 100755 index 0000000..d33245b --- /dev/null +++ b/src/simulation.ts @@ -0,0 +1,38 @@ +#!/usr/bin/env -S deno run --allow-read + +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 { TableLogging } from "./lib/runner.ts"; + +async function main() { + const args = await new Command().name("simulation") + .description( + "Program to simulate TUSMO game with guesser controller.", + ) + .option( + "-d, --dictionnary ", + "Sets dictionnary to use words from.", + { default: "./data/liste_francais.txt" }, + ).option( + "-n, --length ", + "Length of the word to use from the dictionnary.", + { default: 6 }, + ).option( + "-w, --wait ", + "Time to wait between guesses, in ms.", + { default: 500 }, + ).parse(Deno.args); + + const dict = await Dict.from_file(args.options.dictionnary, args.options.length); + + const guesser = new Guesser(dict); + const game = Simulator.from_dict_rand(dict); + console.log("Target is", game.word); + console.log(); + + const runner = new Runner(game, guesser, new TableLogging(), args.options.wait); + await runner.play_all(); +} + +if (import.meta.main) await main(); From 241bcd29e311a5934b4c807cb0a1cb80c273f733 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Tue, 30 Apr 2024 16:42:17 +0200 Subject: [PATCH 10/10] add deno dependencies lock --- deno.lock | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 deno.lock diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..a72822d --- /dev/null +++ b/deno.lock @@ -0,0 +1,77 @@ +{ + "version": "3", + "redirects": { + "https://deno.land/x/cliffy/command/mod.ts": "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts" + }, + "remote": { + "https://deno.land/std@0.221.0/assert/assert.ts": "bec068b2fccdd434c138a555b19a2c2393b71dfaada02b7d568a01541e67cdc5", + "https://deno.land/std@0.221.0/assert/assertion_error.ts": "9f689a101ee586c4ce92f52fa7ddd362e86434ffdf1f848e45987dc7689976b8", + "https://deno.land/std@0.221.0/console/_data.json": "cf2cc9d039a192b3adbfe64627167c7e6212704c888c25c769fc8f1709e1e1b8", + "https://deno.land/std@0.221.0/console/_run_length.ts": "7da8642a0f4f41ac27c0adb1364e18886be856c1d08c5cce6c6b5c00543c8722", + "https://deno.land/std@0.221.0/console/unicode_width.ts": "d92f085c0ab9c7ab171e4e7862dfd9d3a36ffd369939be5d3e1140ec58bc820f", + "https://deno.land/std@0.221.0/fmt/colors.ts": "d239d84620b921ea520125d778947881f62c50e78deef2657073840b8af9559a", + "https://deno.land/std@0.221.0/text/closest_string.ts": "8a91ee8b6d69ff96addcb7c251dad53b476ac8be9c756a0ef786abe9e13a93a5", + "https://deno.land/std@0.221.0/text/levenshtein_distance.ts": "24be5cc88326bbba83ca7c1ea89259af0050cffda2817ff3a6d240ad6495eae2", + "https://deno.land/std@0.224.0/assert/assert_exists.ts": "43420cf7f956748ae6ed1230646567b3593cb7a36c5a5327269279c870c5ddfd", + "https://deno.land/std@0.224.0/assert/assertion_error.ts": "ba8752bd27ebc51f723702fac2f54d3e94447598f54264a6653d6413738a8917", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/_argument_types.ts": "ab269dacea2030f865a07c2a1e953ec437a64419a05bad1f1ddaab3f99752ead", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/_errors.ts": "d78e1b4d69d84b8b476b5f3c0b028e3906d48f21b8f1ca1d36d5abe9ccfe48bc", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/_spread.ts": "0cc6eb70a6df97b5d7d26008822d39f3e8a1232ee0a27f395aa19e68de738245", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/_type_utils.ts": "820004a59bc858e355b11f80e5b3ff1be2c87e66f31f53f253610170795602f0", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/_utils.ts": "fa0e88cc4215b18554a7308e8e2ae3a12be0fb91c54d1473c54c530dbd4adfcb", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/command.ts": "83cbece11c1459d5bc5add32c3cad0bf49e92c4ddd3ef00f22f80efdae30994e", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/completions/_bash_completions_generator.ts": "0c6cb1df4d378d22f001155781d97a9c3519fd10c48187a198fef2cc63b0f84a", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/completions/_fish_completions_generator.ts": "8ba4455f7f76a756e05c3db4ce35332b2951af65a2891f2750b530e06880f495", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/completions/_zsh_completions_generator.ts": "9df79fbac17a32b9645d01628c41a2bfd295d7976b87b0ae235f50a9c8975fbc", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/completions/bash.ts": "53fe78994eb2359110dc4fa79235bdd86800a38c1d6b1c4fe673c81756f3a0e2", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/completions/complete.ts": "58df61caa5e6220ff2768636a69337923ad9d4b8c1932aeb27165081c4d07d8b", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/completions/completions_command.ts": "506f97f1c6b0b1c3e9956e5069070028b818942310600d4157f64c9b644d3c49", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/completions/fish.ts": "6f0b44b4067740b2931c9ec8863b6619b1d3410fea0c5a3988525a4c53059197", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/completions/mod.ts": "8dda715ca25f3f66d5ec232b76d7c9a96dd4c64b5029feff91738cc0c9586fb1", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/completions/zsh.ts": "f1263c3946975e090d4aadc8681db811d86b52a8ae680f246e03248025885c21", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/deprecated.ts": "bbe6670f1d645b773d04b725b8b8e7814c862c9f1afba460c4d599ffe9d4983c", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/deps.ts": "a58ea2fa4e2ed9b39bb8dd8c35dd0498c74f05392517ff230a9a4d04c4c766b7", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/help/_help_generator.ts": "98619da83ff25523280a6fdcad89af3f13a6fafefc81b71f8230f3344b5ff2c5", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/help/help_command.ts": "fbbf0c0827dd21d3cec7bcc68c00c20b55f53e2b621032891b9d23ac4191231c", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/help/mod.ts": "8369b292761dcc9ddaf41f2d34bfb06fb6800b69efe80da4fc9752c3b890275b", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts": "4b708df1b97152522bee0e3828f06abbbc1d2250168910e5cf454950d7b7404b", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/type.ts": "f588f5d9635b79100044e62aced4b00e510e75b83801f9b089c40c2d98674de2", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/types.ts": "bc9ff7459b9cc1079eeb95ff101690a51b4b4afa4af5623340076ee361d08dbb", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/types/action_list.ts": "33c98d449617c7a563a535c9ceb3741bde9f6363353fd492f90a74570c611c27", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/types/boolean.ts": "3879ec16092b4b5b1a0acb8675f8c9250c0b8a972e1e4c7adfba8335bd2263ed", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/types/child_command.ts": "f1fca390c7fbfa7a713ca15ef55c2c7656bcbb394d50e8ef54085bdf6dc22559", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/types/command.ts": "325d0382e383b725fd8d0ef34ebaeae082c5b76a1f6f2e843fee5dbb1a4fe3ac", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/types/enum.ts": "8a7cd2898e03089234083bb78c8b1d9b7172254c53c32d4710321638165a48ec", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/types/file.ts": "8618f16ac9015c8589cbd946b3de1988cc4899b90ea251f3325c93c46745140e", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/types/integer.ts": "29864725fd48738579d18123d7ee78fed37515e6dc62146c7544c98a82f1778d", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/types/number.ts": "aeba96e6f470309317a16b308c82e0e4138a830ec79c9877e4622c682012bc1f", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/types/string.ts": "e4dadb08a11795474871c7967beab954593813bb53d9f69ea5f9b734e43dc0e0", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/upgrade/_check_version.ts": "6cfa7dc26bc0dc46381500e8d4b130fb224f4c5456152dada15bd3793edca89b", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/upgrade/mod.ts": "4eff69c489467be17dea27fb95a795396111ee385d170ac0cbcc82f0ea38156c", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/upgrade/provider.ts": "c23253334097dc4b8a147ccdeb3aa44f5a95aa953a6386cb5396f830d95d77a5", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/upgrade/provider/deno_land.ts": "24f8d82e38c51e09be989f30f8ad21f9dd41ac1bb1973b443a13883e8ba06d6d", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/upgrade/provider/github.ts": "99e1b133dd446c6aa79f69e69c46eb8bc1c968dd331c2a7d4064514a317c7b59", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/upgrade/provider/nest_land.ts": "0e07936cea04fa41ac9297f32d87f39152ea873970c54cb5b4934b12fee1885e", + "https://deno.land/x/cliffy@v1.0.0-rc.4/command/upgrade/upgrade_command.ts": "27191f4b1ce93581b6d5ee2fff6003fe4fca437f476ecb98b6eae92f2b4d0716", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/_errors.ts": "f1fbb6bfa009e7950508c9d491cfb4a5551027d9f453389606adb3f2327d048f", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/_utils.ts": "25e519ce1f35acc8b43c75d1ca1c4ab591e7dab08327b7b408705b591e27d8bd", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/_validate_flags.ts": "e60b9038c0136ab7e6bd1baf0e993a07bf23f18afbfb6e12c59adf665a622957", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/deprecated.ts": "a72a35de3cc7314e5ebea605ca23d08385b218ef171c32a3f135fb4318b08126", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/deps.ts": "bed26afff36eeb25509440edec9d5d141b3411e08cc7a90e38a370969b5166bb", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/flags.ts": "3e62c4a9756b5705aada29e7e94847001356b3a83cd18ad56f4207387a71cf51", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/types.ts": "9e2f75edff2217d972fc711a21676a59dfd88378da2f1ace440ea84c07db1dcc", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/types/boolean.ts": "4c026dd66ec9c5436860dc6d0241427bdb8d8e07337ad71b33c08193428a2236", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/types/integer.ts": "b60d4d590f309ddddf066782d43e4dc3799f0e7d08e5ede7dc62a5ee94b9a6d9", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/types/number.ts": "610936e2d29de7c8c304b65489a75ebae17b005c6122c24e791fbed12444d51e", + "https://deno.land/x/cliffy@v1.0.0-rc.4/flags/types/string.ts": "e89b6a5ce322f65a894edecdc48b44956ec246a1d881f03e97bbda90dd8638c5", + "https://deno.land/x/cliffy@v1.0.0-rc.4/table/_layout.ts": "73a9bcb8a87b3a6817c4c9d2a31a21b874a7dd690ade1c64c9a1f066d628d626", + "https://deno.land/x/cliffy@v1.0.0-rc.4/table/_utils.ts": "13390db3f11977b7a4fc1202fa8386be14696b475a7f46a65178354f9a6640b7", + "https://deno.land/x/cliffy@v1.0.0-rc.4/table/border.ts": "5c6e9ef5078c6930169aacb668b274bdbb498461c724a7693ac9270fe9d3f5d5", + "https://deno.land/x/cliffy@v1.0.0-rc.4/table/cell.ts": "65e3ee699c3cebeb4d4d44e8f156e37a8532a0f317359d73178a95724d3f9267", + "https://deno.land/x/cliffy@v1.0.0-rc.4/table/column.ts": "cf14009f2cb14bad156f879946186c1893acdc6a2fee6845db152edddb6a2714", + "https://deno.land/x/cliffy@v1.0.0-rc.4/table/consume_words.ts": "369d065dbf7f15c664ea8523e0ef750fb952aea6d88e146c375e64aec9503052", + "https://deno.land/x/cliffy@v1.0.0-rc.4/table/deps.ts": "cbb896e8d7a6b5e3c2b9dda7d16638c202d9b46eb738c2dae1fa9480d8091486", + "https://deno.land/x/cliffy@v1.0.0-rc.4/table/row.ts": "79eb1468aafdd951e5963898cdafe0752d4ab4c519d5f847f3d8ecb8fe857d4f", + "https://deno.land/x/cliffy@v1.0.0-rc.4/table/table.ts": "298671e72e61f1ab18b42ae36643181993f79e29b39dc411fdc6ffd53aa04684" + } +}