Quem disse isso? Eleição presidencial de 2016

16

Nesse desafio, sua tarefa é fazer escrever um programa com menos de 300 caracteres, com um parágrafo curto ou algumas frases que um candidato tenha dito e emitido quem o disse.

Entrada : pode ser tomada como parâmetro para uma função, entrada para um programa etc. Será um parágrafo curto, corretamente pontuado.

Saída : o candidato que você pensa que é. Este poderia ser um dos

Ben Carson (1)
Ted Cruz (2)
John Kasich (3)
Marco Rubio (4)
Donald Trump (5)
Hillary Clinton (6)
Bernie Sanders (7)

Eu deixei de fora os nomes das pessoas que desistiram desde 1º de março. Você pode imprimir o próprio nome ou, mais convenientemente, o número que corresponde ao nome.

Pontuação: sua pontuação é a porcentagem de casos de teste que você acertou. Maior pontuação ganha. Os laços (ou pontuações perfeitas) são quebrados pelo comprimento do código, como em um código de golfe.

Os casos de teste podem ser obtidos de:

http://www.presidency.ucsb.edu/debates.php

Clique em cada debate, democrata e republicano que aconteceu até agora (antes de 1º de março). Todo parágrafo é um caso de teste, a menos que o "parágrafo" tenha menos de 20 caracteres.

Aqui está o código que extrai os casos de teste de uma página específica:

var t = $(".tools").parentNode.querySelectorAll("p");
var categ = {}, cur = 0;
for (var i = 0; i < t.length; ++i) {
  var p = t[i], str = p.innerText;
  if (p.querySelector("b")) {
    cur = p.querySelector("b").innerText.replace(':', '');
    str = str.replace(/^.*?:\s/, '');
  }
  str = str.replace(/\[applause\]/g, '')
  if (str.length < 20) continue;
  if (categ[cur] == null) categ[cur] = [];
  categ[cur].push(str);
}

Você pode fazer isso categ.SANDERSpara obter uma lista de todos os parágrafos que o senador Sanders disse.

Você pode descartar qualquer coisa que não seja dita pelos candidatos listados acima (por exemplo, categ.BUSHou categ.CHRISTIE).

Aqui está o arquivo com todos os casos de teste: https://drive.google.com/file/d/0BxMn8--P71I-bDZBS2VZMDdmQ28/view?usp=sharing

O arquivo é organizado pelo candidato

CANDIDATE CANDIDATE_LAST_NAME
(empty line)
Series of statements. Each paragraph is separated by (NEW PARAGRAPH)-
(empty line)
CANDIDATE NEXT_CANDIDATE_LAST_NAME
(empty line)
etc.

Um exemplo de envio parcial seria:

if (/ win | wall | great | beautiful/.test(p)) return 5;
if (/ percent | top one | rigged /.test(p)) return 7;
// etc. for all candidates

ou

var words = p.split(' ');
// majority of words have less than 5 characters
if (words.length - words.filter(a => a.length < 5).length < 4) evidence[5]++;
// at the end
return /* index with the most evidence */ 

Aqui é um lugar onde você pode testar soluções javascript: https://jsfiddle.net/prankol57/abfuhxrh/

O código usa o parâmetro ppara representar a frase a ser classificada. Exemplo de código com pontuação em torno de 20% (a estimativa seria de 11%):

if (/ rigged | top | percent | Wall Street /.test(p)) return 'Sanders';
return 'Trump';

Exatamente o que estou perguntando: escreva um programa / função com menos de 300 caracteres que tome como entrada uma frase que um candidato tenha dito e retorne como saída que o candidato disse. Sua pontuação é a porcentagem de casos de teste que você acertou. Maior pontuação ganha.

Sim, eu sei que muitas linhas têm [laughter]ou estão [cheering]nelas. Estes não serão removidos. Na pior das hipóteses, são informações extras que você pode ignorar; na melhor das hipóteses, são informações extras que você pode usar (por exemplo, eu inventei isso, mas talvez o riso das pessoas seja uma evidência de que Marco Rubio está falando). Os casos de teste são como eles aparecem no arquivo de texto.

soktinpk
fonte
1
Eu tenho uma sugestão. Que tal você fazer código-golfe, mas precisa acertar todas as aspas? Além disso, convém diminuir as cotações, pois isso é um pouco ridículo de resolver como está.
Cyoce 02/03
2
@Cyoce acertar todas as citações seria ridículo (eu acho) considerando o grande número de citações.
soktinpk
1
Idéia de desafio inteligente, pode precisar de algum refinamento. Você já pensou em postar no Sandbox para receber algum feedback?
Ashwin Gupta 02/03
1
Qual é o critério de vencimento? (E por que você acha que ninguém vai ter uma pontuação perfeita?)
Peter Taylor
2
Os dados de origem que você forneceu são um pouco confusos (difíceis de analisar automaticamente), o que eu acho que tira um pouco do espírito do desafio. Fiz uma versão limpa que usa uma linha por cotação, com uma linha em branco que separa o próximo nome do candidato. Isso é muito mais fácil de analisar na maioria dos idiomas. Fiz o upload aqui: drive.google.com/file/d/0B3uyVnkMpqbVSnVrZkVwTUhDODg (além de alterar novas linhas, deixei os dados intocados. Isso inclui o que parece ser um problema de codificação para -)
Dave

Respostas:

14

Poliglota, ~ 18,6%

Isso funciona em: Cjam, Pyth, TeaScript, Japt, Seriamente, 05AB1E, GolfScript, Jelly e provavelmente muito mais.

6

Isso gera Hillary para todas as entradas. Isso ocorre porque Hillary disse mais. Embora não seja a maneira mais engenhosa de fazer isso. Funciona ¯ \ _ (ツ) _ / ¯

Downgoat
fonte
Gosto de como isso é sinalizado como postagem de baixa qualidade. : P
Denker
1
@DenkerAffe provavelmente por ser curto
Downgoat
1
Alguma razão para usar JavaScript? Você poderia ter golfed-lo a um personagem em alguma outra língua: P
ghosts_in_the_code
@ghosts_in_the_code fixo
Downgoat
9

Pitão, 34,16% (297 bytes)

FNc"7creta
6enato
3ohio
2donal
7 major 
6o try t
5tot
5se me
7nai
4m pres
2he ob
3 bala
5jeb
6e aff
5mendous 
2mnest
5. we'r
7ave got to
2c ter
4ntur
7 campaign 
2flat
5obo
4is pre
4-here'
2note
2m el
4 issue 
5, very
6o af
1fact o
6en's
5pany
6he republicans
7 -- 
4meon
5bea
4ory o
7"bI}tNrzZhNB

(observe que algumas linhas terminam em espaços)

Eu optei pela opção mais simples que consegui pensar: verifique uma lista de padrões e, assim que encontrar uma correspondência, faça a saída do candidato correspondente. Se tudo mais falhar, produza o candidato mais provável a partir do restante. Depois disso, trata-se de compactar o máximo possível de dados em 300 bytes.

FNc"<data>"bI}tNrzZhNB

Demolir:

FN                      for N in ...
   "<data>"              the hard-coded data (newline separated)
  c                      split using...
           b             '\n' constant,
            I           if
              tN         tail (all but first char) of current item
             }           is contained within
                rzZ      the input (lowercased),
                        then:
                   hN    print the head (first char) of the current item
                     B   and break out of the loop.

Então, de onde vêm esses dados? Bem, a estrutura é simplesmente:

<candidate_number><phrase>
<candidate_number><phrase>
<etc.>

(com uma entrada no final sem frase para atuar como o substituto final)

Mas por que esses itens em particular? Eu escrevi um programa C ++ para analisar o conjunto de dados fornecido (com alguma limpeza manual de novas linhas primeiro para tornar a estrutura consistente). Ele analisa todas as substrings ("tokens") em cada citação (de 1 a 16 caracteres) e verifica repetidamente o token que oferece o maior benefício a seguir na lista. Quando um padrão estiver na lista, remova as aspas correspondentes e repita (fica um pouco mais complicado mantê-lo rápido, mas esse é o básico). O código provavelmente é muito longo para ser incluído aqui, mas eu posso colocá-lo no github mais tarde (quando eu o limpei um pouco).

Eu tentei alguns sistemas de pontuação. No final, eu fui com este:

score = (
    + matching_quote_count_for_most_likely_author * 10
    - matching_quote_count_for_other_authors * 7
    - token_length
)

Uma abordagem mais rigorosa de permitir apenas novos itens que não introduzem respostas incorretas pareceu ficar em torno de 20 a 25%, necessitando de muitos padrões para aumentar. Essa abordagem mais confusa se sai muito melhor e ainda pode atingir ~ 80% de precisão (com 550 itens). A pontuação enviada possui 38 itens, que foi o máximo que pude caber no limite de 300 caracteres.

Na verdade, o resultado de 34% vem de um programa C ++ de teste que executa as mesmas etapas. Deve combinar, mas não tenho um equipamento de teste Pyth para verificar.

Esta é a primeira vez que usei Pyth, então imagino que mais bytes possam ser extraídos, permitindo um pouco mais de dados.

Dave
fonte
4
Agora também sei que Sanders adora falar sobre a secretária Clinton, Clinton é obcecada pelo senador Sanders, Kasich ama Ohio, Cruz sempre menciona Donald Trump, Rubio é obcecado por séculos, Carson tem todos os "fatos do assunto", e Trump adora dizer "totalmente". Parece o começo de um gerador de bingo político. Vou ter de experimentá-lo em algumas personalidades do Reino Unido ...
Dave
Eu acho que você poderia salvar alguns bytes aqui carregando a string com .".
lirtosiast
8

Javascript, 32,87%

299 caracteres:

function Q(a,b){return p.toLowerCase().split(' ').join('').includes(a)<<b}z=Q('ink',0)+Q('int',1)+Q('ona',2)+Q('rica',3)+Q('twe',4)+Q("we'",5)+Q('youkn',6);return '55472726464727446676664676767676563641233643334456364233336141745116222136477126111113361611262316263122216111673336225611363276'[z]*1

Estratégia:

Eu fiz uma pesquisa de força bruta sobre quais segmentos de palavras incluir em um "hash". Em seguida, uma pesquisa de string acontece com esse hash de maneira a escolher o candidato mais provável para esse hash.

O próprio código:

// The Q function checks if a string is present.
// Then left-shifts the true/false result up to e.g. 64,32,16,8,4,2,1
// This way we can combine results into any number 0 to 127.
function Q(a,b){return p.toLowerCase().split(' ').join('').includes(a)<<b}

// Now we check for key string occurrences:
z=Q('ink',0)+Q('int',1)+Q('ona',2)+Q('rica',3)+Q('twe',4)+Q("we'",5)+Q('youkn',6)

// Finally, use this as an index into the lookup string. (Multiply by 1 to convert char to int.)
return '55472726464727446676664676767676563641233643334456364233336141745116222136477126111113361611262316263122216111673336225611363276'[z]*1

Este é o meu primeiro envio de código de golfe, então sugestões são bem-vindas :)

Ru Hasha
fonte
5

Mathematica, 23,7775%

(l=ToLowerCase@#;Ordering[-StringCount[l,#]&/@{"fact","donald"|"obama","done"|"ohio","issue"|"united"|"why"|"world","great"|"many","senator","american"|"believe"|"campaign"|"secretary"|"street"|"wall"},1])[[1]]&

Ele conta as ocorrências de palavras-chave comuns exclusivas de cada candidato e gera o número do candidato com a pontuação mais alta.

Basicamente, encontrei as palavras mais comuns de todos os candidatos

t = Import["~/Documents/candidate quotes.txt"];
ts = DeleteCases[StringSplit[t, "\n\n"], ""];
tss = Split[ts, StringLength[#2] > 20 &][[{3, 4, 5, 6, 7, 1, 2}]];
names = StringSplit[#][[2]] & /@ tss[[All, 1]];
quotes = StringSplit[#, "(NEXT PARAGRAPH)"] & /@ StringJoin /@ tss[[All, 2 ;;]];
(* remove the 100 commonest english words *)
wd = WikipediaData["Most common words in English", "ArticleWikicode"];
Flatten[StringSplit[StringCases[wd, 
  Shortest["{| class=\"wikitable\"" ~~ w__ ~~ "}"] -> w], "\n"]];
common100 = 
Alternatives @@ ToLowerCase@DeleteDuplicates@Flatten[StringSplit /@ 
     StringCases[#, 
      "|| " ~~ ("[[" | "") ~~ w : ((WordCharacter | " ") ..) -> 
       w] & /@ %];
commonest = 
  Commonest[
Flatten[StringSplit[
    StringDelete[ToLowerCase[#], 
     PunctuationCharacter | (WordBoundary ~~ (common100) ~~ 
        WordBoundary)]] & /@ #], 20] & /@ quotes;

e escolheu as palavras-chave comuns únicas para cada candidato.

keywords = 
 Alternatives @@@ 
  Table[Complement[commonest[[n]], 
    Union[Flatten[Delete[commonest, n]]]], {n, Length[names]}];

Após excluir manualmente algumas das palavras-chave, esta é a tabela final:

Carson    fact
Cruz      donald|obama
Kasich    done|ohio
Rubio     issue|united|why|world
Trump     great|many
Clinton   senator
Sanders   american|believe|campaign|secretary|street|wall

Com essas palavras-chave, o comprimento total da função é de 211 caracteres. Eu testei a função em todas as aspas:

pairs = Flatten[MapThread[Table[q -> #1, {q, #2}] &, {names, quotes}]];
test[q_ -> n_] := Boole[n === names[[p@q]]] (* here p is my function that outputs the predicted candidate's number *)
Total[ParallelMap[test, pairs]]/Length[pairs] // N

o que fornece uma precisão de 23,7775%.

shrx
fonte
3

Python, 25.677868%

Arbitrariamente escolheu quatro caracteres diferentes que seriam usados ​​para identificar os candidatos. Cada candidato recebe um fator de pontuação por personagem, com base em uma pesquisa em subidas que eu corri por alguns minutos para terminar em 25,68%.

Suponho que isso prova pelo menos que o conceito é melhor do que escolher um candidato com os olhos vendados ou apenas escolher Clinton, mas eu estaria interessado em ver alguém aplicar um algoritmo de pesquisa melhor, tanto pelos fatores quanto pelos caracteres utilizados.

w=dict(zip("hr?.",((.847,.491,.821,.54,.744,.765,.234),(.494,.777,.202,.587,.7,.852,.484),(.915,.187,.161,.559,.748,.244,.43),(.11,.013,.628,.974,1.037,.484,.302))))
def f(t,r=(0,0,0,0,0,0,0)):
 s=r
 for c in t:s=map(lambda a,b:a+b,s,w.get(c,r))
 return s.index(max(s))+1
boomlinde
fonte
1

Javascript, TBD

a=[...p].reduce((a,b)=>(a<<5)-a+b.charCodeAt(0)|0,0)%1000,alert(a>0?0:1000,a<79?1:a<226?2:a<333?3:a<497?4:a<697?5:a<849?6:7)

Converte cada string em um código de hash e usa métodos probabilísticos para determinar o alto-falante. Seria bom se alguém com uma boa configuração pudesse testar isso para mim.

LegionMammal978
fonte
Conto cerca de 16,1%, mas não tenho muita certeza do que faz. O que o a + = a? 0: 1000 faz? (Eu tive que substituir o alerta com um retorno assim que eu não tinha certeza exatamente o que fazer)
soktinpk
@soktinpk Desculpe, o a+=erro deve ter sido um erro de digitação.
precisa