표지로 일부 책을 판단합시다


47

내용이 질문을한다는 것을 누구나 알고 있습니다. 그러나 좋은 제목도 도움이되며 이것이 우리가 가장 먼저 보는 것입니다. 이제 첫인상을 프로그램으로 바꾸고 어떤 종류의 타이틀이 더 인기를 얻었는지 알아볼 차례입니다.

이에 따라 PPCG 질문의 제목을 입력으로 받아 점수 예측을 리턴하는 프로그램 또는 함수를 작성해야합니다.

예를 들어, Counting Grains of Rice입력으로 수신 할 수 있으며이 59경우 점수에 가까운 것을 반환하려고합니다 . 정수가 아닌 추측은 괜찮지 만 그 이하의 추측 -20은 그렇지 않습니다.

테스트 및 채점을위한 데이터는 다음과 같습니다.

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

채점 : 귀하의 프로그램은이 사이트의 (PPCG) 내역에있는 모든 질문에 대해 실행되며 비공개 질문은 포함하지 않습니다. 이 함수 ln(score + 20)는 각 점수 및 각 추측에 적용됩니다. 두 결과 값 집합 사이의 제곱근 오류는 점수입니다. 낮을수록 좋습니다.

예를 들어, 매번 0을 추측 한 프로그램은 0.577, 매번 11을 추측 한 프로그램은 0.362를 기록합니다.

점수를 계산하여 답변 제목에 포함 시키십시오. 이 질문에 얼마나 많은 공언을할지 프로그램의 예측도 포함 시키십시오.

제한 사항 :

  • 과도한 하드 코딩을 방지하려면 1000 자 이하 여야합니다.

  • 합리적인 머신에서 1 분 이내에 위의 전체 데이터 세트에서 실행해야합니다.

  • 표준 허점이 닫힙니다.


다음은 파이썬으로 작성된 테스터로, 사용 및 / 또는 모호성을 해결합니다.

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
좋은 생각이지만 데이터 세트가 안정적이지 않은 것은 부끄러운 일이므로 잠시 후 점수가 유효하지 않습니다. 전략적 투표의 가능성도 미미합니다.이 질문에 대답하고 같은 주에 복셀 포 퓰리 배지를받는 사람은 의심의 여지가 있어야합니다! ;-)
레벨 리버 St

1
제목에 [closed]and 같은 항목이 포함되거나 제외 [on hold]됩니까?
es1024

4
@steveverrill 글쎄, 그 단점은 시간이 지남에 따라 프로그램이 미래 게시물뿐만 아니라 미래 게시물에서도 잘 작동하는지 확인할 수 있습니다.
isaacg

6
하드 코딩을이기는 것은 어렵습니다. 각 하드 코딩 된 상위 투표 질문은 최대 0.4 점을 줄일 수 있습니다. 하하, 일반적인 패턴도 많지 않은 것 같습니다. 나는 대답이 1000 바이트로 많은 하드 코딩 된 결과를 맞추는 방법과 경쟁 할 것이라고 예측하고 있습니다.
justhalf

5
전체 질문을 테스트 세트로 사용해서는 안됩니다. 특정 숫자 (10 % -20 %)를 무작위로 미리 선택하고이를 테스트 세트로 정의해야합니다 (단, 그 숫자를 알려주지 마십시오). 미래 예측 값이있는 알고리즘 (예 : 특정 하위 집합에서 잘 작동하는 알고리즘)보다 과거 기록을 예측하는 알고리즘을 만드는 것이 훨씬 쉽습니다. (우리가 볼 수있는 것에서 그 10 %를 제거하는 것이 더 나을 것이지만, 실제로는 효과가 없을 것입니다.)
Joe

답변:


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 사이의 값으로 해시했습니다. 이 값을 빈이라고합시다. 각 빈에 대해 평균 점수를 계산했습니다. 빈의 작은 부분에 대해 동일한 빈에 대한 제목 해시가 1 개 이상 충돌하기 때문에 평균이 필요합니다. 그러나 대부분의 경우 각 제목은 자체 빈에 매핑됩니다.

각 타이틀에 대한 2 바이트 코드의 기본 개념은 1 바이트로는 충분하지 않다는 것입니다. 충돌이 너무 많아서 각 1 바이트 빈에 어떤 점수를 할당할지 알 수 없습니다. 그러나 2 바이트 빈을 사용하면 충돌이 거의 없으며 각 타이틀의 2 바이트 표현을 효과적으로 얻을 수 있습니다.

그런 다음 빈을 순위 매기 십시오-우리가 11을 추측하는 대신이 빈에 계산 된 값을 할당하면 점수의 이득을 계산하십시오. 최상의 N 빈을 가져 와서 문자열로 코딩하십시오 (실제 코드에서 d).

인코딩 : bin의 키는 2 바이트로 코딩됩니다. 값은 1 바이트를 사용하여 인코딩됩니다. 나는 -8에서 300 + 사이의 값을 찾았으므로 1 바이트로 넣으려면 조금 짜야했습니다 : x-> (x + 8) / 2.

실제 코드 :

바이트 트립 트로 d를 읽고 위에서 설명한 인코딩을 디코딩합니다. 제목이 주어지면 해시 (모듈로 256 ^ 2)를 계산하고 해당 키가 dict에서 발견되면 매핑 된 값을 반환하십시오. 그렇지 않으면 11을 반환하십시오.


3
제안 : 평균 점수는 그다지 좋지 않습니다. 점수 함수에 대한 도전을보십시오. 비선형입니다.
중복 제거기

1
@ 중복 제거기 감사합니다. 완료된 후에 깨달았습니다. 빈의 99 %에 대해서는 충돌이 없으므로 평균은 실제로 해당 빈에 매핑되는 단일 제목의 점수입니다.
Ofri Raviv

16

자바 스크립트 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 빈에 대한 최적의 추측은 479 자 기본 70 문자열로 인코딩됩니다.
  • 70 개가 넘는 투표 제목의 경우, 제목에는 다른 70 개가 넘는 투표 제목과 충돌하지 않고 70 개 미만의 투표 제목을 탐지하지 않는 최첨단 해싱 기술을 사용하여 생성 된 고유 한 3 자리 기본 36 코드가 할당됩니다. 이 최첨단 기술은 충돌이 발생하지 않을 때까지 임의의 빈 카운트를 시도하는 것과 유사합니다.
  • > 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

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 이지만 문자 제한으로 인해 매우 제한됩니다. 얼마나 제한되어 있습니까? 잘...

  • 각 제목마다 소문자로 변환하고 최소 4 글자 이상의 단어 만 봅니다. 그런 다음 각 단어 의 처음 세 글자 를 기능으로 사용합니다. 문자를 저장하기 위해 문장 부호를 제거하지 않습니다.
  • 우리 는 적어도 19 단어 의 시작 부분 있는 문자 삼중 항만 선택합니다 ( w위에 저장되어 있습니다). 압축은 트리플렛을 재 배열하여 가능한 많은 이중 문자가 존재하도록하며,이 쌍은 해당 ASCII 대문자로 대체됩니다 (예 : fiLoNoN ... → fil, lon, non, ...).
  • 각 삼중 항에 대해 제목의 점수를보고 점수의 평균 및 표준 편차를 계산합니다. 그런 다음 우리는 정수로 그 변환 과에 저장 m, s사실을 이용하여 위의 평균 /의 SD 대부분의 90에 있는지 (직접 ASCII 인코딩을 허용 (95) 인쇄 가능한 ASCII 있기 때문에)
  • G 정규 분포 함수입니다-e를 2dp로 반올림하고 2π의 역 제곱근을 1dp로 반올림하여 문자를 저장합니다.

전체적으로 극한의 문자 제한으로 인해 내가 생각해 낸 최악의 아이디어 중 하나를 만들었지 만 (잘 작동하지는 않지만) 얼마나 많은 양을 넣을 수 있었는지에 매우 만족합니다. 압축에 대한 더 좋은 아이디어가 있다면 알려주세요. :)

(무의미한 압축을 지적한 KennyTM에게 감사드립니다)


내가 코드를 잘못 실행하지 않으면 압축 코드가 압축 해제 결과보다 훨씬 깁니다 ... w='grge…scse';w=[w[i:i+2]for i in range(0,len(w),2)]165 바이트이고 C=lambda:…;w=C('…')179 바이트입니다.
kennytm

@ KennyTM Oh thanks-코드를 너무 엉망으로 삼아 모든 압축을 추적하지 못하는 문자 제한에 맞추려고했습니다. : P
Sp3000

4

Python 2, 535 자, 점수 0.330910, 11.35 예측

각 단어를 포함하는 제목에 대한 점수를 평균 한 다음 상위 및 하위 50 개 단어를 사용하여 guess(title)함수 에서 BASE 점수를 수정하십시오 .

파이썬 코드 :

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

점수 : 알 수없는
길이 : 5 바이트
예측 : 5

골프 :

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

언 골프 드 :

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

점수 쿼리는 평균 점수가 5입니다.

현재 테스트 할 수있는 능력이 없으며 다른 사람들은 실행 / 편집을 환영합니다.


더 걸프 : int s () {return 5;}
Joshua

"여기서 PPCG 질문의 제목을 입력으로 받아 점수의 예측을 반환하는 프로그램이나 함수를 작성해야합니다." -죄송하지만 nope : 0
Joshpbarron

main ()을 잊어 버린 경우 첫 번째 함수가 main () 인 플랫폼을 보았습니다. 어쩌면 그는 그것에 의존하고 있습니다.
Joshua
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.