让我们按封面来判断一些书


47

每个人都知道内容是问题所在。但是好标题也有帮助,这是我们看到的第一件事。现在是时候将第一印象变成一个程序,并弄清楚哪种标题会获得更多支持。

您面临的挑战是编写一个程序或函数,该程序或函数将PPCG问题的标题作为输入,并返回其得分的预测。

例如Counting Grains of Rice59在这种情况下,您可能会收到输入作为输入,并且您将尝试返回接近分数的内容。非整数的猜测是可以的,但低于或等于猜测的-20则不行。

以下是用于测试和评分的数据:

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

评分:您的程序将针对该站点(PPCG)历史记录中的每个问题运行,而不包括已关闭的问题。ln(score + 20)然后,该功能将应用于每个分数和每个猜测。两个结果值集之间的均方根误差就是您的得分。越低越好。

例如,一个程序每次猜测为0的得分为0.577,而每次猜测为11的程序得分为0.362。

请计算您的分数,并将其包括在答案标题中。还请包括您的程序对这个问题将获得多少票的预测。

限制条件:

  • 为防止过多的硬编码,请不要超过1000个字符。

  • 必须在一台合理的计算机上在一分钟之内运行上面的所有数据集。

  • 标准漏洞已关闭。


这是一个用Python编写的测试器,供您使用和/或消除歧义:

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

19
这是个好主意,但可惜的是数据集不稳定,因此分数过一段时间就会变得无效。进行战略投票的可能性也很小:任何回答此问题并在同一周内获得人妖徽章的人都应该受到怀疑!;-)
Level River St

1
标题是否包括和排除诸如[closed]和之类的内容[on hold]
es1024

4
@steveverrill好吧,随着时间的推移,它的另一面是,我们将能够查看这些程序在以后的帖子和过去的帖子中是否做得很好。
isaacg 2014年

6
难以克服硬编码。每个硬编码的投票最多的问题可以减少多达0.4的分数。而且似乎也没有太多常见的模式,哈哈。我预测答案将与如何在1000字节中容纳尽可能多的硬编码结果竞争。
justhalf 2014年

5
您不应该使用完整的问题作为测试集。您应该随机选择一个特定的数字(10%-20%),并将其定义为测试集(但不要告诉任何人这是什么)。相比于具有未来预测价值的算法(即,对任何给定子集都适用的算法),预测一种历史的算法要容易得多。(最好将这10%从我们所看到的全部中删除,但这并不能很好地工作。)
2014年

Answers:


9

Python 2,991个字符,得分0.221854834221,预测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)

说明:

这是无耻的硬编码,但是尝试有效地做到这一点。

预处理:

在单独的代码中,我将每个标题散列为0到256 ^ 2-1之间的值。我们称这些值为值箱。对于每个垃圾箱,我计算了平均分数。(需要平均,因为对于一小部分的容器来说,会有冲突-同一容器上有多个标题散列。但是对于绝大多数,每个标题都映射到它自己的容器上)。

每个标题2个字节的代码背后的想法是1个字节是不够的-我们遇到太多的冲突,因此我们真的不知道为每个1个字节的bin分配多少分。但是对于2字节的bin,几乎没有冲突,并且我们有效地获得了每个标题的2字节表示形式。

然后对垃圾箱进行排名 -如果我们为该垃圾箱分配其计算值,而不是仅仅猜测11,则计算得分的增加。取前N个垃圾箱,并将其编码为字符串(在实际代码中为d)。

编码:垃圾桶的密钥编码为2个字节。该值使用1个字节编码。我发现值在-8到300+之间,所以只需要压缩一点就可以放入1个字节:x->(x + 8)/ 2。

实际代码:

将d读取为字节三元组,解码上述编码。给定标题后,计算其哈希值(模256 ^ 2),如果在字典中找到该键,则返回其映射到的值。否则,返回11。


3
一个建议:平均分不是那么好。看一下挑战评分功能,它是非线性的。
Deduplicator 2014年

1
@Deduplicator谢谢,我意识到我完成之后。事实是,对于99%的垃圾箱,没有碰撞,因此平均值实际上只是映射到该垃圾箱的单个标题的得分。
Ofri Raviv

16

Javascript ES6

得分:0.245663
长度:1000字节
预测:5

(我想这个问题是由于意外投票失败引起的:P)

缩小的

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

展开式

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

该函数S接受一个字符串(标题)并返回其分数。

行为注意事项:

  • ≤70个投票标题与> 70个投票标题分开处理
  • 使用高度复杂的完整关键字跟踪潜力优化算法将≤70个投票标题分类到垃圾箱中,该算法绝不类似于字符串哈希函数
  • 经过一番开心的演算后,结果发现,每个仓位的最佳猜测只是仓位中所有标题的(票数+ 20)的几何平均值,减去20
  • 然后,将所有479个bin的最佳猜测编码为479个字符的base-70字符串
  • 对于> 70个投票标题,将为这些标题分配唯一的3位以36为基数的代码,这些代码使用最新的哈希技术生成,可确保与其他> 70个投票标题不会发生冲突,并且不会误检测≤70个投票标题。这项最新技术绝不像尝试随机计数,直到没有碰撞发生。
  • > 70个投票标题代码及其投票计数被编码为字符串(每个标题6个字节),该字符串将转换为简单的查找表。因此,对于所有> 70个投票标题,该例程具有零错误。

10

Python 2,成绩= 0.335027,999个字符,为此问题预测11.34828

只是为了使球滚动。这不是最佳选择。

奇特的SVM只是我的随机想法,我感觉很喜欢实现它,所以就在这里。它确实将基线提高了0.02点,因此我对此感到非常满意。但是,为了表明硬编码输入是大多数改进的源头,我也在硬编码一些答案。

如果不进行硬编码,则得分为0.360(实际上所有预测都在11左右,哈哈)

我正在使用scikit-learnnltk

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

我不确定我是否理解-您从外部文件中读取了分数?那么,为什么不仅仅预测sd [t]呢?这将得到0的分数...
Ofri Raviv

2
因为那会不好玩= p
justhalf 2014年

4

Python 2,986个字符,得分0.3480188,预测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]

相关功能是J

该程序本质上是Naive Bayes,使用标题词作为功能,但是由于char限制,它受到了极大的限制。如何限制?好...

  • 对于每个标题,我们将其转换为小写,并且仅查看至少4个字母长的单词。然后,我们将每个单词的前三个字母作为特征。我们跳过剥离标点来节省字符。
  • 我们仅选择字母三胞胎,它们至少以19个单词开头(这些存储在w上面)。压缩是通过重新排列三元组来完成的,以使存在尽可能多的双字母,并将这些对替换为其对应的ASCII大写字母(例如,fiLoNoN ...→fil,lon,non,...)
  • 对于每个三元组,我们查看出现在其中的标题的得分,并计算得分的平均值和标准偏差。然后,我们使用mean / sd最多为90的事实将它们转换为整数,并将它们存储在中ms(允许直接ASCII编码,因为有95个可打印的ASCII)
  • G 是正态分布函数-我们将e舍入为2dp,将2 pi的平方根取反为1 dp以节省字符。

总的说来,最大字符限制使这成为我曾经提出过的最糟糕的想法之一,但是我对能够成功塞满多少东西感到满意(即使它不能很好地工作)。如果有人对压缩有更好的想法,请告诉我:)

(感谢KennyTM指出我的无意义压缩)


除非我执行错误,否则您的压缩代码甚至比解压缩的结果还要长... w='grge…scse';w=[w[i:i+2]for i in range(0,len(w),2)]是165个字节,而您的C=lambda:…;w=C('…')是179个字节。
kennytm 2014年

@KennyTM哦,谢谢-我一直在搞乱代码,试图适应char限制,以至于我忘了所有压缩。:P
Sp3000

4

Python 2,535个字符,得分0.330910,预测11.35

平均包含每个单词的标题的得分,然后使用前50个单词和后50个单词来修改guess(title)函数中的BASE得分。

Python代码:

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

3

C

得分:未知
长度:5个字节
预测:5个

打高尔夫球:

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

取消高尔夫:

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

查询分数可获得平均分数5。

我目前没有测试能力,欢迎其他人运行/编辑。


进一步陷入困境:int s(){return 5;}
约书亚

“您面临的挑战是编写一个程序或函数,该程序或函数将PPCG问题的标题作为输入,并返回其得分的预测。” -对不起,但没有打0:
Joshpbarron 2014年

我已经看到了一个平台,如果您忘记了main(),那么您的第一个功能就是main()。也许他依赖于此。
约书亚
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.