Sayının mükemmel olup olmadığını döndüren fonksiyon

1’den 1000’e kadar olan sayılardan mükemmel sayı olanları ekrana yazdırın. Bunun için bir sayının mükemmel olup olmadığını dönen bir tane fonksiyon yazın.

*Bir sayının bölenlerinin toplamı kendine eşitse bu sayı mükemmel bir sayıdır. Örnek olarak 6 mükemmel bir sayıdır (1 + 2 + 3 = 6)

def mükemmel_mi(sayı = 1000):

     toplam = 0
     bölen = 1

     mükemmel_sayılar = []

     for v in range(1,sayı):
        while (bölen < v):
            if (v % bölen == 0):
                toplam += bölen
                bölen += 1
                if (v == toplam):
                    mükemmel_sayılar.append(v)
        return mükemmel_sayılar

print(mükemmel_mi())

Şöyle yapabilirsiniz:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


def mukemmel_mi(liste):
   for i in liste:
       bolenler = []
       for j in range(1, i):
           if i % j == 0:
               bolenler.append(j)
       if sum(bolenler) == i:
           yield i
           
           
for i in mukemmel_mi([j for j in range(1000) if j != 0]):
    print(f"{i} mükemmel bir sayı.")

Cevabın için teşekkür ederim fakat yazdığın kodlar bana çok karışık geldi tam anlayamadım benim sormak istediğim benim yazdığım kodlar neden yanlış

Kodlarınıza biraz yakından bakalım:

def mükemmel_mi(sayı = 1000):

     toplam = 0
     bölen = 1

     mükemmel_sayılar = []

     for v in range(1,sayı):
        # Yukarıdaki for döngüsüne göre 
        # v = 1 olduğunda
        # Aşağıdaki while döngüsü atlanır.
        # Doğrudan mükemmel_sayılar return edilir.
        # Ve return edilen şey boş bir listedir.
        while (bölen < v):
            if (v % bölen == 0):
                toplam += bölen
                bölen += 1
                if (v == toplam):
                    mükemmel_sayılar.append(v)
        return mükemmel_sayılar

print(mükemmel_mi())

Ayrıca bir for döngüsünde return'u for döngüsünün içinde kullanarak birden fazla değeri geri dönderemeyiz. Bu yüzden return'u for döngüsünün dışına almak lazım. for döngüsünün içinde bir değişkeni geri döndermek istiyorsak, ya döngü içindeyken onu bir listeye eklemeli, sonradan listeyi geri döndermeli ya da yield deyimi kullanılmalı. Bu arada bir önceki mesajımda yazdığım kodlar aşağıdaki gibi de yazılabilirdi.

# Argümanı liste değil de
# sayı olacak şekilde 
# fonksiyonu yeniden düzenleyebilirsiniz.
def mukemmel_mi(liste):
   mukemmel_sayilar = []
   for i in liste:
       # Listedeki her bir sayı için
       # bir tane bolenler listesi oluşturulsun
       bolenler = []
       # Her bir sayı kendisine kadar olan sayılara
       # kadar bir döngü içerisine sokulsun
       for j in range(1, i):
           # i değişkenini kendisine kadar olan j sayılarına bölelim (0 hariç)
           # kalanı 0 veren j sayısını
           # bolenler listesine ekleyelim.
           if i % j == 0:
               bolenler.append(j)
       # Eğer bolenler listesindeki j sayılarının toplamı
       # i değişkenine eşitse, i mükemmel bi sayıdır.
       if sum(bolenler) == i:
           # i, mükemmel bir sayıysa mukemmel_sayilar
           # listesine eklensin.
           mukemmel_sayilar.append(i)
   # Son olarak döngü tamamlandığında 
   # mükemmel_sayilar'ı geri dönderelim.
   return mukemmel_sayilar
           
           
liste = [j for j in range(1000) if j != 0]
print(mukemmel_mi(liste))

Aşağıdaki fonksiyon da yukarıdaki fonksiyon ile benzer sonuçlar üretir. Ama birinin argümanı list veri tipindeyken, diğerinin argümanı int veri tipindedir.

def mukemmel_mi(sayi):
   mukemmel_sayilar = []
   for i in range(1, sayi):
       toplam = 0
       for j in range(1, i):
           if i % j == 0:
               toplam += j
       if toplam == i:
           mukemmel_sayilar.append(i)
   return mukemmel_sayilar
           
           
print(mukemmel_mi(1000))

yield deyimi kullanarak aşağıdaki gibi de yazılabilir:

def mukemmel_mi(sayi):
   for i in range(1, sayi):
       toplam = 0
       for j in range(1, i):
           if i % j == 0:
               toplam += j
       if toplam == i:
           yield i       
          

print(list(mukemmel_mi(1000)))
1 Beğeni
mukemmel_mi = lambda sayi: sum(filter(lambda d: sayi % d == 0, range(1, sayi))) == sayi

print(list(filter(mukemmel_mi, range(1, 1001))))

Su yuzden:

mükemmel_sayılar listesi, “bir sayinin mukemmel olup olmadigi” degil.

yazdiginiz kodda d degeri nereden aliniyor aciklayabilir misiniz biraz. teşekkürler

Sayenizde lambda, map, filter ile ilgilenmeye başladım. :slight_smile:
Mesela aşağıdaki kodlar yazdığınız kodlarla aynı işlemleri yapıyor sadece yazım şekli biraz farklı:

mukemmel_mi = lambda sayi: list(filter(lambda x: sum(filter(lambda y: x % y == 0, range(1, x))) == x, range(1, sayi)))
print(mukemmel_mi(sayi=1000))

@gopenumbra
d, sayi verisi gibi, bir lambda fonksiyonunun argümanı. Aynı şekilde yukarıdaki lambda fonksiyonundaki sayi, x ve y verileri de birer argüman.

  1. lambda y: x % y == 0, bir lambda fonksiyonudur.
    y, bu fonksiyonun argümanı olup, x bu fonksiyonun argümanı değildir. Bu fonksiyon şu haliyle bir NameError hatası yükseltir. Ama kodun devamı sayesinde bu kısım bir anlam kazanır. Fonksiyon; bir x sayısının, değişen bir y sayısına bölündüğünde kalan 0'a eşit mi değil mi sorgusu yapar. Bu fonksiyondan True veya False değerlerinden birisi geri döndürülür.

  2. filter(lambda y: x % y == 0, range(1, x)), ifadesi şu haliyle bir NameError hatası yükseltir. Ama kodun devamı sayesinde bu kısım çalışır bir hal alır.

    Kısaca filter() fonksiyonu nasıl kullanılıyor ona bakalım:

    Çağrılışı filter(fonksiyon, yinelenebilir_veri) şeklindedir. Fonksiyon, yinelenebilir veri tipinden aldığı her bir argüman ile bir koşulu denetler.

    Örnek:

fonksiyon = lambda x: x % 2 == 0
liste = range(1, 10)
filtrelenmis_liste = list(filter(fonksiyon, liste))
print(filtrelenmis_liste)

# O halde yukarıdaki kodları şu şekilde düzenleyebiliriz:
filtrelenmis_liste =  list(filter(lambda x: x % 2 == 0, range(1, 10)))
print(filtrelenmis_liste)

filter(lambda y: x % y == 0, range(1, x)) ifadesi ile; x, 1'den x'e kadar olan sayılara bölünür ve 0 kalanını veren y sayılar bulunur.

  1. sum(filter(lambda y: x % y == 0, range(1, x))) ifadesinde, x hala tanımlanmamış bir haldedir. Yani sadece bu kod çalıştırılırsa NameError hatası yükseltilir. Kısaca sum() fonksiyonu nasıl kullanılıyor önce ona bakalım:

    Çağrılışı sum(range(10)) şeklindedir. Fonksiyon, yinelenebilir verideki her bir sayıyı toplar ve toplamı geri döndürür.

sum(filter(lambda y: x % y == 0, range(1, x))) ifadesi ile, 1'den x'e kadar olan y sayılarından, x'i tam bölen sayılar bulunur ve toplanır.

  1. lambda x: sum(filter(lambda y: x % y == 0, range(1, x))) == x, bir lambda fonksiyonudur. Burada, x değişebilen bir argüman olarak tanımlanır. Bu fonksiyon verilen bir x sayısının mükemmel olup olmadığını sorgular. x, mükemmel bir sayıysa, yani 0 kalanını veren bölenlerin (y sayılarının) toplamı x'e eşitse, True değeri yükseltilir.

  2. filter(lambda x: sum(filter(lambda y: x % y == 0, range(1, x))) == x, range(1, sayi)). Burada sayi henüz tanımlanmamış başka bir fonksiyonun argümanıdır. Yani şu haliyle kodları çalıştırsak yine NameError hatası alırız. sayi'yi argüman olarak alacak olan fonksiyon mukemmel_mi fonksiyonudur. Filter fonksiyonu bu şekilde çağrılırsa hata oluşur. Ama burada yapılan işlemden bahsetmek gerekirse; 1'den sayi'ya kadar olan sayıların mükemmel sayı olup olmadığı sorgulanır. Ve True değeri veren sayılar filtrelenir.

  3. Bu da mukemmel_mi fonksiyonu: mukemmel_mi = lambda sayi: list(filter(lambda x: sum(filter(lambda y: x % y == 0, range(1, x))) == x, range(1, sayi)))

8 Beğeni

Sizi tebrik ederim. Üşenmemiş o kadar anlatmışsınız üstüne bir de resim hazırlamışsınız. Aslında genelde beğenip geçerdim ama bu çabanız gerçekten takdire layık. :slight_smile:

1 Beğeni

çok teşekkürler bu detaylı anlatım için

Super :slight_smile:
Ama mukemmel_mi ismi yerine limit parametresi alan mukemmel_sayilar veya mukemmel_sayilari_bul filan kullanirdim ben.

Lambda’ya parametre olarak gelen degiskenlere bound variable, disaridan gelenlere free variable diyoruz. Free variable’lar Python’da lexical scope’tan late binding ile alinip closure olusturuluyor.

2 Beğeni

Fonksiyonun ismini ve parametre ismini ben de değişik kullanırdım. :slight_smile:

Hmm, closure şöyle bir şeymiş:

def f(x):
    def g(y):
        return x + y
    return g  # Return a closure.

def h(x):
    return lambda y: x + y  # Return a closure.

# Assigning specific closures to variables.
a = f(1)
b = h(1)

# Using the closures stored in variables.
assert a(5) == 6
assert b(5) == 6

# Using closures without binding them to variables first.
assert f(1)(5) == 6  # f(1) is the closure.
assert h(1)(5) == 6  # h(1) is the closure.

Bu return şeklini biliyorum. “()” işaretleri olmadan return edilen fonksiyonun isminin closure olduğunu yeni öğreniyorum. Fonksiyon bezeyicilerinde kullanılan yapıya da closure deniliyor o halde, doğru mu?

def f(x):
    def g(func):
        def h():
            return func() * x
        return h
    return g


@f(x=10)
def a():
    return 5


print(a())
# Sonuç = 50

(Burada) free variable’larina deger atanmis fonksiyonlara closure deniyor. Genel olarak butun anonim fonksiyonlara/lambda’lara diyen de var.

f’nin dondurdugu g, x variable’ini f’nin argumanindan almis tek parametreli bir fonksiyon. g’nin bir closure’u.

“() isaretleri olmadan return edilen fonksiyon” == return edilen (anonim) fonksiyon.

1 Beğeni

Genellikle tkinter’de lambda fonksiyonunu sıklıkla kullanmak durumunda kaldığımı söyleyebilirim.
Mesela bir widget’in command parametresine bir fonksiyon atanacak diyelim, fonksiyonu sadece isim olarak yazıyoruz.

widget.config(command=fonksiyon)

Ama bazen fonksiyonlara parametreler girmek gerekiyor, dolayısıyla command kısmına bir lambda fonksiyonu yazmak gerekiyor.

Örneğin:

widget.config(command=lambda: fonksiyon(*args))
widget.bind("<Button-1>", lambda event: fonksiyon(event, *args))

Eyvallah hocam çok saolun yazdığım kodları güzel düzenlemişsiniz list veri tipiyle yazdığınız algoritma çok hoşuma gitti bide sum parametresinide öğrenmiş oldum o çok mantıklıymış

1 Beğeni

Affınıza sığınarak ufak bir düzeltme de bulunsam?

sum() bir parametre değil, bir fonksiyondur.

Doğru sum() bir fonksiyondur gömülü fonksiyon hatta mesajı hızlı hızlı yazdım işte bazen böyle terimlere dikkat etmiyorum :slight_smile:

1 Beğeni

Kod mükemmel derecesinde açık aslında elinize sağlık :slight_smile: