Doğru şekilde golf oynuyor muyum?


12

Code Golfing'in uygun olup olmadığını merak ediyorum. Küçük bir karma programı Python'da tek bir ifadeye dönüştürmek için kendime meydan okudum. İlk olarak şununla başladım:

from itertools import permutations
from string import ascii_lowercase
from random import sample

def test():
    chars = sample(ascii_lowercase, 9)
    sums = list(map(h, permutations(chars)))
    if len(set(sums)) == len(sums):
       print("unique results for permutations of given string")
    else:
       print("duplicate entries present in test results")

def h(s):
    r = 0
    for i in range(len(s)):
        r += ord(s[i]) << (i * len(s))
    return r

test()

Daha sonra işlevi özyinelemeli hale getirdim:

def h(s, i=0):
    if i < len(s) - 1: return h(s, i+1) + ord(s[i]) << (i * len(s))
    else: return ord(s[i]) << (i * len(s))

Kodu tekrarlamak için bir lambda ile kısaltmayı denedim (işe yaramadı):

def h(s, i=0, f=lambda s,i: ord(s[i]) << (i * len(s))):
    if i < len(s) - 1: return h(s, i+1) + f(s,i)
    else: return f(s,i)

Sonunda bir lambda ile sonuçlandım:

h=lambda s,i=0:h(s,i+1)+ord(s[i])<<(i*len(s))if i<len(s)-1 else ord(s[i])<<(i*len(s))

Programın tek bir ifade olmasını istedim, bu yüzden önce şunu buldum:

def test():
    chars = sample(ascii_lowercase, 9)
    sums = list(map((lambda s,i=0,f=lambda s,i,f:f(s,i+1,f)+ord(s[i])<<(i*len(s))if i<len(s)-1 else ord(s[i])<<(i*len(s)):f(s,i,f)), permutations(chars)))
    if len(set(sums)) == len(sums):
       print("unique results for permutations of given string")
    else:
       print("duplicate entries present in test results")

Ve son olarak:

print((lambda x=list(map((lambda s,i=0,f=lambda s,i,f:f(s,i+1,f)+ord(s[i])<<(i*len(s))if i<len(s)-1 else ord(s[i])<<(i*len(s)):f(s,i,f)), permutations(sample(ascii_lowercase, 9)))): "unique results for permutations of given string" if len(set(x)) == len(x) else "duplicate entries present in test results")())

Codegolf sorunları bu şekilde mi çözüldü? Bu tür şeyleri hiç gerçekten yapmadım, bu yüzden şu anda doğru olup olmadığını bilmek istiyorum.

Değişiklik: Bu program tüm işleri sizin için yapar; bu yüzden burada fonksiyona atıfta bulunacağım: Girdi olarak, program belirli bir dizenin tüm permütasyonlarını alır; burada dize rastgele seçilen dokuz karakterdir ascii_lowercase. Çıktı, belirli bir dizginin her bir permütasyon sonucunun, farklı bir dizge için başka bir sonucun kopyası olup olmadığını tanımlayan, insan tarafından okunabilen bir dizgidir. Tüm permütasyonlar için kopya yoksa, program başarıyı gösterir. Dokuz karakter, kutumda tekrar tekrar hesaplanabilen en büyük karakter uzunluğu olarak seçildi.

Değişiklik II Çalışkan bir okuyucu tarafından işaret edildiği gibi, tarif edilen amaç eşlik eden kodla elde edilemez. Test durumu açıkça yetersizdir.


3
Bu iyi bir ipucu sorusuna benziyor ve golf sürecinizi ayrıntılı olarak gösterdiğiniz için memnunum. Ama "karma" programla ne demek istediğini bilmiyorum. Girdinin nasıl alınacağını, çıktının nasıl verileceğini ve çıktının girdiyle olan ilişkisini açıklayan bir özellik göndermelisiniz.
xnor

@xnor bu yeterli mi?
motoku

Kod golf için, bu isteğe bağlı alanlardan bazılarını kesinlikle kaldırmalısınız. Ayrıca, yazdırma daha kısa olduğu için Python 2'yi kullanın. print"x"yerineprint("x")
mbomb007

Ve yerine bir liste kavrama kullanın list()?
mbomb007

3
İşleminiz iyi görünüyor. Bir programla başlayın, deneme / hata ile kısaltın. Daha fazla deneyim edinin ve python ipuçlarına göz atın ve kısa sürede harika bir iş çıkarırsınız.
Geobits

Yanıtlar:


11

Golf için 'doğru' bir yol yoktur. İyi iş çıkardınız ve kullandığınız işlem oldukça standart. Programı tek bir ifadeye dönüştürmek genellikle bir gereklilik değildir.

Eğer yardımcı olursa, programınıza golf oynamaya nasıl yaklaşacağım ...

Karma işlevinde, for ifadesi bir toplamla değiştirilebilir:

def h(s):
    r = 0
    r = sum(ord(s[i]) << (i * len(s)) for i in range(len(s)))
    return r

Bu daha sonra lambda işlevi olarak tanımlanabilir:

h = lambda s: sum(ord(s[i]) << (i * len(s)) for i in range(len(s)))

Ve şimdi gereksiz boşlukları ve köşeli parantezleri kaldırıyoruz:

h=lambda s:sum(ord(s[i])<<i*len(s)for i in range(len(s)))

Sp3000'in işaret ettiği gibi, bu numaralandırma ile daha da kısaltılabilir:

h=lambda s:sum(ord(x)<<i*len(s)for i,x in enumerate(s))

Test fonksiyonuna geçerek ilk iki satırını birleştiriyoruz:

def test():
    sums = list(map(h, permutations(sample(ascii_lowercase, 9))))
    ...

Her iki işlev de yalnızca bir kez kullanıldığından, her şeyi satır içinde taşıyabiliriz:

sums = list(map(lambda s:sum(ord(x)<<i*len(s)for i,x in enumerate(s)), permutations(sample(ascii_lowercase, 9))))
...

Bu bir liste kavrayışı olarak daha kısadır:

sums = [sum(ord(x)<<i*len(s)for i,x in enumerate(s)) for s in permutations(sample(ascii_lowercase, 9))]

Sonra, daha kısa bir isim veriyoruz ve gereksiz alanları tekrar kaldırıyoruz:

x=[sum(ord(x)<<i*len(s)for i,x in enumerate(s))for s in permutations(sample(ascii_lowercase,9))]

İf ifadesi yazdırma işlevinin içine taşınabilir:

print('unique...' if len(set(x)) == len(x) else 'duplicate...')

Bununla birlikte, kullanımı genellikle daha kısadır ve / veya:

print(len(set(x)) == len(x) and 'unique...' or 'duplicate...')

Yana len(x)değişmeyen şu hesaplamayı ve değerini hardcode:

print(len(set(x)) == 362880 and 'unique...' or 'duplicate...')

Gereksiz alanları kaldırdıktan ve karşılaştırmayı değiştirdikten sonra:

print(len(set(x))<362880and'duplicate...'or'unique...')

Bu, her şeyi tek bir ifadeye taşımamızı sağlar:

print(len(set([sum(ord(x)<<i*len(s)for i,x in enumerate(s))for s in permutations(sample(ascii_lowercase,9))]))<362880and'duplicate...'or'unique...')

Ve şimdi bunun yerine belirli bir kavrayış kullanabiliriz:

print(len({sum(ord(x)<<i*len(s)for i,x in enumerate(s))for s in permutations(sample(ascii_lowercase,9))})<362880and'duplicate...'or'unique...')

Sonuç, ithalat hariç 210 bayttır. Bir sonraki adım muhtemelen ithalatı veya uzun ipleri aşağı çekmek olacaktır.


7
Funnily yeterince, enumeratedaha kısa olduğunu düşünüyorum :h=lambda s:sum(ord(x)<<i*len(s)for i,x in enumerate(s))
Sp3000

@ Sp3000 oh güzel! Her yapının günü vardır: D
grc
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.