Détecter les questions en double

20

Détecter les questions en double

Il était une fois un site de golf. Il y avait un problème: les gens posaient encore et encore des questions similaires ou identiques. Vous avez étéchoisi sélectionné forcé enrôlé chantage demandé d'automatiser le processus de décision si une question est une copie d'une question existante, par tous les moyens nécessaires (voir Règles).

Contribution

Votre programme doit accepter une seule URL comme entrée. Il peut supposer que cela conduit à une question sur codegolf.stackexchange.com .

Production

Recherchez des questions similaires sur le site. Si vous pensez que la question d'entrée est un doublon d'une question existante (ou vice versa), affichez l'URL de l'autre question. Vous pouvez générer plusieurs URL, séparées par de nouvelles lignes. À la fin de votre sortie, sortez end(sur une ligne distincte).

Notation

  • Si une question que vous sortez était en effet marquée comme un doublon de la question d'entrée (ou vice versa), vous marquez 4 points. Il s'agit d'une "supposition correcte".
  • Pour chaque faux positif (aka "estimation incorrecte"), vous perdez 2 points.
  • Pour chaque question qui était en fait un doublon mais qui n'apparaît pas dans votre sortie (alias "supposition manquante"), perdez 1 point.

Le score le plus élevé après avoir traité 32 questions d'entrée gagne. Ces 32 questions sont un "tour". Au début de chaque tour, les scores seront remis à 0. Un tour sera exécuté tous les quelques jours et le classement sera mis à jour après chaque tour.

Règles

  • Si les questions A et C sont toutes deux fermées en tant que doublons de B, A comptera comme un doublon de C et vice versa.
  • Au début de chaque tour, votre programme peut ne pas posséder de données sur des questions (c'est-à-dire pas de codage en dur ), sauf sur la façon d'analyser le site Web.
  • Cependant, vous pouvez conserver des données dans des fichiers externes pendant un tour.
  • Aucune donnée ne peut être conservée entre les tours.
  • Votre sortie doit avoir une nouvelle ligne de fin.
  • Vous ne pouvez utiliser aucune donnée du site Web à l'exception des résultats de recherche et de l'URL, du titre, des balises et du texte d'une question , avec ou sans mise en forme. Par exemple, vous ne pouvez pas utiliser le texte "marqué comme doublon par foo, bar ..." qui apparaît sur les questions en double.
  • Vous pouvez récupérer ces données directement sur le site, via data.SE ou via l'API.
  • Chaque soumission doit avoir un nom.
  • Chaque soumission doit avoir une numérotation de version claire.
  • Si une soumission ne produit pas de résultat après un délai (à déterminer; veuillez indiquer le temps que prend votre soumission), elle sera tuée et perdra 8 points.

la source
2
N'est-ce pas 1 minute subjective? Les connexions réseau et l'exploration entraîneront un grand nombre de demandes Web. Cela pourrait facilement prendre plus d'une minute pour tout le monde :)
Optimizer
4
Je pense que nous ne pouvons pas arriver à ce nombre directement, vous devrez peut-être écrire un exemple de programme vous-même (ou utiliser la première réponse) pour déterminer le temps de seuil correct.
Optimiseur
7
Au lieu de gratter le site, vous devez passer par l'API et spécifier les champs qui peuvent être utilisés.
Gilles 'SO- arrête d'être méchant'
5
Ce serait tellement drôle si cette question était en double .. oh l'ironie xD
Teun Pronk
3
@professorfish Vous pourriez vraiment utiliser des cas de test, c'est parti. Ces données proviennent toutes de Data.SE, elles devraient donc être fiables. N'hésitez pas à me faire paraître idiot et à me prouver le contraire. Cette question a codegolf.stackexchange.com/q/37737 n'a pas de doublons. Cette question codegolf.stackexchange.com/q/12348 a ce codegolf.stackexchange.com/q/10465 Cette question codegolf.stackexchange.com/q/12498 a ces codegolf.stackexchange.com/q/20006 codegolf.stackexchange.com/ q / 242
PenutReaper

Réponses:

3

Python 3

Je donne à cette entrée le nom The Differ.

Code:

import urllib.request, gzip, re, json, difflib, sys
API_URL = "https://api.stackexchange.com/"
qurl = input()
qid = int(re.search("\d+",qurl).group(0))
def request(url,wrapper=False,**params):
    params.setdefault("filter","withbody")
    params.setdefault("site","codegolf")
    url = API_URL + url + "?"+"&".join([str(k)+"="+str(v) for k,v in params.items()])
    compressed_response = urllib.request.urlopen(url)
    response = gzip.decompress(compressed_response.read()).decode("utf8")
    response_object = json.loads(response)
    if wrapper:
        return response_object
    else:
        return response_object["items"]
question = request("questions/%s"%qurl)[0]
tags = ";".join(question["tags"])
title = question["title"]
escaped = title.replace(" ","%20")
related = request("similar",title=escaped,pagesize=100)
hasmore = False
length = sys.maxsize
for tag in question["tags"]:
    result = request("search",tagged=tag,
                     wrapper=True,
                     filter="!-*f(6rc.cI8O",
                     pagesize=100)
    if result["total"] < length:
        length = result["total"]
        related.extend(result["items"])
        hasmore = result["has_more"]
        besttag = tag
related.extend(best)
if length < 1500:
    for page in itertools.count(2):
        if not hasmore:
            break
        response = request("search",
                           tagged=besttag,
                           page=page,
                           pagesize=100,
                           filter="!-*f(6rc.cI8O",
                           wrapper=True)
        hasmore = response["has_more"]
        related.extend(result["items"])
matcher = difflib.SequenceMatcher(None, question["body"], None)
titlematcher = difflib.SequenceMatcher(None, question["title"], None)
seen = set()
seen.add(question["question_id"])
for possible in related:
    matcher.set_seq2(possible["body"])
    titlematcher.set_seq2(possible["title"])
    score = matcher.ratio()+titlematcher.ratio()
    qid = possible["question_id"]
    if score > .85 and qid not in seen:
        print(qid)
        seen.add(qid)
print("end")

Le filtre "!-*f(6rc.cI8O"incluait le totalparamètre sur l'objet wrapper global et le bodyparamètre sur les questions.

Cette entrée fait deux demandes d'API plus une par balise sur la question plus une pour cent questions dans sa balise la moins utilisée. S'il atteint un accélérateur api (qu'il ne vérifie pas), il soulèvera unurllib.error.HTTPError: HTTP Error 400: Bad Request

pppery
la source