適切にコードゴルフをしていますか?


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

プログラムを1つのステートメントにしたかったので、最初に思いつきました。

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専門家の読者が指摘したように、記載されている意図された目的は、付随するコードからは得られません。テストケースは明らかに不十分です。


3
これは良いヒントの質問のように見えます。ゴルフのプロセスを詳細に示してくれたことを嬉しく思います。しかし、私はあなたが「ハッシュ」プログラムで何を意味するのか分かりません。入力の取得方法、出力の指定方法、および出力と入力の関係を説明する仕様を投稿する必要があります。
xnor

@xnorで十分ですか?
-motoku

コードゴルフでは、これらのオプションのスペースをさらに削除する必要があります。また、印刷が短いため、代わりにPython 2を使用します。print"x"代わりにprint("x")
-mbomb007

そして、代わりにリスト内包表記を使用しlist()ますか?
mbomb007

3
あなたのプロセスはうまくいくようです。プログラムで開始し、試行錯誤で短縮します。より多くの経験を積んで、Pythonのヒントを参照すると、すぐに素晴らしい結果が得られます。
ジオビット

回答:


11

ゴルフに「正しい」方法はありません。順調に進んでおり、使用したプロセスはかなり標準的です。ただし、プログラムを1つのステートメントにすることは、通常は要件ではありません。

それが役立つ場合、私はあなたのプログラムをゴルフダウンする方法を以下に示します...

ハッシュ関数では、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が指摘したように、enumerateでこれをさらに短縮できます。

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

テスト関数に移り、最初の2行をマージします。

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

これにより、すべてを1つのステートメントに移動できます。

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.