Le système de handicap PPCG

35

Comme nous le savons tous, méta est débordait de plaintes au sujet de notation code de golf entre les langues (oui, chaque mot est un lien séparé, et ceux - ci peuvent être que la pointe de l'iceberg).

Avec tant de jalousie envers ceux qui se sont donné la peine de consulter la documentation Pyth, j'ai pensé qu'il serait bien de relever un défi un peu plus constructif, digne d'un site Web spécialisé dans les problèmes de code.


Le défi est plutôt simple. En entrée , nous avons le nom de la langue et le nombre d'octets . Vous pouvez les prendre comme entrées de fonction stdinou comme méthode de saisie par défaut de votre langue.

En sortie , nous avons un nombre d'octets corrigé , c'est-à-dire votre score avec le handicap appliqué. Respectivement, la sortie doit être la sortie de la fonction stdoutou la méthode de sortie par défaut de votre langue. La sortie sera arrondie aux nombres entiers, car nous aimons les systèmes décisifs.

En utilisant le plus laid, piraté ensemble requête ( lien - ne hésitez pas à nettoyer), j'ai réussi à créer un ensemble de données (zip avec .xslx, .ods et .csv) qui contient un aperçu de toutes les réponses à des questions . Vous pouvez utiliser ce fichier (et supposons qu'il soit disponible à votre programme, par exemple, il est dans le même dossier) ou de convertir ce fichier dans un autre format classique ( .xls, .mat, .savetc - mais il ne peut contenir les données originales!). Le nom doit rester QueryResults.extavec extl'extension de choix.


Maintenant pour les détails. Pour chaque langue, il existe des paramètres Boilerplate Bet Verbosity V. Ensemble, ils peuvent être utilisés pour créer un modèle linéaire du langage. Soit nle nombre d'octets réel, et cle score corrigé. En utilisant un modèle simple n=Vc+B, nous obtenons pour le score corrigé:

    n-B
c = ---
     V

Assez simple, non? Maintenant, pour déterminer Vet B. Comme vous vous en doutez, nous allons procéder à une régression linéaire, ou plus précise, une régression linéaire pondérée par les moindres carrés. Je ne vais pas expliquer les détails à ce sujet - si vous ne savez pas comment faire cela, Wikipedia est votre ami , ou si vous avez de la chance, la documentation de votre langue.

Les données seront les suivantes. Chaque point de données sera le nombre d'octets net le nombre moyen de la question c. Pour comptabiliser les votes, les points seront pondérés par leur nombre de votes plus un (pour comptabiliser 0 votes), appelons cela v. Les réponses avec des votes négatifs doivent être écartées. En termes simples, une réponse avec 1 vote doit compter autant que deux réponses avec 0 vote.

Ces données sont ensuite intégrées dans le modèle susmentionné en n=Vc+Butilisant une régression linéaire pondérée.


Par exemple , étant donné les données pour une langue donnée

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

Maintenant, nous composons les matrices pertinentes et des vecteurs A, yet W, avec nos paramètres dans le vecteur

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

nous résolvons l'équation matricielle (avec 'la transposée)

A'WAx=A'Wy

pour x(et par conséquent, nous obtenons notre Bet Vparamètre).


Votre score sera la sortie de votre programme, lorsque vous aurez votre propre nom de langue et votre propre décompte. Alors oui, cette fois, même les utilisateurs de Java et C ++ peuvent gagner!

AVERTISSEMENT: La requête génère un ensemble de données avec un grand nombre de lignes invalides en raison de personnes qui utilisent en- tête de « cool » et le formatage des gens de marquage leur des questions comme le . Le téléchargement que j'ai fourni a la plupart des valeurs aberrantes supprimées. N'utilisez PAS le fichier CSV fourni avec la requête.

Bonne codage!

Sanchises
la source
3
s / regarder la documentation Pyth / étudier soigneusement les deux existants morceaux de documentation Jelly
lirtosiast
Votre requête ne semble pas faire la différence entre Perl 5 et Perl 6. Ce qui revient à ne pas distinguer le C ++ de Haskell.
Brad Gilbert b2gills
@ BradGilbertb2gills je sais - cela fait beaucoup de choses bizarres, surtout à cause du fait que les gens deviennent fous avec le formatage. N'hésitez pas à l'améliorer, mais pour le moment, c'est un compromis entre l'absence de numérotation des versions et les langues appelées C++ <s>6 bytes</s>. De plus, je n'avais jamais fait de T-SQL avant aujourd'hui et je suis déjà impressionné par ma capacité d'extraire le décompte.
Sanchises
Peut-on supprimer les valeurs éloignées, c'est-à-dire les langues avec une seule entrée (noms de langue généralement incorrects) ou celles comportant plus de 10 000 octets?
Robert Fraser
@ RobertFraser Je pensais que ce serait trop pour un seul défi. Je vais réparer le fichier de données, voir edit.
Sanchises

Réponses:

21

Mathematica, 244.719 (245 bytes)

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]

Cas de test

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

Qu'en est-il des autres langues?

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

Modèle alternatif :log(c)=log((n-B)/V)

Une caractéristique notable du code de golf (et probablement d’autres problèmes de codage) est que la distribution des longueurs de programmes tend à être une distribution exponentielle (contrairement à une distribution uniforme). Par conséquent, le modèle log(n)=log(Vc+B)est beaucoup plus susceptible d’équilibrer les influences entre les points grands cet petits c.

Comme on peut le voir dans les graphiques ci-dessous, la distribution des points convient à une adaptation à l'échelle logarithmique.


Résultats du nouveau modèle

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

Nous avons trouvé deux langages exceptionnels - Ruby avec V=0.724et Retina avec V=1.322, et un critère pour être une langue de golf populaire - avoir un grand passe-partout négatif.

njpipeorgan
la source
@sanchises Jusqu'ici tout va bien, sauf que vous utilisez des points-virgules comme délimiteurs dans csv.
njpipeorgan
C'est Microsoft Excel pour vous. Apparemment, économiser en tant que CSV est trop difficile pour cela.
Sanchises
Donc, apparemment, CJam a une longueur passe-passe négative. Intéressant.
PurkkaKoodari
@ Pietu1998 Le modèle linéaire n'est pas aussi précis, je pense.
njpipeorgan
@ Pietu1998 Pas tout à fait surprenant, car les langues de golf prennent généralement des entrées implicites et peuvent renvoyer des sorties implicites. Notez que la "longueur de la plaque de cuisson" est définie par la moyenne et non par un langage idéal sans chaudière. En fait, je suis positivement surpris de voir à quel point ce modèle simple semble se porter lorsque l’on examine ces résultats.
Sanchises
3

Python3, 765.19 (765) octets

Probablement de la place pour jouer au golf ici. Nécessite Numpy pour les trucs de la matrice. Lit à partir de stdin, formaté comme suit: [lang] [octets / n]. Arrête lorsque vous envoyez 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()

Résultats

J'aurais peut-être fait quelque chose de mal à un moment donné; J'obtiens des résultats différents de ceux de la réponse de 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
Yodle
la source