Doppelte Fragen erkennen

20

Doppelte Fragen erkennen

Es war einmal eine Golfanlage. Es gab ein Problem: Leute stellten immer wieder ähnliche oder identische Fragen. Du bist gewesenAuserwählte Auserwählte Zwangsverpflichtete erpresst aufgefordert, den Prozess der Entscheidung zu automatisieren, ob eine Frage ein Duplikat einer vorhandenen Frage ist, und zwar auf jede Art und Weise, die erforderlich ist (siehe Regeln).

Eingang

Ihr Programm muss eine einzelne URL als Eingabe akzeptieren. Es kann davon ausgegangen werden, dass dies zu einer Frage auf codegolf.stackexchange.com führt .

Ausgabe

Suchen Sie auf der Website nach ähnlichen Fragen. Wenn Sie der Meinung sind, dass die eingegebene Frage ein Duplikat einer vorhandenen Frage ist (oder umgekehrt), geben Sie die URL der anderen Frage aus. Sie können mehrere URLs ausgeben, die durch neue Zeilen getrennt sind. Am Ende Ihrer Ausgabe geben Sie end(in einer separaten Zeile) aus.

Wertung

  • Wenn eine von Ihnen ausgegebene Frage tatsächlich als Duplikat der eingegebenen Frage markiert wurde (oder umgekehrt), erhalten Sie 4 Punkte. Dies ist eine "richtige Vermutung".
  • Für jedes falsch positive Ergebnis (auch "falsche Vermutung" genannt) verlieren Sie 2 Punkte.
  • Verlieren Sie für jede Frage, die tatsächlich ein Duplikat war, aber nicht in Ihrer Ausgabe enthalten ist (auch bekannt als "fehlende Vermutung"), 1 Punkt.

Die höchste Punktzahl nach der Behandlung von 32 Eingabefragen gewinnt. Diese 32 Fragen sind eine "Runde". Zu Beginn jeder Runde werden die Punktzahlen auf 0 zurückgesetzt. Alle paar Tage wird eine Runde ausgeführt und die Rangliste nach jeder Runde aktualisiert.

Regeln

  • Wenn die Fragen A und C beide als Duplikate von B geschlossen sind, zählt A als Duplikat von C und umgekehrt.
  • Zu Beginn jeder Runde enthält Ihr Programm möglicherweise keine Daten zu Fragen (dh keine Hardcodierung ), es sei denn, Sie möchten wissen , wie die Website analysiert wird.
  • Sie können jedoch während einer Runde Daten in externen Dateien aufbewahren.
  • Zwischen den Runden dürfen keine Daten gespeichert werden.
  • Ihre Ausgabe muss eine nachgestellte neue Zeile haben.
  • Sie dürfen keine Daten von der Website außer den Suchergebnissen und der URL, dem Titel, den Tags und dem Text einer Frage mit oder ohne Formatierung verwenden. Beispielsweise dürfen Sie nicht den Text "als Duplikat von foo, bar ... markiert" verwenden, der auf doppelten Fragen erscheint.
  • Sie können diese Daten direkt von der Site über data.SE oder über die API abrufen.
  • Jede Einreichung muss einen Namen haben.
  • Jede Einreichung muss eine eindeutige Versionsnummer haben.
  • Wenn eine Einreichung nach Ablauf einer festzulegenden Frist keine Ausgabe liefert (bitte geben Sie an, wie lange Ihre Einreichung dauert), wird sie abgebrochen und verliert 8 Punkte.

quelle
2
Ist 1 Minute nicht subjektiv? Netzwerkverbindungen und Crawlen führen zu einer Vielzahl von Webanforderungen. Es könnte leicht länger als 1 Minute dauern für alle :)
Optimizer
4
Ich denke, wir können nicht direkt zu dieser Zahl kommen. Möglicherweise müssen Sie selbst ein Beispielprogramm schreiben (oder die erste Antwort verwenden), um die richtige Schwellenzeit zu bestimmen.
Optimierer
7
Anstatt die Site zu scrappen, sollten Sie die API durchgehen und angeben, welche Felder verwendet werden dürfen.
Gilles 'SO- hör auf böse zu sein'
5
Es wäre so lustig, wenn diese Frage ein Duplikat wäre ... oh die Ironie xD
Teun Pronk
3
@professorfish Du könntest wirklich ein paar Testfälle gebrauchen, los geht's. Diese Daten stammen alle von Data.SE und sollten daher zuverlässig sein. Fühlen Sie sich frei, mich albern aussehen zu lassen und mir das Gegenteil zu beweisen. Diese Frage hat codegolf.stackexchange.com/q/37737 hat keine Duplikate. Diese Frage hat codegolf.stackexchange.com/q/12348 diese codegolf.stackexchange.com/q/10465 Diese Frage hat codegolf.stackexchange.com/q/12498 diese codegolf.stackexchange.com/q/20006 codegolf.stackexchange.com/ q / 242
PenutReaper

Antworten:

3

Python 3

Ich gebe diesem Eintrag den Namen 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")

Der Filter "!-*f(6rc.cI8O"enthielt den totalParameter für das globale Wrapper-Objekt und den bodyParameter für Fragen.

Mit diesem Eintrag werden zwei API-Anforderungen plus eine pro Tag für die Frage plus eine pro hundert Fragen in dem am wenigsten verwendeten Tag erstellt. Wenn es eine Api-Drossel trifft (auf die es nicht prüft), wird ein erhöhturllib.error.HTTPError: HTTP Error 400: Bad Request

Pfeffer
quelle