我是否正确进行代码搜寻?


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

我尝试用lambda缩短它来重复代码(这没有用):

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)

最后,我得到了一个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))

我希望该程序成为一个声明,所以首先我想到了:

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

这是如何解决代码高尔夫问题的吗?我从来没有真正做过这样的事情,所以现在我只想知道我是否做对了。

修订:该程序可以为您完成所有工作;因此,我将在此引用该函数:作为输入,该程序接受给定字符串的所有排列;这里的字符串是从中随机选取的9个字符ascii_lowercase。输出是人类可读的字符串,用于定义给定字符串的每个排列结果是否与另一个字符串的另一个结果重复。如果所有排列均无重复,则程序指示成功。九个字符被选为最大的字符长度,可以在我的盒子上反复计算。

修改II正如好学的读者所指出的,所描述的预期目的不是通过随附的代码获得的。测试用例显然是不够的。


3
这看起来是一个很好的提示问题,很高兴看到您详细介绍了您的高尔夫运动过程。但是我不知道您所说的“哈希”程序是什么意思。您应该发布一个规范,该规范说明如何获取输入,如何给出输出以及输出与输入之间必须具有什么关系。
xnor 2015年

@xnor就足够了吗?
motoku

对于代码高尔夫,您绝对应该删除一些其他可选空格。另外,由于打印时间较短,因此请改用Python 2。print"x"而不是print("x")
mbomb007

并使用列表理解代替list()
mbomb007

3
您的过程似乎很好。从程序开始,通过尝试/错误来缩短。获得更多经验并浏览python技巧,您将立竿见影。
Geobits'2

Answers:


11

没有“正确”的高尔夫方式。您做得不错,使用的过程相当标准。不过,通常不需要将程序变成一个语句。

如果有帮助,这就是我如何打败您的程序的方法...

在哈希函数中,for语句可以替换为sum:

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 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.