En kısa kod satırı kullanımı ile asal sayıları bulma

Programlama eğitimi verdiğim için öğrencilerimi her zaman en kısa kodla programlarını yazmayı tavsiye ederim. Bu bazen benim için de oldukça şaşırtıcı sonuçlar çıkarabiliyor ve benim de yeni şeyler öğrenmemi sağlıyor.

Sorumuz basit: 1000 e kadar olan asal sayıları yazdıran bir program yazınız. (Tabiki en kısa kod satırını kullanarak)

Daha kısası olabilir gibi geliyor ama tek satırlık bir cevap yazdım:

Cevap
print(*list(filter(lambda x: False if True in [x%i==0 for i in range(2, x)] else True, range(2, 1000))))
3 Beğeni

Bu tabi üst düzey bir cevap olmuş :slight_smile: sonuçta ortaokul öğrencilerini düşünürsek bu şekilde cevap verebilecek düzeyde değiller

Merhaba @sonsuz hocam,
Ben sizin gibi bir eğitmen değilim belki. Ama şahsen kısa kod yazmak yerine kendisine verilen kaynakları iyi değerlendiren kodun daha önemli olduğunu düşünüyorum(belki ortaokul öğrencileri için geçerli olmayabilir bilemem). Bence bırakın implementation daha uzun olsun. Ama sizin bulunduğunuz şartları da bilemiyorum.
Saygılar.

5 Beğeni

Akıl yaşta değil baştadır diye düşünürsek bunu ilkokul öğrencileri de yapabilir.

1 Beğeni

Ben tabi haliyle şöyle bir kod bekliyorum öğrencilerden.

for sayi in range(2,1000):
    asal = True
    for bolen in range(2,sayi//2):
        if sayi%bolen==0:
            asal = False
    if asal:
        print(sayi, end = ", ")
1 Beğeni

Fakat bir öğrencim şöyle bir kod gönderdi.

for i in range (2,1000):
    for a in range (2,i//2):
        if (i%a)==0:
            break
    else:
        print (i,end=", ")

Programa bakınca bütün sayıları yazdırır diye düşündüm ilk başta elseyi if’e bağlı olarak değerlendirdim. Sonra else nin if’e değil de for döngüsüne bağlı olduğunu gördüm. Bu beni şaşırttı diyebilirim. C/C++ programlamadan geldiğim için alışık olmadığım bir görüntüydü.

Şaşırmaya devam etmek güzel bir şey.

1 Beğeni

Merhaba, ben de ufak bir fikir vermek isterim.

era = [0 for i in range(1001)]
for i in range(2, 1001):
    if(era[i] == 0):
        print(i)
        k = i + i
        while(k < 1001):
            era[k] = 1
            k += i

Eratosthenes kalburu. Sıklıkla kullanılır.
Öğrencinizin kodunu aşağıdaki gibi düzeltsek daha optimize olur.

from math import sqrt
for i in range (2,1000):
    for a in range (2,int(sqrt(i))):
        if (i%a)==0:
            break
    else:
        print (i,end=", ")

Neyse her üç kodu da test edelim(testin doğru sonucu vereceğini garanti edemeyiz ama aralık ne kadar büyük olursa doğruluk payı o kadar artar. O yüzden kodlarda ufak değişiklikler yaptım. Hatamız varsa affola.)

from timeit import timeit as tit

testcode1 = """
prime = []
era = [0 for i in range(1000001)]
for i in range(2, 1000001):
    if(era[i] == 0):
        prime.append(i)
        k = i + i
        while(k < 1000001):
            era[k] = 1
            k += i
"""

testcode2 = """
prime = []
from math import sqrt
for i in range (2,1000000):
    for a in range (2,int(sqrt(i))):
        if (i%a)==0:
            break
    else:
        prime.append(i)
"""

testcode3 = """
prime = []
for i in range (2,1000000):
    for a in range (2,i//2):
        if (i%a)==0:
            break
    else:
        prime.append(i)
"""



print("testcode1", tit(stmt = testcode1, number = 1))
print("testcode2", tit(stmt = testcode2, number = 1))
print("testcode3", tit(stmt = testcode3, number = 1))

outputs:

testcode1 0.3228799
testcode2 4.667852399999999
# [hesaplamasını bekliyorum, hesabı bitirebilirse editleme de yapacağım.]

Gerçekten ben de çok şaşırdım. Tesadüfe bak ki face gruplarından birinde daha böyle bir şey görmüştüm de kodu çalıştırmaya üşendiğimden(yani telde olduğumdan kodu çalıştırmadım) yanlış olduğunu düşünmüştüm. İlginç :thinking:

Edit: Sayın Seyirciler, Baylar ve bayanlar, işte karşınızdaaaa

testcode3 1398.2167295

Edit 2: Özür dilerim, tescode1 kodunu yeniden editledim. Ama yine de pek bir değişiklik olmadığını söyleyebilirim. Şöyle ki.

testcode1 0.46847779999999994

Bu fonksiyonun implementasyonu hakkında bir varsayımda bulunuyor. Kaynağınız var mı?

Üstteki yazıyı yazarken araştırmadım. Ama bir zamanlar araştırmıştım. Aklımda log2(n) diye kalmış.

Kaynağım sağlam bir kaynak değil.
Yanlış bilgi verdiğimi düşünüyorsanız beni bilgilendirerek hatalarımı düzeltebilirsiniz.

CPython’un math.sqrt'yi nasıl impleme ettiğini bilmiyorum. 5 dakikadır kaynak kodlarına bakıyorum ama sadece isqrt’yi bulabildim, o da tahmin ettiğim gibi 64bit sayılar için fast path kullanıyor (bu da implementasyondaki optimizasyonların karmaşıklığı nasıl etkilediğine bir örnek).

Ama günümüzde çoğu işlemcinin float’ların karekökünü almaya özel instruction’ları (talimat?) var. Yani kök alma işlemi yazılım değil donanım seviyesinde gerçekleşiyor. Bu da kök işlemini O(1) civarına indiriyor.

1 Beğeni

En kısa olanı değil en okunabilir olanı yazmalarını tavsiye etmelisiniz bence

2 Beğeni

Zaten onu anlatmak istemiştim. Nasıl gereksiz kod kullanıp uzattıklarını görseniz. Kısa, net anlamında kullandım.

1 Beğeni

[print(n)for n in range(2,999)if all([n%i!=0 for i in range(2,n)])]

3 Beğeni

Eratosthenes kalburu kadar zaman kazandırmasa da ilk koda göre daha hızlı bir yöntem.

asallar = [2]
for sayi in range(3,1000000):
    for bolen in asallar:
        if sayi%bolen==0:
            break
    else:
        asallar.append(sayi)
print(asallar)
1 Beğeni
import re

asal_degil = re.compile(R"^1?$|^(11+?)\1+$")
kaca_kadar = 1_000
asallar = [sayi
           for sayi in range(kaca_kadar)
           if not re.search(asal_degil, "1"*sayi)]