코드 골프를 올바르게하고 있습니까?


12

Code Golfing이 제대로되어 있는지 궁금합니다. 나는 작은 해싱 프로그램을 파이썬에서 하나의 문장으로 만들기 위해 도전했다. 나는 처음부터 시작했다.

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 문제가 해결되는 방법입니까? 나는 실제로 이런 종류의 일을 한 적이 없으므로 지금 당장 내가 잘하고 있는지 알고 싶습니다.

개정 : 이 프로그램은 모든 업무를 수행합니다. 여기서는 함수를 참조 할 것입니다. 입력으로 프로그램은 주어진 문자열의 모든 순열을 취합니다. 여기서 문자열은에서 임의로 선택한 9 개의 문자입니다 ascii_lowercase. 출력은 주어진 문자열의 각 순열 결과가 다른 문자열에 대한 다른 결과의 복제인지 여부를 정의하는 사람이 읽을 수있는 문자열입니다. 모든 순열에 대해 중복이없는 경우 프로그램은 성공을 나타냅니다. 9 개의 문자는 내 상자에서 쉽게 반복적으로 계산되는 가장 큰 문자 길이로 선택되었습니다.

개정 II Studious 독자가 지적한 바와 같이, 기술 된 의도 된 목적은 첨부 된 코드를 통해 얻을 수 없다. 테스트 사례가 분명히 부적절합니다.


3
이것은 좋은 팁 질문처럼 보입니다. 골프 과정을 자세히 보여 드리겠습니다. 그러나 "해싱"프로그램이 무슨 뜻인지 모르겠습니다. 입력을받는 방법, 출력 방법, 출력과 입력의 관계를 설명하는 사양을 게시해야합니다.
xnor

@ xnor로 충분합니까?
motoku

코드 골프의 경우 옵션 공간을 더 제거해야합니다. 또한 인쇄 시간이 짧기 때문에 대신 Python 2를 사용하십시오. print"x"대신print("x")
mbomb007

그리고 대신 목록 이해력을 사용 list()합니까?
mbomb007

3
당신의 과정은 괜찮아 보입니다. 시행 착오로 단축되는 프로그램으로 시작하십시오. 더 많은 경험을 얻고 파이썬 팁을 탐색 하면 곧 좋은 결과를 얻을 수 있습니다.
Geobits

답변:


11

골프를하는 '올바른'방법은 없습니다. 당신은 잘했고, 사용한 과정은 상당히 표준입니다. 프로그램을 하나의 문장으로 만드는 것이 일반적으로 요구되는 것은 아닙니다.

도움이된다면 다음은 골프 프로그램에 접근하는 방법입니다.

해싱 함수에서 for 문은 다음 합계로 대체 될 수 있습니다.

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

그런 다음 람다 함수로 정의 할 수 있습니다.

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 함수 안에서 이동할 수 있습니다 :

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.