Answers:
h=1:m 2h&m 3h&m 5h
m=map.(*)
c@(a:b)&o@(m:n)|a<m=a:b&o|a>m=m:c&n|0<1=a:b&n
main=print$take 1000000h
在我测试过的机器上,在3.7s内计算百万(如果您确实希望存储输出,则可以更多)
取消高尔夫:
-- print out the first million Hamming numbers
main = print $ take 1000000 h
-- h is the entire Hamming sequence.
-- It starts with 1; for each number in the
-- sequence, 2n, 3n and 5n are also in.
h = 1 : (m 2 h) & (m 3 h) & (m 5 h)
-- helper: m scales a list by a constant factor
m f xs = map (f*) xs
-- helper: (&) merges two ordered sequences
a@(ha:ta) & b@(hb:tb)
| ha < hb = ha : ta & b
| ha > hb = hb : a & tb
| otherwise = ha : ta & tb
所有Haskell都擅长于:以一种有效的方式将列表定义为自身的惰性函数。
Python 181个字符
h=[]
h.append(1)
n=input()
i=j=k=0
while n:
print h[-1]
while h[i]*2<=h[-1]:
i+=1
while h[j]*3<=h[-1]:
j+=1
while h[k]*5<=h[-1]:
k+=1
h.append(min(h[i]*2,h[j]*3,h[k]*5))
n-=1
h=[]
使用最小制表符距离和单个字符换行符在后面删除了空格,文件大小最终为187个字节。
h=[1]
。另外,直接在源代码中给数字,以保存数字字符<1000000
。
def k i,n;(l=Math).log(i,2)*l.log(i,3)*l.log(i,5)/6>n end
def l i,n;k(i,n)?[i]:[i]+l(5*i,n)end
def j i,n;k(i,n)?[i]:[i]+j(3*i,n)+l(5*i,n)end
def h i,n;k(i,n)?[i]:[i]+h(2*i,n)+j(3*i,n)+l(5*i,n)end
puts h(1,n=gets.to_i).sort.first n
现在它已经足够快了,但是肯定仍有很多高尔夫运动会发生。
→ time echo 1000000 | ruby golf-hamming.rb | wc
1000000 1000000 64103205
echo 1000000 0.00s user 0.00s system 0% cpu 0.003 total
ruby golf-hamming.rb 40.39s user 0.81s system 99% cpu 41.229 total
wc 1.58s user 0.05s system 3% cpu 41.228 total
use List::Util min;
$\=$/;$h{1}=();delete$h{$_=min keys%h},print,@h{$_*2,$_*3,$_*5}=()for 1..<>
取消高尔夫:
use List::Util 'min';
my %hamming;
my $up_to = <>;
$hamming{1} = (); # The value is undef, but the key exists!
for (1 .. $up_to) {
my $next = min( keys %hamming );
delete $hamming{$next}; # We're done with this one
print $next, "\n";
@hamming{ $next * 2, $next * 3, $next * 5 } = (); # Create keys for the multiples
} # Rinse, repeat
需要11分钟才能计算出前100,000个数字,我什至不想考虑1,000,000个数字。它会在3秒钟内完成前10,000个工作;就像O(n ^ 2):(
{⍺⍴{⍵[⍋⍵]}∪,⍵∘.×⍳5}⍣≡∘1
{⍺⍴{⍵[⍋⍵]}∪,⍵∘.×⍳5}⍣≡∘1 Monadic function:
{⍺⍴{⍵[⍋⍵]}∪,⍵∘.×⍳5} Define the following helper function g(⍺,⍵):
⍵∘.×⍳5 Make a multiplication table between ⍵ and (1 2 3 4 5).
(Including 4 is unnecessary but saves bytes.)
, Flatten the table into an array.
∪ Keep unique elements.
{⍵[⍋⍵]} Grade up the array and access it at those indices.
(This is the APL idiom to sort an array.)
⍺⍴ Keep the first ⍺ elements; pad by repeating the array.
{⍺⍴{⍵[⍋⍵]}∪,⍵∘.×⍳5}⍣≡ Repeatedly apply g with some fixed left argument
until a fixed point is reached.
At this point we have a dyadic function that takes
n on the left and the starting value on the right,
and returns multiples of the n Hamming numbers.
∘1 Fix 1 as the right argument.
1↓0 1{⍺↑{⍵[⍋⍵]}∪,⍵∘.×⍳5}⍣≡⍨1+⊢
{⍺⍴∧∪,⍵×⍀⍳5}`⍣≡∘1
。(反引号需要因错误。)