Lassen Sie uns einige Bücher nach ihren Umschlägen beurteilen

47

Jeder weiß, dass der Inhalt die Frage stellt. Aber ein guter Titel hilft auch, und das ist das Erste, was wir sehen. Es ist Zeit, diesen ersten Eindruck in ein Programm zu verwandeln und herauszufinden, welche Arten von Titeln mehr positive Stimmen erhalten.

Sie werden hiermit aufgefordert, ein Programm oder eine Funktion zu schreiben, die den Titel einer PPCG-Frage als Eingabe verwendet und eine Vorhersage der Punktzahl zurückgibt.

Beispielsweise könnten Sie Counting Grains of Riceals Eingabe empfangen und 59in diesem Fall versuchen, etwas zurückzugeben, das in der Nähe der Punktzahl liegt . Nicht ganzzahlige Vermutungen sind in Ordnung, Vermutungen bei oder darunter -20jedoch nicht.

Hier sind die Daten zum Testen und Bewerten:

http://data.stackexchange.com/codegolf/query/244871/names-and-upvotes

Bewertung: Ihr Programm wird für jede Frage im Verlauf dieser Site (PPCG) ausgeführt, wobei geschlossene Fragen nicht berücksichtigt werden. Die Funktion ln(score + 20)wird dann auf jede Punktzahl und auf jede Vermutung angewendet. Der quadratische Mittelwertfehler zwischen den beiden resultierenden Wertesätzen ist Ihre Punktzahl. Weniger ist besser.

Zum Beispiel würde ein Programm, das jedes Mal 0 erraten hat, 0,577 Punkte erzielen, während eines, das jedes Mal 11 erraten hat, 0,362 Punkte erzielen würde.

Bitte berechnen Sie Ihre Punktzahl und fügen Sie sie in den Titel Ihrer Antwort ein. Bitte geben Sie auch die Vorhersage Ihres Programms an, wie viele Upvotes diese Frage erhalten wird.

Beschränkungen:

  • Um eine übermäßige Kodierung zu vermeiden, dürfen nicht mehr als 1000 Zeichen eingegeben werden.

  • Muss auf einem vernünftigen Computer in weniger als einer Minute mit dem gesamten oben genannten Datensatz ausgeführt werden.

  • Standardlücken sind geschlossen.


Hier ist ein in Python geschriebener Tester, der Sie verwenden und / oder Unklarheiten beseitigen kann:

import sys
import math
import csv

scores_dict = {}

with open(sys.argv[1], 'r') as csv_file:
    score_reader = csv.reader(csv_file)
    for score, title in score_reader:
        if score == 'Score':
            continue
        scores_dict[title] = int(score)

def rate_guesses(guesser):
    def transform(score):
        return math.log(score + 20) if score > -20 else 0
    off_by_total = 0
    lines_count = 0
    for title in scores_dict:
        guessed_score = guesser(title)
        real_score = scores_dict[title]
        off_by_total += (transform(real_score) - transform(guessed_score)) ** 2
    return (off_by_total/len(scores_dict)) ** .5

def constant11(title):
    return 11

print(rate_guesses(constant11))
isaacg
quelle
19
Gute Idee, aber es ist eine Schande, dass der Datensatz nicht stabil ist und die Ergebnisse nach einer Weile ungültig werden. Es gibt auch eine kleine Möglichkeit der strategischen Abstimmung: Jeder, der diese Frage beantwortet und in derselben Woche ein Vox-Populi-Abzeichen erhält, sollte mit Argwohn betrachtet werden! ;-)
Level River St
1
Schließt der Titel Dinge wie [closed]und [on hold]gegebenenfalls ein oder aus ?
es1024
4
@steveverrill Nun, die Kehrseite davon ist, wie die Zeit fortschreitet, werden wir in der Lage sein, zu sehen, ob die Programme auf zukünftigen und vergangenen Posts gut abschneiden.
isaacg
6
Es ist schwierig, Hardcodierung zu besiegen. Jede hartcodierte Frage mit der höchsten Bewertung kann bis zu 0,4 Punkte reduzieren. Und es scheint auch nicht viel gemeinsames Muster zu geben, haha. Ich gehe davon aus, dass die Antworten nur darüber konkurrieren werden, wie viele hartcodierte Ergebnisse in 1000 Bytes passen.
Nur die Hälfte des
5
Sie sollten nicht den gesamten Fragenkatalog als Testsatz verwenden. Sie sollten eine bestimmte Zahl (10% -20%) nach dem Zufallsprinzip vorwählen und als Test-Set definieren (aber niemandem mitteilen, was das ist). Es ist viel einfacher, einen Algorithmus zu erstellen, der den Verlauf der Vergangenheit vorhersagt, als einen, der einen zukünftigen Vorhersagewert hat (dh einen, der für eine bestimmte Teilmenge gut funktioniert). (Es wäre sogar besser, diese 10% von dem zu entfernen, was wir überhaupt sehen können, aber das würde nicht wirklich gut funktionieren.)
Joe,

Antworten:

9

Python 2, 991 Zeichen, Ergebnis 0.221854834221, Vorhersage 11

import base64
e={}
d=base64.decodestring('vgAcRAEVDAIsqgQYalYaggcjQKwVXAoZWAsYQg0Ckg4VlWEX9hEDRhMe0hckCBkeuhsW3CAWQiEm\nSiMZMiwgTDAZZjIcSLMZfDQDnjwCe2AVaEQCYWEBIEgnDEoXzk0e3lQb5FYVKlkVZlwB+F0XwmI/\nGmRcuGUXWmYdVGkbzmwafG8eaHMdInkggHonRn5sKoMXgIkpbowVOI4cNJAubpQdYpcydJgVypkA\nZpweMp8ZsqEcRKMghKQYkKVPPXEWMqkWHKwbjrEdzLIBNLMf1LQivrYC99UV9rxNRsABNMEiPzob\npc0ActAhn3gcrNUZYNcWYNov/t8VgOEXAuMYqOUWsqUiCPIefPWNbvtKevwWvP0Cl9UsjQMdWwQb\nfQdpJQgWYwkCZRLBjxMWWdkqHRkWNxwB6x8p2SEZyyICSyYcgysaOS0CUy8hezAaGeEVpTRQ3zUz\nZzkZRzohizwwST4c8UAdF0OqG9AXIuEYYRN6208nU1AktVEVJ1IVWeMkIVQXdY4D2VYYD/cYb1om\nG1xA0zoY3uUaRWAhWpBSHWUXQTxGe+cad20CO3AZX3EBw3IiMXcef3gecXsVGXwhw30VbX4W24BD\n6qyQ45YaYYgZ4YobbYwauY4bMY82HZEdO5YmQ5cV35sVxaMbY6gYNas576ws+bADO7QpN7hdLJ8B\n4Eoks8EYX8VU68cYWfcar82QOdAaxdEfQ9UiW/kXL9k2ddwCW90m694enqUCkeEBE+IYWvsfA1FC\nJ+spMVIjhe4WEP0fAfYax/c3MfgbgfkqP/0DLf4V\n')
for i in range(0,600,3):
 e[ord(d[i])*256+ord(d[i+1])]=ord(d[i+2])*2-8
def p(t):
 return e.get(hash(t)%256**2,11)

Erläuterung:

Dies ist eine unverschämte Hardcodierung, die jedoch effizient durchgeführt werden muss.

Vorverarbeitung:

In einem separaten Code habe ich jeden Titel auf einen Wert zwischen 0 und 256 ^ 2-1 gehasht. Nennen wir diese Wertefächer. Für jeden Behälter habe ich die durchschnittliche Punktzahl berechnet. (Der Durchschnitt wird benötigt, da für einen kleinen Teil der Bins Kollisionen vorliegen - mehr als 1 Titel-Hash für denselben Bin. Bei der überwiegenden Mehrheit wird jeder Titel einem eigenen Bin zugeordnet.)

Die Idee hinter dem 2-Byte-Code für jeden Titel ist, dass 1 Byte nicht ausreicht - wir bekommen zu viele Kollisionen, sodass wir nicht genau wissen, welche Punktzahl jedem 1-Byte-Bin zugewiesen werden soll. Bei 2-Byte-Bins gibt es jedoch fast keine Kollisionen, und wir erhalten effektiv eine 2-Byte-Darstellung jedes Titels.

Dann zählt die Behälter - die Verstärkung in der Partitur berechnen , wenn wir dieses Fach seinen berechneten Wert zuweisen, anstatt nur 11. den Top - N - Bins Nehmen Sie erraten, und Code sie in einen String (die in dem eigentlichen Code ist d).

Die Kodierung: Der Schlüssel der Bin wird mit 2 Bytes kodiert. Der Wert wird mit 1 Byte codiert. Ich habe Werte zwischen -8 und 300 + gefunden, musste also ein wenig drücken, um 1 Byte zu erhalten: x -> (x + 8) / 2.

Tatsächlicher Code:

lese d als Byte-Triplets und decodiere die oben erläuterte Codierung. Wenn ein Titel angegeben wird, berechnen Sie seinen Hash (Modulo 256 ^ 2). Wenn dieser Schlüssel im Diktat gefunden wird, geben Sie den Wert zurück, dem er zugeordnet ist. Andernfalls geben Sie 11 zurück.

Ofri Raviv
quelle
3
Ein Vorschlag: Die durchschnittliche Punktzahl ist nicht so gut. Schauen Sie sich die Bewertungsfunktion für Herausforderungen an, sie ist nicht linear.
Deduplizierer
1
@ Deduplicator Danke, das habe ich gemerkt, nachdem ich fertig war. Für 99% der Behälter gibt es keine Kollisionen. Der Durchschnitt ist also nur die Punktzahl des einzelnen Titels, der diesem Behälter zugeordnet ist.
Ofri Raviv
16

Javascript ES6

Bewertung: 0.245663
Länge: 1000 Bytes
Vorhersage: 5

(Ich denke, die Frage ist auf eine unerwartete Lawine von Abstimmungen zurückzuführen.: P)

Minimiert

E="ABCDEFGHIJKLMNOPQRSTUVWXYZ";E=E+E.toLowerCase()+"0123456789!@#$%;*()";P="RCRHIFMGPGIDQKHMJLLRMLFJGKHEqHPOgJNKGPCHPJNUPOSGJQKKKMELMIJHLKIKNcKDOfSJLFHDILGKIOUKLMLLKMKIHGHJGIIJDGJKIHIIFIGMTIHFJMIKDJGQJKGMKJHPRJPLMGIOPIIIIPBYFMGLEIKIMMRUKFLFGJFKFTHPFODEQTGTHKIJDHNJGDGiHKNYLHHDLJHGILOEViKNEKGQZfHJMIISIJFRHKLJMLPIFJILKKKJKKJESHNLLIKIGKGJJJHKJRGULLSLRONJNEeLKIQGGPQIHPLEIHHIDXjQHNBKOGWWIENRbYoHINHNMKTNKHTGMIPXFJLLMLIHPPLDJJKFUMIQMOKJLJJKIJKNLHRILJIAIbJEZOGIELGHGLOINDPJMJeJWRIIJHSOZDOsOFRRIOIOTIJSGGJKFUIDOINGOcLQEJFEITLMNIIGIGIMG7LPSNLKVOKIFGHJITGOFUJIIRN";K={};"99r1501vz076mip077myv0733it280exx081gt9118i1g279dyx102uho203ejd07433z087uje097kdg1567ft2088rk275dmu1203ez106lih1763ei126f6q101aax084owh088aid161i9y179gvn236ptn3338vf132i55080fke101l4z3789ai281ulm081blm124euz074o5m07513z14117l095qdn092gl30757n5153".replace(/(...)(...)/g,(_,a,b)=>K[a]=1*b);D=40655;N=479;H=(s,T)=>(h=7,[...s].map(c=>h=~~(h*T+c.charCodeAt(0))),h);S=s=>(y=H(s,31),K[((y%D+D)%D).toString(36)]||E.indexOf(P[(H(s,48)%N+N)%N]));

Erweitert

E = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
E = E + E.toLowerCase() + "0123456789!@#$%;*()";
K = {};
P = "RCRHIFMGPGIDQKHMJLLRMLFJGKHEqHPOgJNKGPCHPJNUPOSGJQKKKMELMIJHLKIKNcKDOfSJL" +
    "FHDILGKIOUKLMLLKMKIHGHJGIIJDGJKIHIIFIGMTIHFJMIKDJGQJKGMKJHPRJPLMGIOPIIIIP" +
    "BYFMGLEIKIMMRUKFLFGJFKFTHPFODEQTGTHKIJDHNJGDGiHKNYLHHDLJHGILOEViKNEKGQZfH" +
    "JMIISIJFRHKLJMLPIFJILKKKJKKJESHNLLIKIGKGJJJHKJRGULLSLRONJNEeLKIQGGPQIHPLE" +
    "IHHIDXjQHNBKOGWWIENRbYoHINHNMKTNKHTGMIPXFJLLMLIHPPLDJJKFUMIQMOKJLJJKIJKNL" +
    "HRILJIAIbJEZOGIELGHGLOINDPJMJeJWRIIJHSOZDOsOFRRIOIOTIJSGGJKFUIDOINGOcLQEJ" +
    "FEITLMNIIGIGIMG7LPSNLKVOKIFGHJITGOFUJIIRN";

   ("99r1501vz076mip077myv0733it280exx081gt9118i1g279dyx102uho203ejd07433z087u" +
    "je097kdg1567ft2088rk275dmu1203ez106lih1763ei126f6q101aax084owh088aid161i9" +
    "y179gvn236ptn3338vf132i55080fke101l4z3789ai281ulm081blm124euz074o5m07513z" +
    "14117l095qdn092gl30757n5153").
        replace( /(...)(...)/g, (_,a,b) => K[a] = 1*b );

D = 40655;
N = 479;
H = (s,T) => (
    h = 7,
    [...s].map( c => h = ~~(h*T + c.charCodeAt(0)) ),
    h
);

S = s => (
    y = H( s, 31 ),
    K[((y%D + D)%D).toString( 36 )] || E.indexOf( P[(H( s, 48 )%N + N)%N] )
);

Die Funktion Sakzeptiert einen String (Titel) und gibt dessen Punktzahl zurück.

Hinweise zum Verhalten:

  • ≤ 70 Stimmen-Titel werden getrennt von> 70 Stimmen-Titeln behandelt
  • ≤ 70-Stimmen-Titel werden mithilfe eines hochentwickelten Algorithmus zur Optimierung des holonomischen Keyword-Tracking-Potenzials, der in keiner Weise einer String-Hash-Funktion ähnelt, in Bins sortiert
  • nach ein wenig glücklicher Überlegung stellt sich heraus, dass die optimale Schätzung für jede Bin einfach der geometrische Durchschnitt der (Stimmen + 20) für alle Titel in der Bin minus 20 ist
  • Die optimalen Schätzwerte für alle 479 Bins werden dann als 479-Zeichen-Base-70-Zeichenfolge codiert
  • Bei Titeln mit mehr als 70 Stimmen werden den Titeln eindeutige dreistellige Base-36-Codes zugewiesen, die mit einer hochmodernen Hashing-Technik erstellt wurden, die keine Kollisionen mit anderen Titeln mit mehr als 70 Stimmen und keine falschen Erkennungen von Titeln mit weniger als 70 Stimmen garantiert. Diese hochmoderne Technik ähnelt in keiner Weise dem Versuch, zufällige Lagerplatzzählungen durchzuführen, bis keine Kollisionen mehr auftreten.
  • Die> 70-Stimmen-Titelcodes und ihre Stimmenanzahl werden in einer Zeichenfolge (6 Bytes pro Titel) codiert, die in eine einfache Nachschlagetabelle konvertiert wird. Die Routine hat daher für alle Titel mit> 70 Stimmen den Fehler Null.
COTO
quelle
10

Python 2, Score = 0.335027, 999 Zeichen, Sagen Sie 11.34828 für diese Frage voraus

Nur um den Ball ins Rollen zu bringen. Das ist nirgends optimal.

Das ausgefallene SVM-Ding ist nur meine zufällige Idee und ich wollte es implementieren, also hier ist es. Es verbessert die Grundlinie um 0,02 Punkte, also bin ich damit zufrieden. Aber um zu zeigen, dass der Großteil der Verbesserungen auf die harte Codierung der Eingabe zurückzuführen ist, habe ich auch einige Antworten hart codiert.

Ohne die Hardcodierung liegt der Wert bei 0,360 (und tatsächlich liegen alle Vorhersagen bei 11, haha).

Ich benutze scikit-learn und nltk

import sys
import math
import csv
from sklearn.feature_extraction.text import TfidfVectorizer as TV
from sklearn.svm import SVR
from nltk.stem.porter import PorterStemmer as PS
sd = {}
lr = None
tv = None
with open(sys.argv[1], 'r') as cf:
    sr = csv.reader(cf)
    for sc, t in sr:
        if sc == 'Score':
            continue
        sd[t] = int(sc)
ts,scs = zip(*sd.items())
s = PS()
def analyzer(st):
    r = []
    for word in st.split():
        if word.isdigit():
            r.append('<NUM>')
        elif not word.isalnum():
            r.append('<PUNCT>')
        else:
            r.append(s.stem(word.lower()))
    return r
tv = TV(min_df=25, stop_words='english', analyzer=analyzer)
ti = tv.fit_transform(ts)
lr = SVR()
lr.fit(ti, scs)
d={'4 w':378,'y 42':333,'eeta':280,'an Got':279,'s 2 ':275,"e I'":208,'r CP':203,'? No':179,'B.O':156}
def c(t):
    for s in d.keys():
        if s in t:
            return d[s]
    t = tv.transform([t])
    r = lr.predict(t)[0]+1.5
    return r
nur zur Hälfte
quelle
Ich bin mir nicht sicher, ob ich das verstehe - Sie haben die Noten aus einer externen Datei gelesen? Warum also nicht einfach sd [t] vorhersagen? Dies würde eine Punktzahl von 0 ergeben ...
Ofri Raviv
2
Weil das keinen Spaß machen würde = p
halbe
4

Python 2, 986 Zeichen, 0,3480188 Punkte, vorhergesagt 12

M,S=14.29,23.02
D=lambda x:[ord(y)-32 for y in x]
w='fiLoNoNuMiNoTiMoShOnLoGoLeThRantexgensuBaSqUnInPeReGaMuLinprOuThInThEvEnClOpExPyThADdiSoLiSiMaTrEqUsImAsCoManstARrePoWoReawhapoLandradeTyPaLOsoReCreprediVeReSpebeTiPrImPladaTrihelmakwhicolpaReValpaTrafoROsoumovfinfunpuzyoufaSeQuiwhecoDeChagivcouchehanpoStrdiGraconjavwricalfrowitbinbrafrabuipoi'
for i in range(26):w=w.replace(chr(65+i),chr(97+i)*2)
w=[w[i:i+3]for i in range(0,372,3)]
m=D("(+),+)+=*...+..++'(*)5)/2)*43++16+0,+33*4*/(0.'+>-)+13+(2?8+6;,3;43+4(+.('(,.*.*+56+6)0((++(B,))+E0,-7/)/*++),+***)2+(3(.*)'")
s=D("))'B)'*j+:51(*3+0')+)^'/<-+MG,-1=),-0:A+T&J&K1%,O*()4Y-%:_A.=A*C]MJ-N%)5(%%-0+).*3Q(M&0'%(+$p*)()a8:-T?%5(-*'/.'+)+@,'J&1'&&")
def G(x,m,s):s=s or 1e-9;return(.4/s)*(2.78**(-(x-m)**2./(2*s*s)))
d={w[i]:(m[i],s[i])for i in range(124)}
def Z(t,c):
 p=1
 for W in t.split():
  if len(W)>3:
   W=W[:3].lower()
   if W in d:p*=G(c,*d[W])
 return p*G(c,M,S)
def J(t):return max([(Z(t,r),r)for r in range(-9,99)])[1]

Die relevante Funktion ist J.

Das Programm ist im Wesentlichen Naive Bayes und verwendet Titelwörter als Funktionen, ist aber dank der Zeichenbeschränkung extrem eingeschränkt. Wie eingeschränkt? Gut...

  • Für jeden Titel konvertieren wir in Kleinbuchstaben und betrachten nur Wörter mit einer Länge von mindestens 4 Buchstaben. Dann nehmen wir die ersten drei Buchstaben jedes dieser Wörter als Merkmale. Wir überspringen die Stripping-Interpunktion, um Zeichen zu sparen.
  • Wir wählen nur Buchstabentripletts aus, die am Anfang von mindestens 19 Wörtern stehen (diese sind oben gespeichert w). Die Komprimierung erfolgt durch Neuanordnung der Triplets, sodass möglichst viele Doppelbuchstaben vorhanden sind, und diese Paare werden durch die entsprechenden ASCII-Großbuchstaben ersetzt (z. B. fiLoNoN ... → fil, lon, non, ...).
  • Für jedes Triplet betrachten wir die Scores der Titel, in denen es vorkommt, und berechnen den Mittelwert und die Standardabweichung der Scores. Dann wir konvertieren diejenigen auf ganze Zahlen und speichern sie in m, süber, unter Ausnutzung der Tatsache , dass die mittlere / sd ist höchstens 90 (eine direkte ASCII - Kodierung ermöglicht, da es 95 druckbaren ASCII)
  • G ist die Normalverteilungsfunktion - wir runden e auf 2dp und die Quadratwurzel von 2 pi auf 1 dp, um Zeichen zu sparen.

Insgesamt hat das extreme Zeichenlimit dies zu einer der schlechtesten Ideen gemacht, die ich mir je ausgedacht habe, aber ich bin ziemlich glücklich darüber, wie viel ich hineingepfercht habe (auch wenn es nicht sehr gut funktioniert). Wenn jemand bessere Ideen für die Komprimierung hat, lass es mich wissen :)

(Danke an KennyTM für den Hinweis auf meine sinnlose Komprimierung)

Sp3000
quelle
Sofern ich den Code nicht falsch ausgeführt habe, ist Ihr Komprimierungscode sogar länger als das dekomprimierte Ergebnis ... er w='grge…scse';w=[w[i:i+2]for i in range(0,len(w),2)]ist 165 Byte lang, während Ihr Code C=lambda:…;w=C('…')179 Byte lang ist.
kennytm
@KennyTM Oh, danke - ich habe so viel mit dem Code rumgespielt und versucht, das Zeichenlimit zu erreichen, bei dem ich den Überblick über das Komprimieren verloren hatte. : P
Sp3000
4

Python 2, 535 Zeichen, 0,330910 Punkte, sagt 11,35 voraus

Mitteln Sie die Punktzahl für Titel, die jedes Wort enthalten, und verwenden Sie dann die oberen und unteren 50 Wörter, um möglicherweise die BASIS-Punktzahl in der guess(title)Funktion zu ändern .

Python-Code:

BASE = 11.35
word={}
for sc,ti in csv.reader(open(sys.argv[1])):
    if sc == 'Score': continue
    parts = re.findall(r"[-a-zA-Z']+", ti.lower())
    for p in parts:
        a, c = word.get(p, (0.0,0))
        word[p] = (a+int(sc), c+1)

rank = sorted([(sc/ct,wd) for wd,(sc,ct) in word.items() if ct > 2])
adjust = rank[:50] + rank[-50:]

def guess(title):
    score = BASE
    parts = re.findall(r"[-a-zA-Z']+", title.lower())
    for sc,wd in adjust:
        if wd in parts:
            score *= 0.7 + 0.3*sc/BASE
    return score
Logik-Ritter
quelle
3

C

Punktzahl: Unbekannt
Länge: 5 Bytes
Voraussagen: 5

Golf gespielt:

int s(char *p){return 5;}

Ungolfed:

int s(char *p)
{
   return 5;
}

Eine Abfrage der Bewertungen ergibt eine durchschnittliche Bewertung von 5.

Ich habe im Moment nicht die Möglichkeit, es zu testen, andere können es gerne ausführen / bearbeiten.

Joshpbarron
quelle
Further Gulfed: int s () {return 5;}
Joshua
"Sie werden hiermit aufgefordert, ein Programm oder eine Funktion zu schreiben, die den Titel einer PPCG-Frage als Eingabe verwendet und eine Vorhersage ihrer Punktzahl zurückgibt." - Sorry, aber nein: 0
Joshpbarron
Ich habe eine Plattform gesehen, auf der, wenn Sie main () vergessen haben, Ihre erste Funktion main () war. Vielleicht hängt er davon ab.
Joshua