Otomatik meta kod golf


13

Tüm codegolf zorluklarından bıktınız. Bu nedenle otomatik olarak sizin için bazı Python kodlarını golf edecek bir program yazmaya karar verirsiniz. 3 test durumu vardır:

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)

Kurallar:

  1. Programınız özel olarak gönderdiğim kodu hedeflememeli ve herhangi bir Python 2 koduyla çalışmalıdır. Codegolfed kaynak kodunu değiştirme hakkını saklı tutarım. Çok satırlı dizeler olmadığını (tam dolu bir ayrıştırıcı oluşturmadınız) ve locals () işlevinin çağrılmadığını varsayabilirsiniz.

  2. Programınızın çıktısı, orijinal kaynak koduyla aynı şekilde çalışmalıdır. (Yani, aynı çıktıyı üretmelidir. Çıktı aynı kaldığı sürece, değişken adları ve dil yapıları değiştirilebilir)

  3. Kaynak kodun giriş / çıkışını yapmak için STDIO veya bir Dosya kullanabilirsiniz.

Puanınız, programınızın çıktısının bayt toplamı olacaktır.

(Yukarıda listelenen kod , GNU Özgür Belgeleme Lisansı 1.2 altında http://rosettacode.org/ adresinden alınmıştır )



3
İşte insanların denemesi, aldatıcı olması için bir bonus test örneği .
Sp3000

4
Çıktınızın " orijinal kaynak koduyla aynı şekilde " çalışıp çalışmadığını belirlemek için modeliniz nedir ? Örneğin, ikinci örnek için, kaldırmanın if __name__ == '__main__':bazı bağlamlardaki davranışı etkileyeceğine, diğerlerinde etkilemeyeceğine inanıyorum . Başka bir örnek için, çözülmemiş girdi stdin'den bir int okuduğunu varsayar ve başka bir şey verilirse bir tür istisna atarsa, golfed girdisi tamsayı olmayan bir şekilde verilirse farklı bir istisna atabilir mi?
Peter Taylor

2
Peki böyle bir programa ne dersiniz random_long_variable=0;print locals()?
Justin

Yanıtlar:


4

Python 2.7, 794

Bir süredir Python için bir madencilik yapmak için anlam ifade ettim, bu yüzden sorunu araştırmak için iyi bir fırsat.

Program, düzenli ifade analizi ve Python ayrıştırıcı işlemlerinin bir karışımını kullanır. Beyaz alan en aza indirilir. Kullanıcı tarafından tanımlanan değişkenin yerine tek harfli bir değişken gelir (kullanımda değildir!). Sonunda while Trueifade bir diyete konur.

Üç test vakasının tümü doğru çalıştığını doğrular. Oluşturulan kodda hatalara neden olabilecek bazı patolojik örnekler hayal edebiliyorum, ancak algoritma çoğu durumda sağlam olmalıdır.

Sonuçlar

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

Çıktı

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)

kod

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 (aşağı 1390'dan)

Topu yuvarlamak için çok hafif, düşük asılı meyve tipi cevap:

/^$/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-->Gerçek TABkarakterlerle değiştir

Açıkça eksiklik:

  • Girintilerin giriş kodunda tam olarak 4 boşluk olduğu varsayılmıştır.

Çok satırlı dizeleri kabul edemeyeceğimiz için, yalnızca belirli bir satırda 'veya "satırda operatörlerden önde gelen / sondaki boşlukları çıkarırız . Bu geliştirilebilir, ancak <sed regex her zaman açgözlü olma hakkında bir şeyler mırıldanıyor> .

Aşağıdaki gibi test edin:

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

Çok satırlı dizeleri kontrol etmenize gerek yoktur, ancak son ikinizin kesinlikle güncellenmesi gerekir.
Nathan Merrill

@NathanMerrill yup. Birincisi önde gelen / sondaki alan şimdi biraz daha iyi, ama girintiyi genelleştirmek çok daha zor olacak - ve kazancın yaklaşık 2 / 3'ünü elde ettiğim yer.
Dijital Travma

3

Python 3.4, 1134

Bu program çoğu program için iyi çalışmalıdır. Garip bir şekilde, Sp3000 test senaryosunu programım için optimize etmek programlarınızdan çok daha kolay. Giriş, ilk argümanda belirtilen dosya üzerinden kabul edilir. Gerçek dosya değiştirilir.

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)

Nasıl çalışır:

İlk olarak, bu program, programınızın kullanıcıyla etkileşime girip girmediğini veya rastgele kullanıp kullanmadığını kontrol eder. Eğer öyleyse, program değiştirilmez. Sonra program çalıştırılır. Program daha sonra ile değiştirilir print "output". Son olarak, program çıktısından daha kısaysa, değiştirilmez.

Sp3000'in programı, optimize edilmiştir:

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'in süper bonus programı, optimize edilmiştir:

Optimize edilmiş sürüm yalnızca% .001 oranında kapalıdır.

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

1
Ben başka dış etkiler vardır eminim argv, inputve randomkod kırardı hangi. ;)
Martin Ender

2
Hah. Belki belirli bir determinizm koymamalıydım - print id(0)bu iyi bir şey.
Sp3000

@Martin (çoğunlukla) düzeltildi. :)
TheNumberOne


Heh, çok yaratıcı.
Nathan Merrill
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.