Il sistema di handicap PPCG


35

Come tutti sappiamo, il meta è pieno di lamentele sul punteggio del code-golf tra le lingue (sì, ogni parola è un collegamento separato, e questi possono essere solo la punta dell'iceberg).

Con così tanta gelosia nei confronti di coloro che si sono davvero preoccupati di consultare la documentazione di Pyth, ho pensato che sarebbe stato bello avere un po 'più di una sfida costruttiva, che si addicesse a un sito web specializzato in sfide del codice.


La sfida è piuttosto semplice. Come input , abbiamo il nome della lingua e il conteggio dei byte . Puoi prenderli come input di funzioni stdino come metodo di input predefinito per le tue lingue.

Come output , abbiamo un conteggio di byte corretto , ovvero il tuo punteggio con l'handicap applicato. Rispettivamente, l'output dovrebbe essere l'output della funzione stdouto il metodo di output predefinito della tua lingua. L'output verrà arrotondato a numeri interi, perché amiamo i tiebreaker.

Utilizzando la query più brutta e compromessa ( link - sentiti libero di ripulirlo), sono riuscito a creare un set di dati (zip con .xslx, .ods e .csv) che contiene un'istantanea di tutte le risposte alle domande del . È possibile utilizzare questo file (e assumere che sia disponibile al vostro programma, ad esempio, è nella stessa cartella) o convertire il file in un altro formato convenzionale ( .xls, .mat, .savecc - ma può contenere solo i dati originali!). Il nome dovrebbe rimanere QueryResults.extcon extl'estensione scelta.


Ora per i dettagli. Per ogni lingua, esiste un parametro Boilerplate Be Verbosity V. Insieme, possono essere utilizzati per creare un modello lineare della lingua. Sia nil numero effettivo di byte e csia il punteggio corretto. Usando un modello semplice n=Vc+B, otteniamo il punteggio corretto:

    n-B
c = ---
     V

Abbastanza semplice, vero? Ora, per determinare Ve B. Come prevedibile, faremo una regressione lineare, o più precisa, una regressione lineare ponderata perlomeno dei quadrati. Non spiegherò i dettagli al riguardo: se non sei sicuro di come farlo, Wikipedia è tua amica o, se sei fortunato, la documentazione della tua lingua.

I dati saranno i seguenti. Ogni punto dati sarà il conteggio dei byte ne il conteggio medio della domanda c. Per tenere conto dei voti, i punti saranno ponderati, in base al loro numero di voti più uno (per tenere conto di 0 voti), chiamiamolo così v. Le risposte con voti negativi devono essere scartate. In termini semplici, una risposta con 1 voto dovrebbe essere uguale a due risposte con 0 voti.

Questi dati vengono quindi inseriti nel modello sopra menzionato n=Vc+Busando la regressione lineare ponderata.


Ad esempio , dati i dati per una determinata lingua

n1=20, c1=8.2, v1=1
n2=25, c2=10.3, v2=2
n3=15, c3=5.7, v3=5

Ora, componiamo le matrici e vettori interessati A, ye W, con i nostri parametri nel vettore

  [1 c1]    [n1]    [1 0 0]  x=[B]
A=[1 c2]  y=[n2]  W=[0 2 0],   [V]
  [1 c3]    [n3]    [0 0 5]

risolviamo l'equazione della matrice ( 'indicando la trasposizione)

A'WAx=A'Wy

per x(e di conseguenza, otteniamo il nostro Be Vparametro).


Il tuo punteggio sarà l'output del tuo programma, quando ti verrà dato il tuo nome e bytunt personale. Quindi sì, questa volta anche gli utenti Java e C ++ possono vincere!

Attenzione: La query genera un set di dati con un sacco di righe non valide a causa di persone che utilizzano 'cool' intestazione formattazione e persone di tagging loro domande come . Il download che ho fornito ha rimosso la maggior parte degli outlier. NON utilizzare il CSV fornito con la query.

Buona programmazione!


3
consulta la documentazione di Pyth / studia attentamente i due pezzi esistenti di documentazione di Jelly
lirtosiast

La tua query non sembra distinguere tra Perl 5 e Perl 6. Il che è simile a non distinguere C ++ da Haskell.
Brad Gilbert b2gills

@ BradGilbertb2gills Lo so - fa un sacco di cose eccentriche, principalmente a causa del fatto che le persone impazziscono con la formattazione. Sentiti libero di migliorarlo, ma in questo momento, è un compromesso tra la mancanza di numerazione delle versioni e le lingue chiamate C++ <s>6 bytes</s>. Inoltre, non ho mai usato T-SQL prima d'ora e sono già impressionato da me stesso che sono riuscito a estrarre il byte.
Sanchises,

È possibile rimuovere valori anomali, ovvero eventuali lingue con una sola voce (in genere nomi di lingue errati) o quelle con> 10.000 byte?
Robert Fraser,

@RobertFraser Ho pensato che sarebbe stato troppo per una singola sfida. Riparerò il file di dati, vedi modifica.
Sanchises,

Risposte:


21

Mathematica, 244.719 (245 byte)

f[l_,n_]:=x/.Solve[d=Rest@Import@"QueryResults.csv";LinearModelFit[#.#2/Tr@#&@@{#~Max~-1&/@#4+1,#3}&@@Thread@#&/@{#,#~Cases~{_,l,__}}&/@d~GroupBy~Last/@#[[;;,1,5]],x,x,Weights->Tr/@#[[;;,;;,4]]]&[d~Cases~{_,l,_,v_/;v>=0,_}~GatherBy~Last]@x==n,x]

Caso di prova

f["mathematica", n]   (* { .820033 (n + 53.4263) } *)
f["mathematica", 245] (* { 244.719 } *)

E le altre lingue?

f["c++", n]           (* { .821181 (n - 79.5437) } *)
f["java", n]          (* { .717579 (n - 56.0858) } *)
f["cjam", n]          (* { 2.21357 (n + 2.73772) } *)
f["pyth", n]          (* { 4.52194 (n - 8.82806) } *)

Modello alternativo :log(c)=log((n-B)/V)

Una caratteristica notevole del code golf (e probabilmente di altri problemi di codifica) è che la distribuzione delle lunghezze dei programmi tende ad essere distribuzione esponenziale (al contrario della distribuzione uniforme). Quindi il modello ha log(n)=log(Vc+B)molte più probabilità di bilanciare le influenze tra i punti con il grande ce il piccolo c.

Come possiamo vedere nei grafici sottostanti, la distribuzione dei punti è adatta per adattarsi in scala logaritmica.


Risultati del nuovo modello

Language       V       B

Python       1.365   -19.4    
Javascript   1.002     1.6
Ruby         0.724     1.7
Perl         1.177   -32.7
C            1.105     1.5
Haskell      1.454   -24.5
Mathematica  1.319   -39.7
PHP          1.799   -62.0
Java         1.642     4.4
C#           1.407     4.5

CJam         0.608   -12.5
Pyth         0.519   -11.4
Golfscript   0.766   -18.0
J            0.863   -21.4
APL          0.744   -17.7
K            0.933   -23.3
Retina       1.322   -37.9
MATL         0.762   -13.3
Jelly        0.965   -23.8

Abbiamo trovato due linguaggi eccezionali - Ruby with V=0.724e Retina with V=1.322, e un criterio per essere un linguaggio golfistico popolare - con una grande piastra negativa.


@sanchises Fin qui tutto bene, tranne per il fatto che usi i punti e virgola come delimitatori in csv.
njpipeorgan,

Questo è Microsoft Excel per te. Apparentemente salvare come CSV è troppo difficile per questo.
Sanchises,

Quindi a quanto pare CJam ha una lunghezza negativa della piastra di cottura. Interessante.
PurkkaKoodari,

@ Pietu1998 Il modello lineare non è così preciso, penso.
njpipeorgan,

@ Pietu1998 Non del tutto sorprendente, dal momento che le lingue del golf in genere accettano input impliciti e possono restituire output impliciti. Si noti che "Lunghezza della piastra della caldaia" è definita in base alla media, non in una lingua ideale senza caldaia. In realtà sono positivamente sorpreso da quanto bene stia facendo questo semplice modello guardando questi risultati.
Sanchises,

3

Python3, 765,19 (765) byte

Probabilmente un po 'di spazio per giocare a golf qui. Richiede numpy per roba da matrice. Legge da stdin, formattato come segue: [lang] [byte / n]. Si interrompe quando si invia q.

import numpy as n,csv
L={};Q={};X={};D=n.dot;f=open('QueryResults.csv',encoding="utf8");R=csv.reader(f);f.readline();Z=list.append;M=n.matrix
for r in R:
 if r[1] not in L:L[r[1]]=[]
 if r[4] not in Q:Q[r[4]]=[]
 Z(L[r[1]],r);Z(Q[r[4]],r)
for l in L:
 b=[];a=[];v=[];t=[]
 for r in L[l]:
  if int(r[3])>-1:
   Z(b,int(r[2]));o=[]
   for q in Q[r[4]]:Z(o,int(q[2]))
   Z(a,sum(o)/len(o));Z(v,int(r[3])+1)
 for k in a:Z(t,[1,k])
 if len(t)<1:continue
 A=M(t);T=A.transpose();W=n.diag(v);y=M(b).reshape((len(b),1));e=D(D(T,W),A)
 if n.linalg.det(e)==0:continue
 i=n.linalg.inv(e);X[l]=D(i,D(D(T,W),y))
p=input()
while(p!="q"):
 S=p.split()
 if S[1]=='n':print("(n-("+str(X[S[0]].item(0))+"))/"+str(X[S[0]].item(1)))
 else:print(str((int(S[1])-X[S[0]].item(0))/X[S[0]].item(1)))
 p=input()

risultati

Avrei potuto fare qualcosa di sbagliato ad un certo punto; Ottengo risultati diversi rispetto alla risposta di Mathematica:

python3 808 -> 765.19
python3 n   -> (n-(32.41))/1.01

c++ n        -> (n-(71.86))/1.17
cjam n       -> (n-(-14.09))/0.51
java n       -> (n-(18.08))/1.64
pyth n       -> (n-(1.42))/0.28
jelly n      -> (n-(-4.88))/0.34
golfscript n -> (n-(-0.31))/0.44
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.