자동 메타 코드 골프


13

당신은 모든 코드 골프 도전에 빠져 있습니다. 따라서 일부 Python 코드를 자동으로 골프화하는 프로그램을 작성하기로 결정했습니다. 3 가지 테스트 사례가 있습니다.

print quickSort([0,7,3,-1,8,10,57,2])
def quickSort(arr):
    less = []
    pivotList = []
    more = []
    if len(arr) <= 1:
        return arr
    else:
        pivot = arr[0]
        for i in arr:
            if i < pivot:
                less.append(i)
            elif i > pivot:
                more.append(i)
            else:
                pivotList.append(i)
        less = quickSort(less)
        more = quickSort(more)
        return less + pivotList + more

for i in xrange(1, 101):
    if i % 15 == 0:
        print "FizzBuzz"
    elif i % 3 == 0:
        print "Fizz"
    elif i % 5 == 0:
        print "Buzz"
    else:
        print i

from sys import argv

def randomGenerator(seed=1):
    max_int32 = (1 << 31) - 1
    seed = seed & max_int32

    while True:
        seed = (seed * 214013 + 2531011) & max_int32
        yield seed >> 16

def deal(seed):
    nc = 52
    cards = range(nc - 1, -1, -1)
    rnd = randomGenerator(seed)
    for i, r in zip(range(nc), rnd):
        j = (nc - 1) - r % (nc - i)
        cards[i], cards[j] = cards[j], cards[i]
    return cards

def show(cards):
    l = ["A23456789TJQK"[c / 4] + "CDHS"[c % 4] for c in cards]
    for i in range(0, len(cards), 8):
        print " ", " ".join(l[i : i+8])

if __name__ == '__main__':
    seed = int(argv[1]) if len(argv) == 2 else 11982
    print "Hand", seed
    deck = deal(seed)
    show(deck)

규칙 :

  1. 귀하의 프로그램은 내가 구체적으로 게시 한 코드를 대상으로해서는 안되며 Python 2 코드와 함께 작동해야합니다. 본인은 코드 골프가되는 소스 코드를 변경할 권리가 있습니다. 여러 줄 문자열이 없으므로 완전한 파서를 작성하지 않았으며 locals ()가 호출되지 않았다고 가정 할 수 있습니다.

  2. 프로그램의 출력은 원래 소스 코드와 동일한 방식으로 실행되어야합니다. (즉, 동일한 출력을 생성해야합니다. 출력이 동일하게 유지되는 한 변수 이름 및 언어 구성을 변경할 수 있습니다)

  3. STDIO 또는 파일을 사용하여 소스 코드의 입력 / 출력을 수행 할 수 있습니다.

점수는 프로그램 출력의 바이트 합계입니다.

(위에 나열된 코드는 http://rosettacode.org/ 에서 GNU Free Documentation License 1.2 아래에 있습니다. )



3
여기의 보너스 테스트 케이스는 사람들이 악독으로 시도하는.
Sp3000

4
"" 원본 소스 코드와 동일한 방식으로 출력이 실행 되는지 여부를 결정하기위한 모델은 무엇입니까 ? 예를 들어 두 번째 예에서는 제거 if __name__ == '__main__':가 일부 상황에서는 동작에 영향을 미치지 만 다른 상황에는 영향을 미치지 않는다고 생각합니다. 다른 예를 들어, 골프화되지 않은 입력이 stdin에서 int를 읽고 다른 유형의 예외가 발생하면 한 가지 유형의 예외를 throw한다고 가정하면 골프가 아닌 입력에 정수가 아닌 다른 유형의 예외가 발생할 수 있습니까?
Peter Taylor

2
이 같은 프로그램은 random_long_variable=0;print locals()어떻습니까?
Justin

답변:


4

파이썬 2.7, 794

필자는 잠시 동안 Python 축소기를 작성하려고했기 때문에 문제를 조사 할 수있는 좋은 기회입니다.

이 프로그램은 정규식 분석과 Python 파서 작업을 혼합하여 사용합니다. 공백이 최소화됩니다. 사용자가 정의한 변수는 사용하지 않는 단일 문자 변수로 대체됩니다. 마침내 while True성명서는 다이어트에 적용됩니다.

세 가지 테스트 사례가 모두 올바르게 실행 중인지 확인합니다. 생성 된 코드에서 오류가 발생할 수있는 병리학 적 예를 상상할 수 있지만 대부분의 상황에서 알고리즘이 강력해야합니다.

결과

228 t1.py
128 t2.py
438 t3.py
794 total

산출

def c(a):
 b=[]
 d=[]
 f=[]
 if len(a)<=1:
  return a
 else:
  e=a[0]
  for i in a:
   if i<e:
    b.append(i)
   elif i>e:
    f.append(i)
   else:
    d.append(i)
  b=c(b)
  f=c(f)
  return b+d+f
print c([0,7,3,-1,8,10,57,2])


for i in xrange(1,101):
 if i%15==0:
  print"FizzBuzz"
 elif i%3==0:
  print"Fizz"
 elif i%5==0:
  print"Buzz"
 else:
  print i


from sys import argv
def a(k=1):
 b=(1<<31)-1
 k=k&b
 while 1:
  k=(k*214013+2531011)&b
  yield k>>16
def d(k):
 f=52
 h=range(f-1,-1,-1)
 g=a(k)
 for i,r in zip(range(f),g):
  j=(f-1)-r%(f-i)
  h[i],h[j]=h[j],h[i]
 return h
def m(h):
 l=["A23456789TJQK"[c/4]+"CDHS"[c%4]for c in h]
 for i in range(0,len(h),8):
  print" "," ".join(l[i:i+8])
if __name__=='__main__':
 k=int(argv[1])if len(argv)==2 else 11982
 print"Hand",k
 e=d(k)
 m(e)

암호

import sys
import re
from tokenize import generate_tokens
from token import tok_name
from keyword import iskeyword

wr = sys.stdout.write

def pyparse(text):
    'Return [TYPE,TOKEN] pair list'
    # Use KEYWORD,NAME,NUMBER,OP,STRING,NL,NEWLINE,COMMENT,INDENT,DEDENT
    rawtokens = generate_tokens(text.readline)
    tokens = [[tok_name[n], t] for n,t,p1,p2,dx in rawtokens]
    for tpair in tokens:
        if tpair[0] == 'NAME' and iskeyword(tpair[1]):
            tpair[0] = 'KEYWORD'
    return tokens

def finduservars(filename):
    'Return a set of user variables that we can replace with a-zA-Z'
    varset = set()
    for line in open(filename):
        line = line.strip()
        match = re.match(r'def\s+(\w+)\s*\((.*)\)\s*:', line)
        if match:
            func, args = match.groups()
            varset.add(func)
            arglist = re.findall(r'(\w+|=)', args)
            for a in arglist:
                if a == '=':
                    break  # keyword args follow - too hard to parse
                varset.add(a)
            continue
        match = re.match(r'(\w+)\s*=.+', line)
        if match:
            assigned = match.group(1)
            varset.add(assigned)
            continue
    return set(v for v in list(varset) if len(v) > 1)

filename = sys.argv[1]
tokenlist = pyparse(open(filename))

# Build map for var->char conversion:
varset = finduservars(filename)
singles = [text for tok,text in tokenlist if tok=='NAME' and len(text)==1]
allvar = [chr(n) for n in range(97,123)+range(65,91)]
charvar = [c for c in allvar if c not in singles]
varreplaced = list(varset)[:len(charvar)]
varmap = dict((v, charvar.pop(0)) for v in varreplaced)

prev = 'NONE'
indent = ['']
output = []
add = output.append
for tok, text in tokenlist:
    if tok == 'NL':
        continue
    elif tok == 'INDENT':
        indent.append( text.replace('    ', ' ') )
        output[-1] = indent[-1]
    elif tok == 'DEDENT':
        indent.pop(-1)
        output[-1] = indent[-1]
    elif tok == 'NEWLINE':
        add(text)
        add(indent[-1])
    elif tok in 'KEYWORD,NAME,NUMBER':
        if prev in 'KEYWORD,NAME,NUMBER':
            add(' ')
        if tok == 'NAME':
            if output[-2] == 'while' and text == 'True':
                add('1') # common verbose idiom
            else:
                add(varmap.get(text, text))
        else:
            add(text)
    else:
        add(text)
    prev = tok

wr(''.join(output))

4

sed, 1074 (1390에서 다운)

볼 롤링을 얻기위한 매우 온화하고 낮은 매달린 과일 유형의 답변

/^$/d                  # Remove empty lines
/^[ <--TAB-->]*#/d     # Remove whole-line comments
s/    /<--TAB-->/g     # Replace 4 spaces with tabs
/^[^'"]*$/s/ *([|&:,<>=*/%+-]) */\1/g  # Remove spaces before/after operators

<--TAB-->실제 TAB문자로 교체

명백한 단점 :

  • 들여 쓰기는 입력 코드에서 정확히 4 칸으로 가정합니다.

우리는 더 여러 줄 문자열을지지 않습니다 때문에, 우리는 단지 / 선도적 인 더가있는 경우 사업자에서 후행 공백을하지 제거 '또는 "주어진 라인에. 이것은 향상 될 수 있지만 <sed regex는 항상 욕심이 많은 것에 대해 혼란스러워합니다> .

다음과 같이 테스트하십시오.

$ cat qs.py fizzbuzz.py cards.py | wc -c
1390
$ sed -rf pygolf.sed qs.py fizzbuzz.py cards.py | wc -c
1074
$ sed -rf pygolf.sed qs.py fizzbuzz.py cards.py | python
[-1, 0, 2, 3, 7, 8, 10, 57]
1
2
Fizz
...
98
Fizz
Buzz
Hand 11982
  AH AS 4H AC 2D 6S TS JS
  3D 3H QS QC 8S 7H AD KS
  KD 6H 5S 4D 9H JH 9S 3C
  JC 5D 5C 8C 9D TD KH 7C
  6C 2C TH QH 6D TC 4S 7S
  JD 7D 8H 9C 2H QD 4C 5H
  KC 8D 2S 3S
$ 

여러 줄 문자열을 확인할 필요는 없지만 마지막 두 줄은 반드시 업데이트해야합니다.
Nathan Merrill

트윗 담아 가기 연산자 선행 / 트레일 링 공간 1은 이제 조금 나아졌지 만 들여 쓰기 된 공간은 일반화하기가 훨씬 더 어려울 것입니다.
디지털 외상

3

파이썬 3.4, 1134

이 프로그램은 대부분의 프로그램에서 잘 작동합니다. 이상하게도 Sp3000 테스트 케이스는 프로그램보다 내 프로그램을 최적화하는 것이 훨씬 쉽습니다. 첫 번째 인수에 지정된 파일을 통해 입력이 승인됩니다. 실제 파일이 수정되었습니다.

import subprocess
from sys import argv

progamtext = open(argv[1]).read()

if 'argv' in progamtext or 'input' in progamtext or 'open' in programtext:#Make sure the program always produces the same results.
    exit(0)

program = subprocess.Popen(['C:\Python27\python', argv[1]], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
program.wait()
erroroutput1 = str(program.stderr.read())
output1 = str(program.stdout.read())
program = subprocess.Popen(['C:\Python27\python', argv[1]], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
program.wait()
erroroutput2 = str(program.stderr.read())
output2 = str(program.stdout.read())
if erroroutput1 != erroroutput2 or output1 != output2:#Make sure the program always produces the same results.
    exit(0)

newprog = ''
if erroroutput1:
    newprog += "import sys\n" + "sys.stderr.write("+ erroroutput1 + ')'
    if output1:
        newprog += "\n"
if output1:
    newprog += 'print ' + output1

if len(newprog) > len(progamtext):
    exit(0)

open(argv[1],mode='w').write(newprog)

작동 방식 :

먼저,이 프로그램은 프로그램이 사용자와 전혀 상호 작용하는지 또는 임의를 사용하는지 확인합니다. 그렇다면 프로그램이 수정되지 않은 것입니다. 다음으로 프로그램이 실행됩니다. 그런 다음 프로그램이로 바뀝니다 print "output". 마지막으로, 프로그램이 출력보다 짧으면 수정되지 않습니다.

최적화 된 Sp3000의 프로그램 :

import sys
sys.stderr.write(b'')
print b'0.540377721372\r\n3\r\n1\r\n7\r\n99\r\nf\r\n[5, 5]\r\n53\r\n53\r\n53\r\n'

Sp3000의 최고 보너스 프로그램 :

최적화 된 버전은 .001 %에 불과합니다.

import sys
sys.stderr.write(b'')
print b'B\r\n'

1
argv, input및 이외의 다른 외부 효과가 있으므로 random코드가 손상 될 것이라고 확신합니다. ;)
Martin Ender

2
하 어쩌면 나는 비결정론을 넣어야했을 것입니다- print id(0)좋은 것입니다.
Sp3000

@Martin 고정 (대부분). :)
TheNumberOne


매우 창의적입니다.
Nathan Merrill
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.