Wer hat das gesagt? Präsidentschaftswahlen 2016

16

In dieser Herausforderung besteht Ihre Aufgabe darin, ein Programm mit weniger als 300 Zeichen zu schreiben , das einen kurzen Absatz oder ein paar Sätze enthält, die ein Kandidat gesagt hat, und denjenigen auszugeben, der es gesagt hat.

Eingabe : Kann als Parameter für eine Funktion, als Eingabe für ein Programm usw. verwendet werden. Es handelt sich um einen kurzen Absatz mit korrekter Interpunktion.

Ausgabe : Der Kandidat, den Sie für richtig halten. Dies könnte einer von

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

Ich habe die Namen der Personen gestrichen, die zum 1. März ausgestiegen sind. Sie können den Namen selbst oder bequemer die Nummer ausgeben, die dem Namen entspricht.

Bewertung: Ihre Bewertung ist der Prozentsatz der Testfälle, die Sie richtig erhalten. Höchste Punktzahl gewinnt. Gleichstände (oder perfekte Punkte) werden wie bei einem Codegolf nach Codelänge getrennt.

Die Testfälle können entnommen werden aus:

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

Klicken Sie auf jede Debatte, sowohl demokratische als auch republikanische, die bisher (vor dem 1. März) stattgefunden hat. Jeder Absatz ist ein Testfall, es sei denn, der "Absatz" ist kürzer als 20 Zeichen.

Hier ist Code, der die Testfälle von einer bestimmten Seite abruft:

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

Sie können dann tun categ.SANDERS, um eine Liste aller Absätze zu erhalten, die Senator Sanders gesagt hat.

Sie können alles verwerfen, was von den oben aufgeführten Kandidaten (z . B. categ.BUSHoder categ.CHRISTIE) nicht gesagt wird .

Hier ist die Datei mit allen Testfällen: https://drive.google.com/file/d/0BxMn8--P71I-bDZBS2VZMDdmQ28/view?usp=sharing

Die Datei ist nach Kandidaten organisiert

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.

Ein Beispiel für eine teilweise Einreichung wäre:

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

oder

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

Hier können Sie Javascript-Lösungen testen: https://jsfiddle.net/prankol57/abfuhxrh/

Der Code verwendet den Parameter p, um die zu klassifizierende Phrase darzustellen. Beispielcode, der ungefähr 20% ergibt (eine Schätzung würde ungefähr 11% ergeben):

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

Genau das, was ich frage: Schreiben Sie ein Programm / eine Funktion in weniger als 300 Zeichen, das / die eine Phrase, die ein Kandidat gesagt hat, als Eingabe verwendet und als Ausgabe zurückgibt, welche Kandidatin es gesagt hat. Ihre Punktzahl ist der Prozentsatz der Testfälle, die Sie richtig machen. Höchste Punktzahl gewinnt.

Ja, ich weiß, dass viele Zeilen [laughter]oder [cheering]in ihnen haben. Diese werden nicht entfernt. Im schlimmsten Fall handelt es sich um zusätzliche Informationen, die Sie ignorieren können. Im besten Fall handelt es sich um zusätzliche Informationen, die Sie verwenden können (z. B. habe ich mir das ausgedacht, aber vielleicht ist das Gelächter ein Beweis dafür, dass Marco Rubio spricht). Die Testfälle sind so, wie sie in der Textdatei angezeigt werden.

soktinpk
quelle
1
Ich habe einen Vorschlag. Wie wäre es, wenn Sie Code-Golf spielen, aber alle Anführungszeichen stimmen müssen? Vielleicht möchten Sie auch die Anführungszeichen viel kürzer machen, da dies ein wenig lächerlich ist, um es so zu lösen, wie es ist.
Cyoce
2
@Cyoce, der alle Anführungszeichen richtig erhält, würde (ich denke) angesichts der bloßen Zahl von Anführungszeichen lächerlich sein.
Soktinpk
1
Clevere Herausforderungsidee, muss aber möglicherweise verfeinert werden. Haben Sie darüber nachgedacht, Feedback in Sandbox zu veröffentlichen?
Ashwin Gupta
1
Was ist das Gewinnkriterium? (Und warum glaubst du, dass niemand ein perfektes Ergebnis erzielt?)
Peter Taylor
2
Die von Ihnen bereitgestellten Quelldaten sind ein wenig unübersichtlich (schwer automatisch zu analysieren), was meiner Meinung nach den Geist der Herausforderung einschränkt. Ich habe eine bereinigte Version erstellt, in der eine Zeile pro Anführungszeichen verwendet wird, wobei der nächste Kandidatenname durch eine Leerzeile getrennt wird. Dies ist in den meisten Sprachen viel einfacher zu analysieren. Ich habe es hier hochgeladen: drive.google.com/file/d/0B3uyVnkMpqbVSnVrZkVwTUhDODg ( abgesehen vom Ändern von Zeilenumbrüchen habe ich die Daten unberührt gelassen. Dies schließt ein, wie es aussieht, Codierungsproblem für -)
Dave

Antworten:

14

Mehrsprachig, ~ 18,6%

Dies funktioniert in: Cjam, Pyth, TeaScript, Japt, Seriously, 05AB1E, GolfScript, Jelly und wahrscheinlich vielen anderen.

6

Dies gibt Hillary für alle Eingänge aus. Dies ist, weil Hillary am meisten sagte. Dies ist zwar nicht der genialste Weg, dies zu tun. Es funktioniert ¯ \ _ (ツ) _ / ¯

Downgoat
quelle
Mir gefällt, wie dieser Beitrag als qualitativ minderwertig gekennzeichnet wird. : P
Denker
1
@DenkerAffe wahrscheinlich, weil er kurz ist
Downgoat
1
Gibt es einen Grund für die Verwendung von JavaScript? Du hättest es auf ein Zeichen in einer anderen Sprache
reduzieren können
@ghosts_in_the_code behoben
Downgoat
9

Pyth, 34,16% (297 Byte)

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

(Beachten Sie, dass einige Zeilen in Leerzeichen enden)

Ich habe die einfachste Option gewählt, die mir in den Sinn gekommen ist: Überprüfen Sie eine Liste von Mustern, und geben Sie den entsprechenden Kandidaten aus, sobald Sie eine Übereinstimmung finden. Wenn alles andere fehlschlägt, geben Sie den wahrscheinlichsten Kandidaten aus dem Rest aus. Danach geht es darum, so viele Daten wie möglich auf 300 Byte zu komprimieren.

FNc"<data>"bI}tNrzZhNB

Nervenzusammenbruch:

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.

Woher kommen diese Daten? Nun, die Struktur ist einfach:

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

(mit einem Eintrag am Ende ohne Phrase, der als endgültiger Fallback fungiert)

Aber warum gerade diese Gegenstände? Ich habe ein C ++ - Programm geschrieben, um den bereitgestellten Datensatz zu analysieren (mit manueller Bereinigung der Zeilenumbrüche, um die Struktur konsistent zu machen). Es prüft alle Teilzeichenfolgen ("Token") in jedem Anführungszeichen (1-16 Zeichen) und sucht dann wiederholt nach dem Token, das den größten Nutzen bringt, um als nächstes in die Liste aufgenommen zu werden. Sobald sich ein Muster in der Liste befindet, entfernen Sie alle passenden Anführungszeichen und wiederholen Sie den Vorgang (es wird etwas komplizierter, es schnell zu halten, aber das sind die Grundlagen). Der Code ist wahrscheinlich zu lang, um ihn hier aufzunehmen, aber ich könnte ihn später auf Github setzen (wenn ich ihn ein wenig aufgeräumt habe).

Ich habe ein paar Bewertungssysteme ausprobiert. Am Ende ging ich mit diesem:

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

Ein strengerer Ansatz, nur neue Elemente zuzulassen, die keine falschen Antworten einbringen, schien bei etwa 20-25% hängen zu bleiben, und es waren viele Muster erforderlich , um höher zu werden. Dieser unschärfere Ansatz funktioniert viel besser und erreicht immer noch eine Genauigkeit von ~ 80% (bei 550 Elementen). Die eingereichte Partitur enthält 38 Elemente. Dies war die maximale Anzahl von 300 Zeichen.

Das 34% -Ergebnis stammt tatsächlich aus einem C ++ - Testprogramm, das dieselben Schritte ausführt. Es sollte passen, aber ich habe kein Pyth-Testgeschirr, mit dem ich es überprüfen kann.

Dies ist das erste Mal, dass ich Pyth verwende, also stelle ich mir vor, dass ein paar Bytes mehr herausgedrückt werden könnten, um ein bisschen mehr Daten zu ermöglichen.

Dave
quelle
4
Auch ich weiß jetzt, dass Sanders es liebt, über Sekretär Clinton zu sprechen, Clinton ist besessen von Senator Sanders, Kasich liebt Ohio, Cruz erwähnt immer Donald Trump, Rubio ist besessen von Jahrhunderten, Carson hat alle "Tatsachen" und Trump liebt es total, "total" zu sagen. Das fühlt sich an wie die Anfänge eines Politik-Bingo-Generators. Ich muss es mit einigen britischen Persönlichkeiten versuchen…
Dave
Ich denke, Sie könnten hier ein paar Bytes sparen, indem Sie den String mit packen .".
Lirtosiast
8

Javascript, 32,87%

299 Zeichen:

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

Strategie:

Ich habe eine Bruce Force-Suche durchgeführt, um herauszufinden, welche Wortsegmente in einem "Hash" enthalten sein sollen. Dann wird mit diesem Hash ein String-Lookup durchgeführt, bei dem der wahrscheinlichste Kandidat für diesen Hash ausgewählt wird.

Der Code selbst:

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

Dies ist meine allererste Code-Golf-Einsendung, daher sind Vorschläge willkommen :)

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

Es werden die Vorkommen gemeinsamer Stichwörter gezählt, die für jeden Kandidaten eindeutig sind, und die Nummer des Kandidaten mit der höchsten Punktzahl ausgegeben.

Grundsätzlich habe ich die häufigsten Wörter aller Kandidaten gefunden

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;

und wählte die gemeinsamen Schlüsselwörter, die für jeden Kandidaten eindeutig sind.

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

Nach dem manuellen Löschen einiger Schlüsselwörter ist dies der letzte Tisch:

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

Mit diesen Schlüsselwörtern beträgt die Gesamtfunktionslänge 211 Zeichen. Ich habe die Funktion über alle Zitate getestet:

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

Dies ergibt eine Genauigkeit von 23,7775%.

shrx
quelle
3

Python, 25.677868%

Wählen Sie willkürlich vier verschiedene Zeichen aus, mit denen die Kandidaten identifiziert werden. Jeder Kandidat erhält einen Bewertungsfaktor pro Charakter, der auf einer Bergsteiger-Suche basiert, die ich einige Minuten lang durchgeführt habe, um am Ende 25,68% zu erreichen.

Ich nehme an, dass dies zumindest beweist, dass das Konzept besser ist, als einen Kandidaten mit verbundenen Augen oder nur Clinton auszuwählen, aber ich wäre daran interessiert, jemanden zu sehen, der einen besseren Suchalgorithmus anwendet, sowohl für die Faktoren als auch für die verwendeten Zeichen.

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

Konvertiert jeden String in einen Hash-Code und verwendet dann probabilistische Methoden, um den Sprecher zu bestimmen. Wäre nett, wenn jemand mit einem guten Setup dies für mich testen könnte.

LegionMammal978
quelle
Ich zähle ungefähr 16,1%, aber ich bin nicht wirklich sicher, was es tut. Was macht das a + = a? 0: 1000? (Ich musste die Warnung durch eine Rückgabe ersetzen, damit ich nicht genau
wusste
@soktinpk Sorry, das a+=muss ein Tippfehler gewesen sein.
LegionMammal978