Programlama ile çözülebilecek zeka soruları

Şöyle bir şey de yapılabilir tabi.

def bolenler(n):
  return sum([i for i in range(1,n//2+1) if n%i==0])

sayi = 1
while sayi>bolenler(sayi):
  sayi+=2
print(sayi)
1 Beğeni

Hocam yan yana yazılan kodları okumada biraz güçlük çekiyorum sizden ricam satır satır olacak şekilde yazabilir misiniz. Birde benim yaptığım yerde nereler yanlış veya ne yapmam gerekiyordu yanlışı düzeltmem için ?

def toplam_bul_ve_karsilastir(sayi):
    toplam = 0  # tam bölenler toplamı
    if sayi % 2 == 1:  # sayı tek ise...
        for n in range(1, sayi):
            if sayi % n == 0:
                toplam += n
    return (toplam > sayi)

for sayi in range(100000):
    if toplam_bul_ve_karsilastir(sayi) == True:
        print(sayi)
        break

# Çıktı: 945
# Manuel çözüm: 945 = 315, 189, 135, 105, 63, 45, 35, 27, ... , 1
# 27'ye kadar olan sayıların toplamı 954 ediyor.
  • For döngüsünden önce sayının tek olup olmadığını kontrol ediyoruz. Eğer tek ise for döngüsü içerisinde tam bölenlerini bulup toplam değişkenine ekliyoruz. En son (toplam > sayi) ifadesini ‘return’ ediyoruz.

  • Eğer ‘True’ ise ekrana o sayıyı yazdırıp ardından fonksiyonun çağrıldığı döngüyü durduruyoruz.

Blok-alıntı
ama bir türlü soruda istenilen şekilde sadece cevabı veren fonksiyonu yazamadım

(Nasıl alıntı yapacağımı tam bilmiyorum :cry:)

solve() fonksiyonunu sürekli olarak çağıracak bir for döngüsü yazmalısınız ve eğer aranan sayı bulunduysa döngünün kırılması için o döngü içerisine bir if bloğu yerleştirebilirsiniz. Bunun için de
if toplam > son: olan kısımdan sonra başka bir global değişkenin değerini değiştirmeniz lazım.

Misal fonksiyondan önce durum = False olarak bir değişken atayın. Ardından fonksiyon içerisinde global liste, islem, durum şeklinde o değişkeni de dahil edin.

    if toplam > son:
        print(f"Zengin Sayı {toplam}>{son}")
        durum = True

sonrasında oluşturacağınız for döngüsü içerisine

for n in range(1000000):
    solve(n)
    if durum == True:  # Veya if durum:
        break

yerleştirebilirsiniz.

1 Beğeni
def bolenler(n):
  return sum([i for i in range(1,n//2+1) if n%i==0])

Bölenlerin toplamını döndüren bir fonksiyon. sum liste toplamını döndürür. i for i in range bir liste tanımlar. 1 den başlayıp sayının yarısına kadar sayıları kontrol eder. if n%i==0 ise eğer n sayısı i ye tam olarak bölünüyorsa listeye ekler.

Şuraya bir tutam sqrt(n) ekleyelim.

anlamayanlar için

range(1, ceil(sqrt(n)))

Trick

İlgili parçanın time complexity si O(n) den O(√n) e düşüyor . Oluşan etkiyi incelemek isteyenler için link

Totaldeki zaman karmaşıklığı ise O(n²) den O(n√n) e düşer.

sqrt(n) olmaz burada. Örneğin 100 sayısı, 50 tam bölenidir. Ama sqrt(n) 10 a kadar bakar.

(Asal bölenlere bakarken kullanabiliriz ama)

Okunuşunda ki harfleri birbirinden farklı en büyük üç haneli sayı nedir?

Himm, evet, haklısıniz, ama 2 yi elde ederseniz 50 yi de zaten otomatikman elde edebilirsiniz.(100/2) 50’nin böldüğünü bulmak için 50 tane işlem yapmaya gerek yok, 2 işlem yapsanız yetiyor. Yani 100 sayısındaki bölenleri toplamak için 100 tane işlem yapmamıza gerek yok, 10 tane işlem yapsak(hadi 20 olsun) yeter.

:thinking: Nasıl yani? (Burayı hafif açabilir misiniz, tamam anladım biraz da, alakayı kuramadım gibi)

def bolenler(n):
  return sum([i for i in range(1, ceil(sqrt(n))) if n%i==0])

Tamam böyle deneyelim kodu. Sonucu buluyor mu? Veya başka ne gibi değişiklikler yapmamız gerekiyor.

Tamam işte istediğiniz şeyleri yapmak için ne gibi değişiklikler lazım kodda onu sordum.

Pardon, biraz yorgun olduğum için yanlış anladım sizi.

Şimdi Python unuttum ama

from math import sqrt
def bolenler(n):
  a = []
  for i in range(1, sqrt(n)):
    if n % i == 0:
      a.append(i)
      if n // i != i:
        a.append(n//i)
   return sum(a)

Gibi bir şey diyorum.

(Sonunda alıntı yapmayı öğrendim :slight_smile: )

okunuslar = {'0': "",
             '1': "bir",
             '2': "iki",
             '3': "üç",
             '4': "dört",
             '5': "beş",
             '6': "altı",
             '7': "yedi",
             '8': "sekiz",
             '9': "dokuz",
             '10': "on",
             '20': "yirmi",
             '30': "otuz",
             '40': "kırk",
             '50': "elli",
             '60': "altmış",
             '70': "yetmiş",
             '80': "seksen",
             '90': "doksan",
             '100': "yüz",
             '200': "ikiyüz",
             '300': "üçyüz",
             '400': "dörtyüz",
             '500': "beşyüz",
             '600': "altıyüz",
             '700': "yediyüz",
             '800': "sekizyüz",
             '900': "dokuzyüz"}

def parcala(sayi):
    sayi = str(sayi)
    tam_okunus = ''
    tam_okunus += okunuslar[sayi[0] + '00']  # Mesela ilk basamak 9 ise yanına '00' ekler ve sözlük içerisinde '900'ün okunuşuna bakar.
    tam_okunus += okunuslar[sayi[1] + '0'] if sayi[1] != '0' else '' # Mesela ilk basamak 9 ise yanına '0' ekler ve sözlük içerisinde '90'ün okunuşuna bakar. 0 ise bir şey eklemez.
    tam_okunus += okunuslar[sayi[2]]
    return tam_okunus

def kontrol_et(tam_okunus):
    for harf in tam_okunus:
        if tam_okunus.count(harf) > 1:
            return False

    return True

for sayi in range(999, 99, -1):
    if kontrol_et(parcala(sayi)) == True:
        print(sayi)
        print(parcala(sayi))
        break
  • Bazı sayıların okunuşlarının yer aldığı bir sözlük,
  • Ardından Girilen sayının okunuşunu ‘return’ eden bir fonksiyon,
  • Onun da ardından ‘return’ edilen okunuşun harflerinin, okunuş içerisinde kaç defa geçtiğini kontrol eden, buna göre ‘False/True’ ‘return’ eden başka bir fonksiyon,
  • Son olarak da 999’dan başlayarak 100’e kadar olan sayıları, yukarıdaki fonksiyonlara parametre olarak giren ve o fonksiyonları çağıran bir ‘for’ döngüsü oluşturdum.

Çıktı:

615
altıyüzonbeş
2 Beğeni

Ben de önceden yazdığım kodu bırakayım son soru için.

def yaziyap(sayi):
    birler = ["","bir","iki","üç","dört","beş","altı","yedi","sekiz","dokuz"]
    onlar = ["","on","yirmi","otuz","kırk","elli","altmış","yetmiş","seksen","doksan"]
    sayi=str(sayi)
    if sayi[0]=="1":
        return "yüz"+onlar[int(sayi[1])] + birler[int(sayi[2])]
    else:
        return birler[int(sayi[0])]+"yüz" + onlar[int(sayi[1])] + birler[int(sayi[2])]

for n in reversed(range(999)):
    if len(yaziyap(n)) == len(set(yaziyap(n))):
        print(yaziyap(n))
        break

Eğlenceli bir soru daha bırakayım. Tam kodluk.

Fedai’nin Ödülü

“Yüzüğümü Honoria’ya başarıyla teslim ettiğin için,” dedi Atilla, fedaisi Tarkan’a, “sana ödül olarak arazi vereceğim ve yerini-yurdunu bileceksin. Şuradaki kazık yığınından dilediğin sayıda kazık al ve araziye dilediğin gibi çak. Sonuçta ilk başladığın yere dön. kazıkları iple birleştireceğim ve ipin belirlediği konveks arazi senin olacak. karar verdiğin sayıda kazığı topladığın andan itibaren 24 saatin var.”

Atilla’nın konveks falan dediğine bakmayın, matematik bilmez, ama Tarkan’da bilmez. Bir kazığı çakmasının 1 dakika sürdüğünü ve iki kazık arası mesafeyi daima aynı sabit hızla yürüdüğünü farz ederek, mümkün olduğunca büyük yüzölçümüne sahip olan araziyi çevreleyecek kazık sayısını bulması için Tarkan’a yardım edin.

Ek bilgiler:
®tarkan ve ®honoria sonsuz’un tescilli kahramanıdır. Atilla Hun imparatorudur. Kazıklar Atilla’nın hazine müşteşarına zimmetlidir. İp çin malıdır.

Yürüme hızı nedir? (20 karakter)

Önemli değil aslında. Sabit bir sayı kabul edebilirsiniz.

#include <iostream>
#include <cmath>
const double pi = 3.14159265358979;

double alanHesapla(double n, double a)
{
	return 0.25 * (n * a * a) * (1.0f / tan(pi / n));
}

int main()
{
	double time = 24 * 60;
	double uzunluk = 0;
	double vYurume = 1; // 1 br/dk
	double vKazik = 1; // 1 kazık/dk
	double alan = 0;
	double eskiAlan = 0;

	for (double i = 3; ; i++) // Kenar sayısı
	{
		double yurumeZamani = time - vKazik * i; // Yürümeye kalan zaman
		uzunluk = (yurumeZamani / i) * vYurume; // Maksimum olabilecek kenar uzunluğu
		eskiAlan = alan;
		alan = alanHesapla(i, uzunluk);

		if (eskiAlan > alan) // Önceki alan elimizdeki alandan çoksa durar
		{
			alan = eskiAlan;
			std::cout << "Kenar sayisi: " << i-1 << std::endl;
			std::cout << "Alan: " << alan << std::endl;
			break;
		}
	}
}

Konveks şekillerde maksimum alana sahip olan şekil eşkenar olandır. Buna göre hesaplayarak buldum.

3 Beğeni

Bir de ben bir soru ekleyebilir miyim ?

@reo ile chatleşirken şöyle bir random attım: “KODoasfoasoafasofkaskfas”
Randomun başında büyük harflerle “KOD” yazıyor.
Pekala, başında büyük harflerle “KOD” yazan bir randomun atılma olasılığını nasıl hesaplarız ?
Bir randomun en az 5, en fazla 50 karakterden oluşması gerektiğini varsayalım.

1 Beğeni

Bunun icin global degiskene hic gerek yok. Fonksiyon, toplam > son ise True, degilse False dondurebilir. Boylelikle global isim alanini kirletmemis oluruz (“durum” cok genel bir isim, ya baska bir fonksiyon musterinin odeme durumunu saklamak isterse?) ve her datanin gereken en kucuk alanda ve zamanda yasama prensibine sagdik kalmis oluruz.

Ayni sekilde yukaridaki fonksiyonda sadece bir kere kullanilip isi biten liste, islem gibi degiskenleri de global namespace’e tasimaya gerek yok.

1 Beğeni