Hamming Sayıları

Hamming sayıları, 2,3 ve 5’ten başka diğer asal bölene sahip olmayan dizilerdir. Örnek verecek olursak hamming dizisi şöyledir.

İlk 60 Hamming Sayısı: 2 3 4 5 6 8 9 10 12 15 16 18 20 24 25 27 30 32 36 40 45 48 50 54 60… şeklinde gider.

Sıradaki sayının bulunması üç farklı durumdan oluşmakta. Sayı 2’ye bölünebiliyorsa bir sonraki aşamada 2,3 ve 5 dışında böleni olmayacak. Örneğin şöyle izah edilebilir.

hamming_numbers.py

if x % 2 == 0:
        return is_hamming_numbers(x/2)

Bu sayede artık var olan sayı elimizdeki dizideki sayılardan birisi durumunda. Örneğin 60/2 sonuç olarak 30 veriyor. Diziye baktığımızda 30’dan büyük ilk sayımız 32. Buna göre 2×32=64 olmakta. Yani 60’tan sonra sayı 2’ye bölünebiliyorsa bu da 2×32=64 olacaktır. Bu durum 3 ve 5 için de yine aynı şekilde anlaşılmaktadır.

Ben 9830’a kadar olan sayıları bulmak istedim. Tabii 9830 kafama göre değildi. İlk stackoverflow hatasını alacağım noktayı aramam uzun sürmedi.

O durumda aldığım hata Python: Maximum recursion depth exceeded hatası di. Yani yineleme derinliğinin aşıldığına dair bir hata mesajı.

Bunun için sys modülünü kullanarak izin verilen recursion aralığını değiştirebiliriz.

import sys
sys.getrecursionlimit() # ayarlanmadan önceki gerçek limit
sys.setrecursionlimit(10000) # limiti 10.000'e ayarla
sys.getrecursionlimit() # limiti göster

setrecursionlimit yineleme limitini belirlemekte kullanılır. Biz bu denememizde özyinelemeli işlev kullandık. Bu özelliği threading modülünün stack_size işlevini kullanarak yükseltebilirsiniz. Var olan limiti yukarıdaki kodda görebiliriniz. getrecursionlimit özelliği size bu değeri verecektir.

hamming_numbers.py

import sys
sys.setrecursionlimit(10000)

def is_hamming_numbers(x):
    if x == 1:
        return 1
    if x % 2 == 0:
        return is_hamming_numbers(x/2)
    if x % 3 == 0:
        return is_hamming_numbers(x/3)
    if x % 5 == 0:
        return is_hamming_numbers(x/5)
    return 0

def hamming_numbers(x):
    if x == 1:
        return 1
    hamming_numbers(x-1)
    if is_hamming_numbers(x) == True:
        print("%s" % x, end=' ')

def hamming_numbers_main():
    sys.stdout.write("Hamming Numbers: ")
    hamming_numbers(9830)

hamming_numbers_main()

Bu da 9830. sayıya kadar olanları yazdırmayı denediğim profile sonucu:

python -m profile hamming_numbers.py

         37722 function calls (10704 primitive calls) in 0.156 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      347    0.000    0.000    0.000    0.000 :0(charmap_encode)
        1    0.000    0.000    0.140    0.140 :0(exec)
      173    0.000    0.000    0.000    0.000 :0(print)
        1    0.016    0.016    0.016    0.016 :0(setprofile)
        1    0.000    0.000    0.000    0.000 :0(setrecursionlimit)
        1    0.000    0.000    0.000    0.000 :0(write)
      347    0.000    0.000    0.000    0.000 cp857.py:18(encode)
        1    0.000    0.000    0.140    0.140 hamming_numbers.py:1(<module>)
   9830/1    0.062    0.000    0.140    0.140 hamming_numbers.py:15(hamming_numb
ers)
        1    0.000    0.000    0.140    0.140 hamming_numbers.py:22(hamming_numb
ers_main)
27018/9829    0.078    0.000    0.078    0.000 hamming_numbers.py:4(is_hamming_n
umbers)
        1    0.000    0.000    0.156    0.156 profile:0(<code object <module> at
 0x0178C390, file "hamming_numbers.py", line 1>)
        0    0.000             0.000          profile:0(profiler)

Kaynaklar:

http://stackoverflow.com/questions/8177073/python-maximum-recursion-depth-exceeded

http://stackoverflow.com/questions/25064781/python-hamming-number-explanation

http://codegolf.stackexchange.com/questions/7/hamming-numbers

http://en.wikipedia.org/wiki/Regular_number