世界を動かす技術を、日本語で。

「uv」の依存関係解決ツールを使ったWordleの解法

概要

  • Pythonの依存関係解決を使ったWordleソルバーの仕組みを解説
  • Sudokuソルバーの手法をWordle問題に応用
  • 各種パッケージとバージョン管理による状態表現
  • フィードバック情報の依存関係への変換手法
  • uvによる効率的な依存解決と実装例

Python依存解決でWordleを解く

  • Sudokuソルバー で使われたPoetry依存解決のアイデアを Wordle に応用
  • uvなど 最新Pythonパッケージ管理ツール の活用
  • 問題の各要素を パッケージとバージョン で表現する設計
  • GitHub で実装例を公開

SudokuとPython依存解決の背景

  • Pythonでは 同一プロジェクト内で同一パッケージの複数バージョンは不可
  • Sudokuの各マスを 81個のパッケージ、各数字を バージョン で表現
  • 行・列・ブロックごとの制約を 依存関係 として記述
  • 既知の数字は バージョン固定、残りはワイルドカードでロックファイル生成
  • Poetry/uv のロックファイル生成で自動的に解決

Wordleのルールとフィードバック

  • Wordle は5文字、6回以内に正解を当てる単語当てゲーム
  • 各文字ごとに グリーン(正位置)・イエロー(誤位置)・ブランク(不在) のフィードバック
  • 例:「YGG..」は1文字目イエロー、2・3文字目グリーン、4・5文字目ブランク

基本構成要素の分析

  • 解答候補単語 を1つのパッケージ、各単語をバージョンで表現
  • 各文字位置を 26バージョン持つ5つのパッケージ で表現(A~Z)
  • 単語パッケージの各バージョンは 位置パッケージ の特定バージョンに依存
    • 例:STALLなら1: S, 2: T, 3: A, 4/5: L

グリーン・イエロー判定の複雑さ

  • フィードバックにより 位置ごとの制約 が大きく変化
  • イエローは「その位置にはないが、他のどこかに存在」
  • ブランクは「グリーン・イエローでない位置にその文字は存在しない」
  • 複数回出現する文字や判定の違いに注意
  • 状況ごとに 事前処理で推論 が必要

Python依存関係ルールの限界

  • Pythonの依存関係仕様では「いずれかのバージョンに依存」は表現不可
  • そのため「 可能位置パッケージ」を追加
    • 各文字ごとに「どの位置に現れるか」をバージョンで管理(2進数エンコードで32バージョン)

フィードバックパッケージの導入

  • フィードバックパッケージ で「Aは位置1,2,5にいる」などの条件を表現
  • 各パッケージはTrue/False(バージョン0/1)のみ
  • フィードバックを元に 依存関係として追加
    • グリーン:{letter}in{position} バージョン1
    • イエロー:{letter}in{position} バージョン0+他位置で1
    • ブランク:該当しない全位置で0

全体構造:呪われたニューラルネットワーク

  • 入力層 :フィードバックパッケージ
  • 中間層 :可能位置パッケージ
  • 出力層 :正確な位置パッケージ(各位置にどの文字か)
  • 単語パッケージ :全体の解答候補
  • 問題パッケージ :解答候補+現在までのフィードバック制約

実装例

  • 5000近いパッケージ・バージョン群を Pythonスクリプトで自動生成
  • 依存関係の指定は「 許容するバージョン以外を全て除外」で実現
  • 各パッケージ例
    • フィードバックパッケージ(wordle_a_in_125)
    • 可能位置パッケージ(wordle_a_poss)
    • 正確な位置パッケージ(wordle_pos_1)
    • 単語パッケージ(wordle_word)

--find-linksとwheels活用

  • uv でwheelsを単一ディレクトリに出力
  • uv lock --find-links でローカルディレクトリを直接参照し高速解決
  • 約4883個のwheelsを 2分で生成 (1秒あたり約40個)

ハーネス(制御ループ)

  • ループごとに
    • フィードバック取得
    • 問題パッケージ用pyproject.toml生成
    • フィードバックパッケージへの依存制約を追加
    • uvで解決・次の推測単語を決定

まとめ

  • Python依存解決を 論理制約エンジン として転用した応用例
  • SudokuからWordleへと 汎用性の高いアプローチ
  • uv の高速性と柔軟なパッケージ生成・依存管理の有用性
  • 制約充足問題への Pythonパッケージ管理の新たな活用法

Hackerたちの意見

次のステップは、uvの依存関係解決ツールを使ってDoomをプレイすることだね。

オシロスコープで動いたらさらにポイント高いよね(妊娠検査薬はもうつまらないし)。

はい、お願いします!

もしuvのパッケージ解決ツールをもっと真面目な目的で使いたいなら、裏でpubgrub-rsライブラリを使ってることに注意してね。

これが僕のお気に入りの数独の試みだよ(Wordleよりも理解しやすいし、ずっとシンプルな問題だからね):https://github.com/konstin/sudoku-in-python-packaging 2008年のDebianパッケージを使った同じ数独のトリックもあるよ:https://web.archive.org/web/20080823224640/https://algebraic...

面白いことに、僕も数年前にSudokuのやつを作ったよ(Poetryを使ったけどね):https://github.com/mildbyte/poetry-sudoku-solver

じゃあ、次はnpmやってみて!

npmは一つのパッケージに複数のバージョンをインストールできるから、これにはうまくいかないかもね。「このパッケージは一つのバージョンだけインストールできる」って制約を設定できるパッケージマネージャーを使わない限り。

すべての「wordle-*」パッケージをPyPIに公開しなかった著者に心から感謝します。ありがとう!

またuvを使う理由が増えた!こういうバグは避けたいよね。最初は、生成するパッケージの文字リストからuをうっかり省いちゃって、特定の推測でめちゃくちゃ分かりにくい長い(500KBのuvが、なんで間違ってるかを必死に説明してくる)依存関係の解決エラーが出たんだ。これをやっちゃったから:import string LETTERS = string.ascii_lowercase じゃなくて、こっち:LETTERS = "abcdefghijklmnopqrstuvwxyz" の方が、ちょっと多く文字を打つけど、正しさを確認するのが楽だよね。

それ、めっちゃいいね!そんな文字列定数があるなんて知らなかった!

ちょっと話が逸れるけど、Firefoxの拡張機能Foxy Gesturesを使ってるんだ。特定のウェブサイトでジェスチャーを描くと、そのジェスチャーがポップアップで表示されるの。そんなの見たことなかった。これってJS/CSSのトリックなの?それとも拡張機能のバグ?

https://WordGlyph.xyz用にもできるのかな?