Auto-meta-code-golf


13

Bạn phát ốm với tất cả những thử thách của codegolf. Do đó, bạn quyết định viết một chương trình sẽ tự động đánh gôn một số mã Python cho bạn. Có 3 trường hợp thử nghiệm:

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)

Quy tắc:

  1. Chương trình của bạn không được nhắm mục tiêu mã tôi đã đăng cụ thể và phải hoạt động với bất kỳ mã Python 2 nào. Tôi bảo lưu quyền thay đổi mã nguồn đang được mã hóa. Bạn có thể giả định rằng không có chuỗi nhiều dòng (vì vậy bạn không xây dựng trình phân tích cú pháp đầy đủ) và người dân địa phương () không được gọi.

  2. Đầu ra của chương trình của bạn sẽ chạy theo cách giống hệt như mã nguồn ban đầu. (Cụ thể, nó phải tạo ra cùng một đầu ra. Tên biến và cấu trúc ngôn ngữ có thể được thay đổi, miễn là đầu ra vẫn giữ nguyên)

  3. Bạn có thể sử dụng STDIO hoặc Tệp để thực hiện nhập / xuất mã nguồn.

Điểm của bạn sẽ là tổng số byte của đầu ra chương trình của bạn.

(Mã được liệt kê ở trên đã được lấy từ http://rosettacode.org/ theo Giấy phép Tài liệu Miễn phí GNU 1.2 )



3
Đây là một trường hợp thử nghiệm tiền thưởng cho mọi người để thử, để được sai lệch.
Sp3000

4
Mô hình của bạn để xác định xem đầu ra " [chạy] theo cách giống hệt như mã nguồn gốc " là gì? Ví dụ, ví dụ thứ hai, tôi tin rằng việc loại bỏ if __name__ == '__main__':sẽ ảnh hưởng đến hành vi trong một số bối cảnh nhưng không ảnh hưởng đến hành vi khác. Đối với một ví dụ khác, nếu đầu vào không được giả định rằng nó đọc một int từ stdin và ném một loại ngoại lệ nếu được đưa ra một thứ khác, thì đầu vào được đánh gôn có thể ném một loại ngoại lệ khác nếu được cung cấp một số nguyên không?
Peter Taylor

2
Thế còn một chương trình như thế này : random_long_variable=0;print locals()?
Justin

Câu trả lời:


4

Python 2.7, 794

Tôi đã có ý định xây dựng một công cụ khai thác cho Python trong một thời gian, vì vậy đây là một cơ hội tốt để điều tra vấn đề.

Chương trình sử dụng kết hợp phân tích biểu thức chính quy và các hoạt động của trình phân tích cú pháp Python. Không gian trắng được thu nhỏ. Biến được xác định bởi người dùng được thay thế bằng một biến chữ cái duy nhất (không được sử dụng!). Cuối cùng, while Truetuyên bố được đưa vào chế độ ăn kiêng.

Cả ba trường hợp kiểm tra đều xác minh là đang chạy chính xác. Tôi có thể tưởng tượng một số ví dụ bệnh lý có thể dẫn đến lỗi trong mã được tạo nhưng thuật toán sẽ mạnh mẽ trong hầu hết các trường hợp.

Các kết quả

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

Đầu ra

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 (giảm từ 1390)

Câu trả lời rất nhẹ, ít quả treo, để có được quả bóng lăn:

/^$/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

Thay thế <--TAB-->bằng TABnhân vật thật

Rõ ràng thiếu sót:

  • Các thụt lề được cho là chính xác 4 khoảng trắng trong mã đầu vào.

Vì chúng ta có thể giả sử không có chuỗi nhiều dòng, nên chúng ta chỉ loại bỏ các khoảng trắng ở đầu / cuối từ các toán tử nếu không có 'hoặc "trên dòng đã cho. Điều này có thể được cải thiện, nhưng <lầm bầm điều gì đó về sed regex luôn luôn tham lam> .

Kiểm tra như sau:

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

Bạn không cần kiểm tra các chuỗi nhiều dòng, nhưng hai chuỗi cuối của bạn chắc chắn cần được cập nhật.
Nathan Merrill

@NathanMerrill yup. Bây giờ toán tử dẫn đầu / dấu cách không gian tốt hơn một chút, nhưng phần thụt lề sẽ khó khái quát hơn nhiều - và là nơi tôi nhận được khoảng 2/3 mức tăng.
Chấn thương kỹ thuật số

3

Con trăn 3,4, 1134

Chương trình này sẽ hoạt động tốt cho hầu hết các chương trình. Thật kỳ lạ, trường hợp thử nghiệm Sp3000 dễ dàng tối ưu hóa cho chương trình của tôi hơn các chương trình của bạn. Đầu vào được chấp nhận thông qua tệp được chỉ định trong đối số đầu tiên. Các tập tin thực tế được sửa đổi.

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)

Làm thế nào nó hoạt động:

Đầu tiên, chương trình này kiểm tra xem chương trình của bạn có tương tác với người dùng hay sử dụng ngẫu nhiên hay không. Nếu có, chương trình không được sửa đổi. Tiếp theo, chương trình được chạy. Chương trình sau đó được thay thế bằng print "output". Cuối cùng, nếu chương trình ngắn hơn đầu ra của nó, nó không được sửa đổi.

Chương trình của Sp3000, được tối ưu hóa:

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'

Chương trình siêu thưởng của Sp3000, được tối ưu hóa:

Phiên bản tối ưu hóa chỉ tắt 0,001% thời gian.

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

1
Tôi chắc chắn có những hiệu ứng bên ngoài khác argv, inputrandom, mã của bạn sẽ bị hỏng. ;)
Martin Ender

2
Hah Có lẽ tôi nên đưa vào một số chủ nghĩa không xác định - print id(0)là một điều tốt.
Sp3000

@Martin Đã sửa (hầu hết). :)
TheNumberOne


Heh, rất sáng tạo.
Nathan Merrill
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.