diff --git a/README.md b/README.md index 46a2a04..80902ae 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,16 @@ - *Выходные данные:* таблица жанров, таблица связей со столбцами (игра, жанр) - *Решение:* смотри файл scrape_genres.py +### Сопоставление базового с полным набором игр + +Необходимо реализовать быстрый неточный поиск из базового набора в полном. Предложение: построить однословные индексы по базовому и полному набору, при сопоставлении использовать расстояние Левенштейна около 3. + +Принято решение сравнивать очищенные названия триграммами. Ошибки присутствуют, для их отбора и исправления можно использовать расстояние Левенштейна. + +- *Входные данные:* таблица игр, таблица архивов +- *Выходные данные:* таблица связей со столбцами (игра, архив) +- *Решение:* смотри файл fuzzy_search.py + ## Задачи ### Выделить из базы данных кеш @@ -57,10 +67,6 @@ html-страницы складывать в отдельную базу дан Необходимо просмотреть жанры, маловстречающиеся и повторяющиеся объединить, построить примерное дерево категорий. -### Сопоставление базового с полным набором игр - -Необходимо реализовать быстрый неточный поиск из базового набора в полном. Предложение: построить однословные индексы по базовому и полному набору, при сопоставлении использовать расстояние Левенштейна около 3. - ### Построение результирующего набора игр Необходимо решить задачу минимизации критериальной функции с ограничением в 15 Гб размера на основе критериев: diff --git a/db.sqlite3 b/db.sqlite3 index 7acc4a2..662e62c 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/fuzzy_search.py b/fuzzy_search.py new file mode 100644 index 0000000..7673aa3 --- /dev/null +++ b/fuzzy_search.py @@ -0,0 +1,51 @@ + +import sqlite3 +from ngram import NGram + +tr_table = str.maketrans('','',' !$&\'()+,-.=@[]') + +def key(s): + """ + !$&'()+,-.0123456789=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz + """ + return s.removesuffix('.zip').lower().translate(tr_table) + +def test_key(): + """ + 1 vs 100 (Europe) [b].zip + 1 vs 100 (europe) [b] + """ + s = '1 vs 100 (Europe) [b].zip' + assert key(s) == '1vs100europeb', key('1 vs 100 (Europe) [b].zip') + +def select(name, xs): + while True: + print(f'?: {name}') + for i, ((_, name), _) in enumerate(xs,1): + print(f'{i}. {name}') + inp = input('1-9,n: ') + if inp=='': + return xs[0] + if inp=='n': + raise ValueError + if inp in set('123456789'): + return xs[int(inp)-1] + +if __name__=='__main__': + test_key() + with sqlite3.connect("db.sqlite3") as db: + G = NGram(key=lambda x: key(x[1])) + for game in db.execute("SELECT ROWID, zip_name FROM archive;"): + G.add(game) + + db.execute("DROP TABLE IF EXISTS game_to_archive;") + db.execute("CREATE TABLE game_to_archive (id_game INTEGER, id_archive INTEGER);") + for id_game, name in db.execute("SELECT ROWID, name FROM top_games;"): + try: + ((id_a1, n1), p1), ((id_a2, n2), p2) = G.search(name)[:2] + if p1/p2<1.05: + (id_a1, n1), p1 = select(name, G.search(name)[:9]) + db.execute("INSERT INTO game_to_archive VALUES (?, ?);", (id_game, id_a1)) + except: + db.execute("INSERT INTO game_to_archive VALUES (?, NULL);", (id_game,)) + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..32519a9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +ngram +requests +lxml