Apakah saya bermain golf dengan benar?


12

Saya ingin tahu apakah saya Code Golfing dengan benar. Saya mengatur tantangan bagi diri saya untuk membuat program hashing kecil menjadi satu pernyataan dengan Python. Saya mulai dengan:

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()

Saya kemudian membuat fungsi rekursif:

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

Saya mencoba memperpendeknya dengan lambda untuk mengulang kode (tidak berhasil):

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)

Akhirnya saya berakhir dengan lambda:

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

Saya ingin program menjadi satu pernyataan, jadi pertama-tama saya membuat:

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")

Dan terakhir saya berakhir dengan:

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")())

Apakah ini bagaimana masalah codegolf diselesaikan? Saya tidak pernah benar-benar melakukan hal semacam ini, jadi sekarang saya hanya ingin tahu apakah saya melakukannya dengan benar.

Amandemen: Program ini melakukan semua pekerjaan untuk Anda; jadi di sini saya akan merujuk ke fungsi: Sebagai input, program mengambil semua permutasi dari string yang diberikan; di sini string diambil sembilan karakter secara acak ascii_lowercase. Outputnya adalah string yang dapat dibaca manusia yang mendefinisikan apakah hasil dari setiap permutasi dari string yang diberikan adalah duplikat dari hasil lain untuk string yang berbeda. Jika tidak ada duplikat untuk semua permutasi, program menunjukkan keberhasilan. Sembilan karakter dipilih sebagai panjang karakter terbesar yang siap dihitung berulang kali di kotak saya.

Amandemen II Seperti yang ditunjukkan oleh pembaca yang rajin belajar, tujuan yang dimaksudkan tidak diperoleh melalui kode yang menyertainya. Kasus uji jelas tidak memadai.


3
Ini sepertinya pertanyaan kiat yang bagus, dan saya senang melihat Anda telah menunjukkan proses bermain golf Anda secara detail. Tapi saya tidak tahu apa yang Anda maksud dengan program "hashing". Anda harus memposting spesifikasi yang menjelaskan bagaimana input harus diambil, bagaimana output akan diberikan, dan apa hubungan output yang harus dimiliki dengan input.
xnor

@ xnor apakah itu cukup?
motoku

Untuk golf kode, Anda harus menghapus lebih banyak ruang opsional itu. Juga, gunakan Python 2 sebagai gantinya, karena pencetakan lebih pendek. print"x"bukannyaprint("x")
mbomb007

Dan gunakan pemahaman daftar bukan list()?
mbomb007

3
Proses Anda tampaknya baik-baik saja. Mulailah dengan sebuah program, disingkat dengan percobaan / kesalahan. Dapatkan lebih banyak pengalaman dan telusuri kiat python dan Anda akan melakukan yang terbaik dalam waktu singkat.
Geobits

Jawaban:


11

Tidak ada cara yang 'benar' untuk bermain golf. Anda telah melakukannya dengan baik, dan proses yang Anda gunakan cukup standar. Membuat program menjadi satu pernyataan biasanya bukan keharusan.

Jika ini membantu, inilah cara saya mendekati golf di program Anda ...

Dalam fungsi hashing, pernyataan for dapat diganti dengan jumlah:

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

Ini kemudian dapat didefinisikan sebagai fungsi lambda:

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

Dan sekarang kami menghapus spasi dan tanda kurung yang tidak perlu:

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

Seperti yang Sp3000 tunjukkan, ini dapat dipersingkat lebih lanjut dengan menyebutkan:

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

Beralih ke fungsi tes, kami menggabungkan dua baris pertamanya:

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

Karena kedua fungsi hanya digunakan satu kali, kami dapat memindahkan semua yang sebaris:

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

Ini lebih pendek sebagai pemahaman daftar:

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

Selanjutnya, kami memberikan nama yang lebih pendek dan menghapus spasi yang tidak perlu lagi:

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

Pernyataan if dapat dipindahkan di dalam fungsi cetak:

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

Namun, biasanya lebih pendek untuk digunakan dan / atau:

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

Karena len(x)tidak berubah, kami dapat menghitung dan meng-hardcode nilainya:

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

Setelah menghapus spasi yang tidak perlu dan beralih di antara perbandingan, kami mendapatkan:

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

Ini memungkinkan kita memindahkan semuanya menjadi satu pernyataan:

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...')

Dan sekarang kita bisa menggunakan pemahaman set sebagai gantinya:

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...')

Hasilnya adalah 210 byte, tidak termasuk impor. Langkah selanjutnya mungkin akan menurunkan impor atau string panjang.


7
Cukup lucu, saya pikir enumeratelebih pendek:h=lambda s:sum(ord(x)<<i*len(s)for i,x in enumerate(s))
Sp3000

@ Sp3000 oh bagus! Setiap builtin memiliki harinya: D
grc
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.