Tôi có chơi golf đúng cách không?


12

Tôi tò mò nếu tôi chơi Golf đúng cách. Tôi tự đặt ra thử thách để biến một chương trình băm nhỏ thành một câu lệnh duy nhất trong Python. Lần đầu tiên tôi bắt đầu với:

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

Sau đó tôi đã thực hiện chức năng đệ quy:

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

Tôi đã thử rút ngắn nó bằng lambda để lặp lại mã (nó không hoạt động):

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)

Cuối cùng tôi đã kết thúc với một 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))

Tôi muốn chương trình là một tuyên bố, vì vậy trước tiên tôi đã nghĩ ra:

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

Và cuối cùng tôi đã kết thúc với:

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

Đây có phải là cách các vấn đề codegolf được giải quyết? Tôi chưa bao giờ thực sự làm điều này, vì vậy ngay bây giờ tôi chỉ muốn biết liệu tôi có làm đúng hay không.

Sửa đổi: Chương trình này thực hiện tất cả các công việc cho bạn; Vì vậy, ở đây tôi sẽ đề cập đến chức năng: Là đầu vào, chương trình có tất cả các hoán vị của một chuỗi nhất định; ở đây chuỗi có chín ký tự được chọn ngẫu nhiên ascii_lowercase. Đầu ra là một chuỗi có thể đọc được bằng con người xác định xem kết quả của mỗi lần hoán vị của chuỗi đã cho có trùng lặp với kết quả khác cho một chuỗi khác không. Nếu không có sự trùng lặp cho tất cả các hoán vị, chương trình chỉ ra thành công. Chín ký tự được chọn là độ dài lớn nhất của các ký tự dễ dàng được tính toán lặp lại trên hộp của tôi.

Sửa đổi II Như được chỉ ra bởi một người đọc hiếu học, mục đích dự định được mô tả không có được thông qua mã đi kèm. Các trường hợp thử nghiệm rõ ràng là không đầy đủ.


3
Đây có vẻ là một câu hỏi mẹo hay và tôi rất vui khi thấy bạn đã trình bày quá trình chơi gôn của mình một cách chi tiết. Nhưng tôi không biết ý của bạn là gì bởi chương trình "băm". Bạn nên đăng một thông số giải thích cách thức đầu vào được thực hiện, cách đưa ra đầu ra và mối quan hệ đầu ra phải có với đầu vào.
xnor

@xnor có đủ không?
motoku

Đối với mã golf, bạn chắc chắn nên loại bỏ thêm một số không gian tùy chọn. Ngoài ra, sử dụng Python 2 thay thế, vì in ngắn hơn. print"x"thay vìprint("x")
mbomb007

Và sử dụng một danh sách hiểu thay vì list()?
mbomb007

3
Quá trình của bạn có vẻ tốt. Bắt đầu với một chương trình, rút ​​ngắn bằng thử nghiệm / lỗi. Có thêm kinh nghiệm và duyệt các mẹo về python và bạn sẽ làm rất tốt trong thời gian ngắn.
Geobits

Câu trả lời:


11

Không có cách "đúng" để chơi gôn. Bạn đã hoàn thành tốt và quy trình bạn đã sử dụng khá chuẩn. Làm cho chương trình thành một tuyên bố thường không phải là một yêu cầu mặc dù.

Nếu nó hữu ích, đây là cách tôi sẽ tiếp cận việc chơi golf trong chương trình của bạn ...

Trong hàm băm, câu lệnh for có thể được thay thế bằng một tổng:

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

Điều này sau đó có thể được định nghĩa là một hàm lambda:

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

Và bây giờ chúng tôi xóa các khoảng trắng và dấu ngoặc không cần thiết:

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

Như Sp3000 đã chỉ ra, điều này có thể được rút ngắn hơn nữa với liệt kê:

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

Chuyển sang chức năng kiểm tra, chúng tôi hợp nhất hai dòng đầu tiên của nó:

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

Vì cả hai chức năng chỉ được sử dụng một lần, chúng tôi có thể di chuyển mọi thứ nội tuyến:

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

Điều này ngắn hơn như là một sự hiểu biết danh sách:

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

Tiếp theo, chúng tôi đặt cho nó một tên ngắn hơn và loại bỏ các khoảng trống không cần thiết một lần nữa:

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

Câu lệnh if có thể được di chuyển bên trong chức năng in:

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

Tuy nhiên, nó thường ngắn hơn để sử dụng và / hoặc:

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

len(x)không thay đổi, chúng tôi có thể tính toán và mã hóa giá trị của nó:

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

Sau khi loại bỏ các không gian không cần thiết và chuyển qua so sánh, chúng tôi nhận được:

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

Điều này cho phép chúng tôi di chuyển mọi thứ vào một tuyên bố:

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

Và bây giờ chúng ta có thể sử dụng một sự hiểu biết thiết lập thay thế:

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

Kết quả là 210 byte, không bao gồm nhập khẩu. Bước tiếp theo có lẽ là đánh gôn xuống hàng nhập khẩu hoặc dây dài.


7
Thật thú vị, tôi nghĩ enumeratelà ngắn hơn:h=lambda s:sum(ord(x)<<i*len(s)for i,x in enumerate(s))
Sp3000

@ Sp3000 ơi thật tuyệt! Mọi nội dung đều có ngày của nó: D
grc
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.