Kto to powiedział? Wybory prezydenckie w 2016 r

16

W tym wyzwaniu Twoim zadaniem jest napisanie programu zawierającego mniej niż 300 znaków, który wymaga krótkiego akapitu lub kilku zdań, które wypowiedział kandydat, i wypowiedz, kto to powiedział.

Wejście : Może być traktowane jako parametr funkcji, dane wejściowe do programu itp. Będzie to krótki akapit, odpowiednio interpunkcyjny.

Wyjście : Kandydat, że myślisz, że jest. To może być jeden z nich

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

Pominąłem nazwiska osób, które wypadły 1 marca. Możesz wypisać samą nazwę lub, wygodniej, numer, który odpowiada nazwie.

Punktacja: Twój wynik to odsetek poprawnych przypadków testowych. Najwyższy wynik wygrywa. Remisy (lub doskonałe wyniki) są dzielone według długości kodu, jak w golfie kodowym.

Przypadki testowe można pobrać z:

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

Kliknij każdą debatę, zarówno demokratyczną, jak i republikańską, która miała miejsce dotychczas (przed 1 marca). Każdy akapit jest przypadkiem testowym, chyba że „akapit” ma mniej niż 20 znaków.

Oto kod, który wyciąga przypadki testowe z określonej strony:

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

Następnie możesz zrobić, categ.SANDERSaby uzyskać listę wszystkich akapitów, które powiedział senator Sanders.

Możesz odrzucić wszystko, co nie zostało powiedziane przez wyżej wymienionych kandydatów (np. categ.BUSHLub categ.CHRISTIE).

Oto plik ze wszystkimi przypadkami testowymi: https://drive.google.com/file/d/0BxMn8--P71I-bDZBS2VZMDdmQ28/view?usp=sharing

Plik jest organizowany przez kandydata

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.

Przykładowym częściowym przesłaniem byłoby:

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

lub

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

Oto miejsce, w którym możesz przetestować rozwiązania javascript: https://jsfiddle.net/prankol57/abfuhxrh/

Kod używa parametru pdo reprezentowania frazy do sklasyfikowania. Przykładowy kod, który zdobędzie około 20% (zgadywanie dostanie około 11%):

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

Dokładnie o co pytam: napisz program / funkcję składającą się z mniej niż 300 znaków, który przyjmuje jako dane wejściowe wyrażenie wypowiedziane przez kandydata i zwraca jako wynik, który kandydat to powiedział. Twój wynik to odsetek przypadków testowych, które masz rację. Najwyższy wynik wygrywa.

Tak, wiem, że wiele linii ma [laughter]lub [cheering]w nich. Nie zostaną one usunięte. W najgorszym przypadku są to dodatkowe informacje, które można zignorować; w najlepszym razie są to dodatkowe informacje, z których możesz skorzystać (np. wymyśliłem to, ale może śmiech ludzi jest dowodem na to, że mówi Marco Rubio). Przypadki testowe są takie, jakie występują w pliku tekstowym.

soktinpk
źródło
1
Mam propozycję. Co powiesz na to, żebyś grał w golfa kodowego, ale musisz poprawnie uzyskać wszystkie cytaty? Możesz także chcieć, aby cytaty były znacznie krótsze, ponieważ rozwiązanie tego problemu jest nieco niedorzeczne.
Cyoce
2
@Cyoce poprawne wykonanie wszystkich cytatów byłoby absurdalne (jak sądzę), biorąc pod uwagę samą liczbę cytatów.
soktinpk
1
Sprytny pomysł na wyzwanie może jednak wymagać dopracowania. Czy zastanawiałeś się nad publikowaniem postów w piaskownicy?
Ashwin Gupta
1
Jakie jest kryterium wygranej? (A jak myślisz, dlaczego nikt nie uzyska idealnego wyniku?)
Peter Taylor
2
Podane przez ciebie dane źródłowe są nieco nieporządne (trudne do automatycznego przeanalizowania), co moim zdaniem odbiera trochę ducha wyzwania. Zrobiłem oczyszczoną wersję, która używa jednej linii na cytat, z pustą linią oddzielającą następną nazwę kandydata. Jest to o wiele łatwiejsze do przeanalizowania w większości języków. Przesłałem go tutaj: drive.google.com/file/d/0B3uyVnkMpqbVSnVrZkVwTUhDODg (poza zmianą nowego wiersza pozostawiłem dane nietknięte. Obejmuje to coś, co wygląda na problem z kodowaniem dla -)
Dave

Odpowiedzi:

14

Polyglot, ~ 18,6%

Działa to w: Cjam, Pyth, TeaScript, Japt, Seriously, 05AB1E, GolfScript, Jelly i prawdopodobnie wielu innych.

6

Daje to Hillary dla wszystkich danych wejściowych. To dlatego, że Hillary powiedziała najwięcej. Chociaż nie jest to najbardziej pomysłowy sposób na zrobienie tego. Działa ¯ \ _ (ツ) _ / ¯

Downgoat
źródło
Podoba mi się, jak to jest oznaczane jako post niskiej jakości. : P
Denker
1
@DenkerAffe prawdopodobnie za krótki
Downgoat
1
Czy jest jakiś powód do korzystania z JavaScript? Mogłeś grać w golfa do jednej postaci w innym języku: P
ghosts_in_the_code
@ghosts_in_the_code naprawiono
Downgoat
9

Pyth, 34,16% (297 bajtów)

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

(zauważ, że niektóre linie kończą się spacjami)

Wybrałem najprostszą opcję, jaką mogłem wymyślić: sprawdź listę wzorców i jak tylko znajdziesz dopasowanie, wypisz odpowiedniego kandydata. Jeśli wszystko inne zawiedzie, wypisz najbardziej prawdopodobnego kandydata z reszty. Następnie chodzi o to, aby wcisnąć jak najwięcej danych w 300 bajtów, jak to możliwe.

FNc"<data>"bI}tNrzZhNB

Awaria:

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.

Skąd więc te dane? Struktura jest po prostu:

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

(z wpisem na końcu bez frazy, która działałaby jako ostatnia awaria)

Ale dlaczego te konkretne przedmioty? Napisałem program C ++ do analizy dostarczonego zestawu danych (najpierw z pewnym ręcznym czyszczeniem nowych linii, aby struktura była spójna). Sprawdza wszystkie podciągi („tokeny”) w każdym cytacie (1-16 znaków), a następnie wielokrotnie sprawdza token, który daje najwięcej korzyści, aby przejść dalej na liście. Gdy wzór znajdzie się na liście, usuń wszystkie cudzysłowy, które pasują do niego, i powtórz (staje się to nieco bardziej skomplikowane, aby utrzymać go szybko, ale to jest podstawa). Kod jest prawdopodobnie zbyt długi, aby go tu umieścić, ale mogę go później umieścić na github (kiedy go trochę wyczyściłem).

Wypróbowałem kilka systemów oceniania. W końcu poszedłem z tym:

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

Bardziej rygorystyczne podejście polegające na dopuszczaniu tylko nowych elementów, które nie wprowadzają niepoprawnych odpowiedzi, wydawało się blokować na poziomie około 20–25%, wymagając dużo wzorów, aby przejść wyżej. To bardziej podejrzane podejście działa znacznie lepiej i wciąż może osiągnąć ~ 80% dokładności (przy 550 przedmiotach). Przesłany wynik składa się z 38 elementów, co najbardziej pasowało do limitu 300 znaków.

Wynik 34% faktycznie pochodzi z testowego programu C ++, który wykonuje te same kroki. Powinien pasować, ale nie mam uprzęży testowej Pyth, aby to sprawdzić.

Po raz pierwszy korzystam z Pyth, więc wyobrażam sobie, że można napisać więcej bajtów, pozwalając na nieco więcej danych.

Dave
źródło
4
Teraz też wiem, że Sanders uwielbia rozmawiać o sekretarce Clinton, obsesję Clintona na punkcie senatora Sandersa, Kasich uwielbia Ohio, Cruz zawsze wspomina o Donaldzie Trumpie, Rubio ma obsesję na punkcie Wieków, Carson ma wszystkie „fakty”, i Trump całkowicie uwielbia mówić „całkowicie”. To wydaje się być początkiem generatora bingo politycznego. Będę musiał spróbować z niektórymi osobistościami z Wielkiej Brytanii…
Dave,
Myślę, że możesz tutaj zaoszczędzić trochę bajtów, pakując ciąg .".
lirtosiast
8

JavaScript, 32,87%

299 znaków:

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

Strategia:

Przeprowadziłem poszukiwanie siły Bruce'a, które segmenty słowa należy uwzględnić w „haszu”. Następnie z tym skrótem odbywa się wyszukiwanie ciągów w taki sposób, że wybiera najbardziej prawdopodobnego kandydata na ten skrót.

Sam kod:

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

To jest mój pierwszy kod golfowy, więc sugestie są mile widziane :)

Ru Hasha
źródło
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]]&

Liczy występowanie typowych słów kluczowych unikalnych dla każdego kandydata i podaje liczbę kandydatów z najwyższym wynikiem.

Zasadniczo znalazłem najczęstsze słowa wszystkich kandydatów

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;

i wybraliśmy wspólne słowa kluczowe, które są unikalne dla każdego kandydata.

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

Po ręcznym usunięciu niektórych słów kluczowych jest to tabela końcowa:

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

Przy tych słowach kluczowych całkowita długość funkcji wynosi 211 znaków. Przetestowałem tę funkcję dla wszystkich cytatów:

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

co daje dokładność 23,7775%.

shrx
źródło
3

Python, 25,677868%

Arbitralnie wybrałem cztery różne postacie, które zostaną użyte do identyfikacji kandydatów. Każdy kandydat otrzymuje współczynnik punktacji na postać na podstawie poszukiwań podczas wspinaczki, którą prowadziłem przez kilka minut, aby uzyskać wynik 25,68%.

Przypuszczam, że to przynajmniej dowodzi, że koncepcja jest lepsza niż wybieranie kandydata z zasłoniętymi oczami lub po prostu wybieranie Clintona, ale byłbym zainteresowany, aby ktoś zastosował lepszy algorytm wyszukiwania, zarówno pod względem czynników, jak i użytych znaków.

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
źródło
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)

Konwertuje każdy ciąg znaków na kod skrótu, a następnie używa metod probabilistycznych w celu ustalenia głośnika. Byłoby miło, gdyby ktoś z dobrą konfiguracją mógł to dla mnie przetestować.

LegionMammal978
źródło
Liczę około 16,1%, ale tak naprawdę nie jestem pewien, co to robi. Co robi a + = a? 0: 1000? (Musiałem zastąpić ostrzeżenie zwrotem, więc nie byłem pewien, co dokładnie zrobić)
soktinpk
@soktinpk Przepraszamy, a+=musiała to być literówka.
LegionMammal978