Qui a dit ça? Élection présidentielle de 2016

16

Dans ce défi, votre tâche est de faire écrire un programme de moins de 300 caractères qui prend un court paragraphe ou quelques phrases qu'un candidat a dit et qui l'a sorti.

Entrée : Peut être prise comme paramètre d'une fonction, entrée dans un programme, etc. Ce sera un court paragraphe, correctement ponctué.

Résultat : le candidat que vous pensez être. Cela pourrait être l'un des

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

J'ai omis les noms des personnes qui ont abandonné le 1er mars. Vous pouvez sortir le nom lui-même, ou, plus commodément, le numéro qui correspond au nom.

Notation: votre score est le pourcentage de cas de test que vous obtenez correctement. Le score le plus élevé l'emporte. Les égalités (ou les scores parfaits) sont brisées par la longueur du code comme dans un golf de code.

Les cas de test peuvent être extraits de:

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

Cliquez sur chaque débat, à la fois démocrate et républicain qui a eu lieu jusqu'à présent (avant le 1er mars). Chaque paragraphe est un cas de test, à moins que le «paragraphe» comporte moins de 20 caractères.

Voici le code qui extrait les cas de test d'une page particulière:

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);
}

Vous pouvez ensuite faire categ.SANDERSpour obtenir une liste de tous les paragraphes que le sénateur Sanders a dit.

Vous pouvez rejeter tout ce qui n'est pas dit par les candidats énumérés ci-dessus (par exemple categ.BUSHou categ.CHRISTIE).

Voici le fichier avec tous les cas de test: https://drive.google.com/file/d/0BxMn8--P71I-bDZBS2VZMDdmQ28/view?usp=sharing

Le dossier est organisé par candidat

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.

Un exemple de soumission partielle serait:

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 */ 

Voici un endroit où vous pouvez tester des solutions javascript: https://jsfiddle.net/prankol57/abfuhxrh/

Le code utilise le paramètre ppour représenter la phrase à classer. Exemple de code qui marque environ 20% (deviner obtiendrait environ 11%):

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

Exactement ce que je demande: Écrivez un programme / fonction en moins de 300 caractères qui prend en entrée une phrase qu'un candidat a dite et retourne en sortie quel candidat l'a dit. Votre score est le pourcentage de cas de test que vous obtenez correctement. Le score le plus élevé l'emporte.

Oui, je sais que beaucoup de lignes ont [laughter]ou [cheering]en elles. Ceux-ci ne seront pas supprimés. Au pire, ce sont des informations supplémentaires que vous pouvez ignorer; au mieux, ce sont des informations supplémentaires que vous pouvez utiliser (par exemple, j'ai inventé cela, mais peut-être que les gens rient sont la preuve que Marco Rubio parle). Les cas de test sont tels qu'ils apparaissent dans le fichier texte.

soktinpk
la source
1
J'ai une suggestion. Que diriez-vous de le faire code-golf, mais vous devez obtenir toutes les citations à droite? De plus, vous voudrez peut-être rendre les devis beaucoup plus courts, car c'est un peu ridicule à résoudre tel quel.
Cyoce
2
@Cyoce obtenir toutes les bonnes citations serait ridicule (je pense) compte tenu du grand nombre de citations.
soktinpk
1
Idée de défi intelligente, peut cependant nécessiter quelques améliorations. Avez-vous envisagé de publier dans Sandbox pour obtenir des commentaires?
Ashwin Gupta
1
Quel est le critère gagnant? (Et pourquoi pensez-vous que personne n'obtiendra un score parfait?)
Peter Taylor
2
Les données source que vous avez fournies sont un peu désordonnées (difficiles à analyser automatiquement), ce qui, à mon avis, enlève un peu l'esprit du défi. J'ai fait une version nettoyée qui utilise une ligne par devis, avec une ligne vierge séparant le prochain nom candiate. C'est beaucoup plus facile à analyser dans la plupart des langues. Je l'ai téléchargé ici: drive.google.com/file/d/0B3uyVnkMpqbVSnVrZkVwTUhDODg (à part changer les nouvelles lignes, j'ai laissé les données intactes. Cela inclut ce qui ressemble à un problème d'encodage pour -)
Dave

Réponses:

14

Polyglotte, ~ 18,6%

Cela fonctionne dans: Cjam, Pyth, TeaScript, Japt, Ser sérieux, 05AB1E, GolfScript, Jelly et probablement beaucoup d'autres.

6

Cela produit Hillary pour toutes les entrées. C'est parce que Hillary en a dit le plus. Bien que ce ne soit pas la façon la plus ingénieuse de le faire. Cela fonctionne ¯ \ _ (ツ) _ / ¯

Downgoat
la source
J'aime la façon dont cela est signalé comme post de faible qualité. : P
Denker
1
@DenkerAffe probablement pour être court
Downgoat
1
Une raison d'utiliser JavaScript? Vous auriez pu le jouer à un personnage dans une autre langue: P
ghosts_in_the_code
@ghosts_in_the_code fixe
Downgoat
9

Pyth, 34,16% (297 octets)

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

(notez que certaines lignes se terminent par des espaces)

Je suis allé avec l'option la plus simple à laquelle je pouvais penser: vérifiez une liste de modèles et dès que vous trouvez une correspondance, sortez le candidat correspondant. Si tout le reste échoue, sortez le candidat le plus probable à partir du reste. Après cela, il s'agit de regrouper autant de données en 300 octets que possible.

FNc"<data>"bI}tNrzZhNB

Panne:

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.

D'où viennent donc ces données? Eh bien, la structure est simplement:

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

(avec une entrée à la fin sans phrase pour agir comme solution de repli finale)

Mais pourquoi ces éléments particuliers? J'ai écrit un programme C ++ pour analyser l'ensemble de données fourni (avec un nettoyage manuel des sauts de ligne d'abord pour rendre la structure cohérente). Il examine toutes les sous-chaînes ("jetons") dans chaque citation (1-16 caractères), puis vérifie à plusieurs reprises le jeton qui donne le plus d'avantages pour aller ensuite dans la liste. Une fois qu'un modèle est dans la liste, supprimez toutes les citations qui le correspondent et répétez (cela devient un peu plus compliqué de le garder rapide, mais c'est l'essentiel). Le code est probablement trop long pour être inclus ici, mais je pourrais le mettre sur github plus tard (quand je l'aurai nettoyé un peu).

J'ai essayé quelques systèmes de notation. À la fin, je suis allé avec celui-ci:

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

Une approche plus stricte consistant à n'autoriser que les nouveaux éléments qui n'introduisent pas de réponses incorrectes semble être bloquée à environ 20-25%, nécessitant beaucoup de modèles pour augmenter. Cette approche plus floue fait beaucoup mieux et peut toujours atteindre une précision de ~ 80% (avec 550 éléments). Le score soumis a 38 éléments, ce qui était le plus que je pouvais tenir dans la limite de 300 caractères.

Le résultat de 34% provient en fait d'un programme de test C ++ qui effectue les mêmes étapes. Cela devrait correspondre, mais je n'ai pas de faisceau de test Pyth pour le vérifier.

C'est la première fois que j'utilise Pyth, donc j'imagine que d'autres octets pourraient être séparés, permettant un peu plus de données.

Dave
la source
4
De plus, je sais maintenant que Sanders aime parler du secrétaire Clinton, Clinton est obsédé par le sénateur Sanders, Kasich aime l'Ohio, Cruz mentionne toujours Donald Trump, Rubio est obsédé par les siècles, Carson a tout le "fait [s] de l'affaire", et Trump adore totalement dire "totalement". Cela ressemble aux débuts d'un générateur de bingo politique. Je vais devoir l'essayer sur certaines personnalités britanniques…
Dave
Je pense que vous pourriez économiser quelques octets ici en emballant la chaîne avec .".
lirtosiast
8

Javascript, 32,87%

299 caractères:

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

Stratégie:

J'ai fait une recherche de force bruce sur les segments de mots à inclure dans un "hachage". Ensuite, une recherche de chaîne se produit avec ce hachage de manière à choisir le candidat le plus probable pour ce hachage.

Le code lui-même:

// 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

Ceci est ma toute première soumission de code de golf, donc les suggestions sont les bienvenues :)

Ru Hasha
la source
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]]&

Il compte les occurrences de mots clés communs propres à chaque candidat et affiche le numéro du candidat avec le score le plus élevé.

En gros, j'ai trouvé les mots les plus courants de tous les candidats

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;

et choisi les mots clés communs qui sont uniques pour chaque candidat.

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

Après avoir supprimé manuellement certains des mots clés, voici le tableau 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

Avec ces mots-clés, la longueur totale de la fonction est de 211 caractères. J'ai testé la fonction sur toutes les citations:

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

ce qui donne une précision de 23,7775%.

shrx
la source
3

Python, 25,677868%

Arbitrairement choisi quatre caractères différents qui seraient utilisés pour identifier les candidats. Chaque candidat reçoit un facteur de score par personnage basé sur une recherche en escalade que j'ai courue pendant quelques minutes pour finir à 25,68%.

Je suppose que cela prouve au moins que le concept est meilleur que de choisir un candidat les yeux bandés ou simplement de choisir Clinton, mais je serais intéressé de voir quelqu'un appliquer un meilleur algorithme de recherche, à la fois pour les facteurs et pour les caractères utilisés.

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
la source
1

Javascript, à déterminer

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)

Convertit chaque chaîne en un code de hachage, puis utilise des méthodes probabilistes pour déterminer le locuteur. Ce serait bien si quelqu'un avec une bonne configuration pouvait tester cela pour moi.

LegionMammal978
la source
Je compte environ 16,1%, mais je ne sais pas vraiment ce que cela fait. Que fait l'a + = a? 0: 1000? (J'ai dû remplacer l'alerte par un retour, donc je ne savais pas exactement quoi faire)
soktinpk
@soktinpk Désolé, cela a+=devait être une faute de frappe.
LegionMammal978