Bazı Kitapları Kapaklarıyla Yardıralım


47

Herkes içeriğin soruyu yaptığını bilir. Fakat iyi bir başlık da yardımcı olur ve ilk gördüğümüz şey budur. İlk izlenimi bir programa dönüştürmenin ve hangi tür başlıkların daha fazla oy aldığını bulma zamanı.

PPCG sorusu başlığını girdi olarak alan ve puanını tahmin eden bir program veya işlev yazmanız istenmektedir.

Örneğin, Counting Grains of Ricebir girdi olarak alabilirsiniz ve 59bu durumda skora yakın bir şey döndürmeye çalışıyorsunuzdur . Tamsayılı olmayan tahminler iyi, ancak altındaki veya altındaki tahminler iyi -20değil.

Test ve puanlama için veriler:

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

Puanlama: Programınız, bu sitenin (PPCG) tarihindeki her soru üzerinde çalışacaktır, kapalı soruları saymaz. Fonksiyon ln(score + 20)daha sonra her bir puana ve her tahminde uygulanacaktır. Elde edilen iki değer kümesi arasındaki kök-ortalama-kare-hata puanınızdır. Alçak daha iyi.

Örneğin, her defasında 0 tahmin eden bir program 0,577, her defasında 11 tahmin eden bir program ise 0,362 puan alacaktır.

Lütfen puanınızı hesaplayın ve cevabınızın başlığına ekleyin. Lütfen programınızın bu sorunun kaç oy alacağı konusundaki öngörüsünü de ekleyin.

Kısıtlamalar:

  • Aşırı kodlamanın önlenmesi için 1000 karakterden fazla olmamalıdır.

  • Yukarıda belirtilen verilerin tamamını makul bir makinede bir dakikadan kısa sürede çalıştırmanız gerekir.

  • Standart Loopholes kapandı.


İşte kullanımınız ve / veya belirsizlikleri gidermek için Python ile yazılmış bir test cihazı:

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
Güzel bir fikir, ancak veri setinin sabit olmaması utanç verici, bu nedenle puanlar bir süre sonra geçersiz hale gelecek. Ayrıca stratejik bir oy kullanma olasılığı da var: bu soruyu cevaplayan ve aynı hafta içinde bir vox-populi rozeti kazanan herkes şüpheyle görülmeli! ;-)
Level River St

1
Başlık , uygun olan hallerde [closed]ve gibi şeyleri içerecek veya hariç tutabilecek [on hold]mi?
es1024 11:14

4
@ steveverrill Eh, bunun tam tersi zaman ilerledikçe, programların geçmiş yayınlarda olduğu gibi gelecekteki yayınlarda da başarılı olup olmadığını görebileceğiz.
isaacg

6
Sabit kodlamayı yenmek zor. Her bir kodlanmış üst oylu soru 0.4 puan kadar düşebilir. Ve aynı zamanda pek yaygın bir örüntü yok gibi görünüyor, haha. Cevapların sadece 1000 byte'a kadar kodlanmış sonuca uyacak şekilde rekabet edeceğini tahmin ediyorum.
justhalf

5
Tüm soruları test setiniz olarak kullanmamalısınız. Rasgele belirli bir sayı (% 10 -% 20) önceden seçmeli ve bunları test grubunuz olarak tanımlamalısınız (ancak kimseye ne olduğunu söylememelisiniz). Geçmişi öngören bir algoritma yapmak, gelecekteki yordayıcı değeri olandan (yani, herhangi bir alt kümede iyi çalışan bir algoritmadan) daha kolaydır. (Bu% 10'luk kısmı bizim gördüğümüzden çıkarmak daha iyi olurdu, ama bu gerçekten işe yaramadı.)
Joe

Yanıtlar:


9

Python 2, 991 karakter, puan 0.221854834221, tahmin 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)

Açıklama:

Bu utanmaz kodlama, ancak verimli bir şekilde yapmaya çalışıyor.

Ön işleme:

Ayrı bir kodda, her bir başlığı 0 ile 256 ^ 2-1 arasında bir değere ayırdım. Bu değerleri depoya çağıralım. Her kutu için ortalama puanı hesapladım. (Kutulara küçük bir oran için çarpışmalar olduğu için ortalamaya ihtiyaç vardır - çarpışmalar vardır - aynı kutuya 1 başlık hastasından daha fazlası. Fakat büyük çoğunluk için her başlık kendi çöp kutusuna eşlenir.

Her bir başlık için 2 baytlık kodun arkasındaki fikir 1 bayt yeterli değil - çok fazla çarpışma alıyoruz, yani her bir 1 baytlık kutuya hangi puanı atayacağımızı bilmiyoruz. Ancak 2 baytlık kutularla neredeyse çarpışma olmaz ve her bir başlığın 2 baytlık gösterimini etkin bir şekilde alırız.

Sonra depoları sıralayın - sadece tahmin etmek yerine bu kutuya hesaplanan değerini atadığımızda puan kazancını hesaplayın. En iyi N kutularını alın ve bunları bir dizgeye kodlayın (gerçek kodda d).

Kodlama: kutunun anahtarı 2 bayt olarak kodlanmıştır. değer 1 bayt kullanılarak kodlanır. -8 ile 300 + arasındaki değerleri buldum, bu yüzden 1 bayta ulaştırmak için biraz sıkmak zorunda kaldım: x -> (x + 8) / 2.

Gerçek kod:

yukarıda açıklanan kodlamanın kodunu çözerek, bayt üçlüsü olarak okunur. Bir başlık verildiğinde, hash değerini hesaplayın (modulo 256 ^ 2) ve bu anahtar dict içinde bulunursa, eşleştiği değeri döndür. Aksi takdirde, 11 döndürün.


3
Bir öneri: Ortalama puan o kadar iyi değil. Zorluk puanlama fonksiyonuna bakın, doğrusal değil.
Deduplicator

1
@Deduplicator Teşekkürler, bittikten sonra anladım. Mesele şu ki, çöplerin% 99'unda çarpışma yok, yani ortalama aslında sadece o çöp kutusuna eşlenen tek başlığın puanı.
Ofri Raviv

16

Javascript ES6

Puan: 0.245663
Uzunluk: 1000 bytes Tahminler
: 5

(Sanırım soru beklenmedik bir düşüş vurgusundan kaynaklanıyor.: P)

küçültülmüş

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

Expanded

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

İşlev Sbir dizgiyi (başlık) kabul eder ve puanını döndürür.

Davranış Üzerine Notlar:

  • ≤ 70 oy başlığı> 70 oy başlığından ayrı ele alınmaktadır
  • Vote 70 oy başlığı, hiçbir şekilde bir dize hash işlevine benzemeyen oldukça karmaşık bir holonomik anahtar kelime izleme potansiyeli optimizasyon algoritması kullanılarak kutulara ayrılır
  • biraz mutlu hesaptan sonra, her kutu için en uygun tahminin sadece kutudaki tüm başlıklar için eksi 20 olan (oy + 20) 'nin geometrik ortalaması olduğu ortaya çıktı.
  • 479 kutuların tümü için optimal tahminler daha sonra 479 karakterlik bir base-70 string olarak kodlanır.
  • > 70 oy başlığı için, diğer> 70 oy başlığı ile çarpışmayı garanti etmeyen ve fal 70 oy başlığının yanlış tespit edilmediğini garanti eden son teknoloji bir karma tekniği kullanılarak oluşturulan benzersiz 3 basamaklı baz-36 kodlar atanır. En son teknolojiye sahip bu teknik, hiçbir şekilde çarpışma meydana gelinceye kadar rastgele çöp kutusu sayımı denemeye benzemez.
  • >> 70 oy başlık kodu ve oy sayıları basit bir arama tablosuna dönüştürülen bir dizede (başlık başına 6 bayt) kodlanır. Bu nedenle rutin,> 70 oydaki başlıklar için sıfır hata yapar.

10

Python 2, Puan = 0.335027, 999 karakter, Bu soru için 11.34828 Tahmini

Sadece topu yuvarlamak için. Bu hiçbir yerde optimal değildir.

Süslü SVM olayı sadece benim rastgele fikrimdir ve onu uygulamak gibi hissettim, işte burada. Taban çizgisini 0,02 puan artırıyor, bu yüzden yeterince mutluyum. Ancak girdilerin kodlanmasının, iyileştirmenin çoğunluğunun geldiği yer olduğunu göstermek için, bazı cevapları da kodlamak zor.

Kodlama olmadan skor 0.360'dır (ve aslında tüm tahminler 11 civarındadır)

Ben kullanıyorum scikit-öğrenme ve 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

Anladığımdan emin değilim - puanları harici bir dosyadan okudunuz mu? Öyleyse neden sadece [s] tahmin etmiyorsunuz? Bu 0 puan verecek ...
Ofri Raviv

2
Çünkü bu eğlenceli olmazdı = p
justhalf

4

Python 2, 986 karakter, puan 0.3480188, tahmin 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]

İlgili fonksiyon J.

Program aslında Naive Bayes'i başlık kelimeleri kullanarak kullanıyor, ancak karakter sınırı sayesinde son derece sınırlı. Ne kadar sınırlı? İyi...

  • Her başlık için küçük harfe dönüşür ve sadece en az 4 harften oluşan kelimelere bakarız. Sonra bu kelimelerin her birinin ilk üç harfini özellik olarak alırız . Karakterlerden tasarruf etmek için soyma noktalama işaretlerini atlarız.
  • Yalnızca en az 19 kelimenin başlangıcındaki harf üçlelerini seçeriz (bunlar wyukarıda saklanır ). Sıkıştırma, üçlülerin mümkün olduğunca çok sayıda iki katı harf bulunacak şekilde yeniden düzenlenmesiyle yapılır ve bu çiftler karşılık gelen ASCII büyük harfleriyle değiştirilir (örneğin fiLoNoN ... → fil, lon, non, ...)
  • Her üçlü için, göründüğü başlıkların puanlarına bakarız ve puanların ortalama ve standart sapmasını hesaplarız. Sonra tamsayılar için bu dönüştürmek ve bunları saklamak m, sgerçeği kullanarak, yukarıda ortalama / sd en 90 altında olduğunu (doğrudan bir ASCII kodlama sağlayan 95 yazdırılabilir ASCII olmadığından)
  • G normal dağılım işlevi - e'den 2dp'ye ve karakterlerden tasarruf etmek için 2 pi'den 1 dp'ye kadar ters kare kökü alıyoruz.

Toplamda aşırı karakter sınırı, bugüne kadar karşılaştığım en kötü fikirlerden birini yaptı, ama ne kadar tıka basa başardığımdan çok mutluyum (çok iyi çalışmamasına rağmen). Herhangi birinin sıkıştırma konusunda daha iyi fikirleri varsa, lütfen bana bildirin :)

(Anlamsız sıkıştırmamı işaret ettiği için KennyTM'e teşekkürler)


Kodu yanlış bir şekilde çalıştırmadığım sürece, sıkıştırma kodunuz dekompresyon sonucundan bile daha uzun ... w='grge…scse';w=[w[i:i+2]for i in range(0,len(w),2)]sizinki C=lambda:…;w=C('…')179 bayt iken 165 bayttır.
kennytm

@KennyTM Oh teşekkürler - Kodla uğraşıyorum, tüm sıkıştırma işlemlerini kaybettiğim char limitine uymaya çalışıyorum. : P
Sp3000

4

Python 2, 535 karakter, puan 0.330910, tahminler 11.35

Her bir sözcüğü içeren başlıklar için puan ortalaması, ardından guess(title)işlevdeki BASE puanını değiştirmek için üst ve alt 50 kelimelerini kullanın .

Python kodu:

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

Puan: Bilinmiyor
Uzunluk: 5 byte
Tahminler: 5

golfed:

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

Ungolfed:

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

Puanların sorgulanması ortalama 5 puan verir.

Şu anda test etme yeteneğim yok, başkaları da çalışabilir / düzenleyebilir.


Daha Körfezli: int s () {return 5;}
Joshua

“PPCG sorusu başlığını girdi olarak alan ve puanının bir tahminini veren bir program veya işlev yazmak için zorlanıyorsunuz.” - Üzgünüm ama hayır: 0
Joshpbarron

Eğer main () 'i unuttuysanız, ilk işlevinizin main () olduğu bir platform gördüm. Belki de buna bağlı.
Joshua
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.