ฉันเขียนรหัสกอล์ฟอย่างถูกต้องหรือไม่?


12

ฉันอยากรู้อยากเห็นถ้าฉันเป็นรหัสกอล์ฟอย่างถูกต้อง ฉันตั้งความท้าทายสำหรับตัวเองในการสร้างโปรแกรมแฮชขนาดเล็กเป็นคำสั่งเดียวใน Python ก่อนอื่นฉันเริ่มด้วย:

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

ฉันทำฟังก์ชันซ้ำแล้วซ้ำอีก:

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

ฉันลองย่อแลมบ์ดาด้วยการทำซ้ำรหัส (มันไม่ทำงาน):

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)

ในที่สุดฉันก็จบลงด้วยแลมบ์ดา:

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

ฉันต้องการให้โปรแกรมเป็นประโยคเดียวดังนั้นก่อนอื่นเลยฉันมาด้วย:

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

และสุดท้ายฉันก็จบลงด้วย:

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 หรือไม่? ฉันไม่เคยทำสิ่งนี้มาก่อนเลยตอนนี้ฉันแค่อยากรู้ว่าฉันทำถูกไหม

การแก้ไข:โปรแกรมนี้ทำงานให้คุณทั้งหมด; ดังนั้นฉันจะอ้างถึงฟังก์ชั่นที่นี่: เป็นอินพุตโปรแกรมใช้ในการเรียงสับเปลี่ยนทั้งหมดของสตริงที่กำหนด; ascii_lowercaseนี่สตริงเก้าตัวอักษรสุ่มเลือกจาก เอาต์พุตเป็นสตริงที่มนุษย์สามารถอ่านได้ซึ่งกำหนดว่าผลลัพธ์ของการเปลี่ยนลำดับของสตริงที่กำหนดแต่ละรายการจะซ้ำกันกับผลลัพธ์อื่นสำหรับสตริงอื่น หากไม่มีการซ้ำซ้อนสำหรับการเรียงสับเปลี่ยนทั้งหมดโปรแกรมจะระบุว่าสำเร็จ ตัวละครเก้าตัวถูกเลือกว่าเป็นความยาวของตัวละครที่ใหญ่ที่สุดที่คำนวณได้ง่าย ๆ บนกล่องของฉัน

การแก้ไข IIตามที่ผู้ชี้แนะผู้ชี้แนะวัตถุประสงค์ที่อธิบายไว้ไม่ได้รับผ่านรหัสที่มาพร้อมกัน กรณีทดสอบไม่เพียงพออย่างเห็นได้ชัด


3
นี่เป็นคำถามที่เป็นเคล็ดลับที่ดีและฉันยินดีที่ได้เห็นว่าคุณได้แสดงขั้นตอนการเล่นกอล์ฟอย่างละเอียดแล้ว แต่ฉันไม่รู้ว่าคุณหมายถึงอะไรโดยโปรแกรม "hashing" คุณควรโพสต์ข้อมูลจำเพาะที่อธิบายถึงวิธีการป้อนข้อมูลวิธีการรับเอาต์พุตและความสัมพันธ์ใดที่เอาต์พุตต้องมีกับอินพุต
xnor

@xnor ไม่เพียงพอหรือไม่
motoku

สำหรับโค้ดกอล์ฟคุณควรลบช่องว่างเพิ่มเติมเหล่านั้นออกอย่างแน่นอน นอกจากนี้ให้ใช้ Python 2 แทนเนื่องจากการพิมพ์สั้นลง print"x"แทนprint("x")
mbomb007

และใช้รายการความเข้าใจแทนlist()?
mbomb007

3
กระบวนการของคุณดูดี เริ่มด้วยโปรแกรมทำให้สั้นลงโดยการลองผิดลองถูก รับประสบการณ์มากขึ้นและเรียกดูเคล็ดลับหลามและคุณจะทำได้ดีในเวลา
Geobits

คำตอบ:


11

ไม่มีวิธีที่ถูกต้องสำหรับการเล่นกอล์ฟ คุณทำได้ดีมากและกระบวนการที่คุณใช้อยู่นั้นค่อนข้างเป็นมาตรฐาน การทำให้โปรแกรมเป็นคำสั่งเดียวไม่ได้เป็นข้อกำหนด

ถ้ามันช่วยได้นี่คือวิธีที่ฉันจะตีกอล์ฟลงโปรแกรมของคุณ ...

ในฟังก์ชัน hashing คำสั่ง for สามารถถูกแทนที่ด้วยผลรวม:

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

สิ่งนี้สามารถนิยามได้ว่าเป็นฟังก์ชัน lambda:

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

และตอนนี้เราลบช่องว่างและวงเล็บเหลี่ยมที่ไม่จำเป็นออก:

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

ในฐานะที่เป็น Sp3000 ชี้ให้เห็นสิ่งนี้สามารถสั้นลงอีกด้วยแจกแจง:

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

ย้ายไปยังฟังก์ชันทดสอบเรารวมสองบรรทัดแรกเข้าด้วยกัน:

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

เนื่องจากฟังก์ชั่นทั้งสองนี้ใช้เพียงครั้งเดียวเราจึงสามารถย้ายทุกอย่างแบบอินไลน์:

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

นี่คือความเข้าใจสั้นกว่ารายการ:

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

ต่อไปเราตั้งชื่อให้สั้นลงและลบช่องว่างที่ไม่จำเป็นออกไปอีกครั้ง:

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

คำสั่ง if สามารถย้ายภายในฟังก์ชั่นการพิมพ์:

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

อย่างไรก็ตามโดยปกติจะใช้งานสั้นกว่าและ / หรือ:

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

เนื่องจากlen(x)ไม่เปลี่ยนแปลงเราสามารถคำนวณและฮาร์ดโค้ดมูลค่าได้:

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

หลังจากลบช่องว่างที่ไม่จำเป็นและสลับไปมาระหว่างการเปรียบเทียบเราได้รับ:

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

สิ่งนี้ช่วยให้เราย้ายทุกอย่างเป็นคำสั่งเดียว:

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

และตอนนี้เราสามารถใช้ชุดความเข้าใจแทน:

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

ผลลัพธ์คือ 210 ไบต์ไม่รวมการนำเข้า ขั้นตอนต่อไปอาจจะนำเข้าจากต่างประเทศหรือสายยาว


7
สนุกมากฉันคิดว่าenumerateสั้นกว่า:h=lambda s:sum(ord(x)<<i*len(s)for i,x in enumerate(s))
Sp3000

@ Sp3000 โอ้ดี! อาคารทุกหลังมีวันที่: D
grc
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.