Detectar perguntas duplicadas

20

Detectar perguntas duplicadas

Era uma vez, havia um site de golfe. Tinha um problema: as pessoas publicavam perguntas semelhantes ou idênticas repetidas vezes. Você esteveselecionado recrutado forçado recrutado chantageado solicitado a automatizar o processo de decidir se uma pergunta é uma duplicata de uma existente, por qualquer meio necessário (consulte Regras).

Entrada

Seu programa deve aceitar um único URL como entrada. Pode-se supor que isso leve a uma pergunta no codegolf.stackexchange.com .

Saída

Pesquise no site perguntas semelhantes. Se você acha que a pergunta de entrada é uma duplicata de uma pergunta existente (ou vice-versa), imprima o URL da outra pergunta. Você pode gerar vários URLs, separados por novas linhas. No final da sua saída, emita end(em uma linha separada).

Pontuação

  • Se uma pergunta que você produz foi realmente marcada como uma duplicata da pergunta de entrada (ou vice-versa), você ganha 4 pontos. Este é um "palpite correto".
  • Para cada falso positivo (também conhecido como "palpite incorreto"), você perde 2 pontos.
  • Para cada pergunta que era realmente uma duplicata, mas não aparece na sua saída (também conhecida como "falta de palpite"), perca 1 ponto.

A pontuação mais alta depois de lidar com 32 perguntas de entrada vence. Essas 32 perguntas são uma "rodada". No início de cada rodada, as pontuações serão redefinidas para 0. Uma rodada será executada a cada poucos dias e o placar atualizado após cada rodada.

Regras

  • Se as perguntas A e C forem fechadas como duplicatas de B, A contará como duplicata de C e vice-versa.
  • No início de cada rodada, seu programa pode não possuir dados sobre perguntas (por exemplo, sem codificação ), exceto sobre como analisar o site.
  • No entanto, você pode manter os dados em arquivos externos durante uma rodada.
  • Nenhum dado pode ser mantido entre as rodadas.
  • Sua saída deve ter uma nova linha à direita.
  • Você não pode usar nenhum dado do site, exceto os resultados da pesquisa e o URL, título, tags e texto de uma pergunta , com ou sem formatação. Por exemplo, você não pode usar o texto "marcado como duplicado por foo, bar ..." que aparece nas perguntas duplicadas.
  • Você pode recuperar esses dados diretamente do site, via data.SE ou pela API.
  • Cada envio deve ter um nome.
  • Cada envio deve ter uma numeração clara da versão.
  • Se um envio não produzir saída após um prazo (a ser decidido; indique quanto tempo leva), ele será eliminado e perderá 8 pontos.

fonte
2
1 minuto não é subjetivo? As conexões de rede e o rastreamento levarão a um grande número de solicitações da Web. Poderia facilmente ter mais de 1 minuto para todos :)
Optimizer
4
Acho que não podemos chegar diretamente a esse número; talvez você precise escrever um exemplo de programa (ou usar a primeira resposta) para determinar o tempo limite correto.
Optimizer
7
Em vez de raspar o site, você deve passar pela API e especificar quais campos podem ser usados.
Gilles 'SO- stop be evil'
5
Seria tão engraçado se esta questão foi um duplicado .. oh a ironia xD
Teun Pronk
3
@professorfish Você realmente pode usar alguns casos de teste, aqui está. Todos esses dados vieram do Data.SE, portanto devem ser confiáveis. Sinta-se livre para me fazer parecer bobo e provar que estou errado. Esta pergunta tem codegolf.stackexchange.com/q/37737 não tem duplicatas. Esta pergunta codegolf.stackexchange.com/q/12348 tem esta codegolf.stackexchange.com/q/10465 Esta pergunta codegolf.stackexchange.com/q/12498 tem esta codegolf.stackexchange.com/q/20006 codegolf.stackexchange.com/ q / 242
PenutReaper

Respostas:

3

Python 3

Estou dando o nome a esta entrada The Differ.

Código:

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")

O filtro "!-*f(6rc.cI8O"incluiu o totalparâmetro no objeto wrapper global e o bodyparâmetro nas perguntas.

Essa entrada faz duas solicitações de API, mais uma por tag na pergunta e uma por cem perguntas na tag menos usada. Se atingir um acelerador de API (que não é verificado), aumentará umurllib.error.HTTPError: HTTP Error 400: Bad Request

pppery
fonte