Programlama ile çözülebilecek zeka soruları

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

“Random” bir sifat (“rastgele”), yanina isim lazim: random string, random mesaj, random harfler.

Diger butun parametrelerden bagimsiz olarak 1 / alfabe_boyu^3 olmasi lazim.

Cozume Monte Carlo yontemiyle yaklasan bir cevap guzel bir egzersiz olabilir. (Monte Carlo yontemi/simulasyonu: Mesajin “kod” ile baslama ihtimalini bulmak icin 1000 tane mesaj uret, kac tanesi “kod” ile basliyor bak. Cevap n/1000. Daha precise (iyi, kesin, hassas) cevap icin daha cok simulasyon yap. Alfabe boyunu kucultmek isteyebilirsiniz.

1 Beğeni
#include <iostream>
#include <string>
typedef unsigned long long int ULLI;

bool check(ULLI x)
{
	std::string x_str = std::to_string(x);
	for(int i = 0; i < x_str.length(); i++)
	{
		for(int j = 0; j < x_str.length(); j++)
		{
			if(i != j && x_str[i] == x_str[j]) // Farklı basamakta aynı sayı varsa false döndür
			       return false;	
		}
	}
	return true;
}

int main()
{
	ULLI count = 0;
	for(ULLI i = 0; i <= 9876543210; i++) // Sayı maksimum 9876543210 olabilir
	{
		if(check(i)) count ++;
	}
	
	std::cout << "Cevap: " << count << std::endl;

	return 0;
}

Kodu yazdım fakat çözmesi c++ kullanmama rağmen çok zaman alıyor. Bunun yerine matematik ile çözdüm.

1 basamaklı: Bir adet rakam koyabiliyoruz. 10 adet sayı var.
2 basamaklı: İki adet rakam koyabiliyoruz fakat onlar basamağına 0 gelemiyor. Birler basamağına ise onlar basamağına koyduğumuz sayıyı koyamıyoruz ama 0 koyabiliyoruz. 9*9=81 adet sayı var.

Bu şekilde devam ederek cevabın 10 + 9.9 + 9.9.8 + 9.9.8.7 + … + 9.9.8.7.6.5.4.3.2.1 olduğunu görebiliyoruz.
Bu eşitliği düzenlersek; ( P(x, y): x’in y’li permütasyonu olmak üzere )
Sonucumuz 10 + 9.( P(9, 1) + P(9, 2) + … + P(9, 9) ) oluyor.

Bunu da hesaplayan ufak bir program yazdım. Sonucu 8877691 buluyor.

from math import factorial

perm = lambda x,y: factorial(x)/factorial(x-y)

sum = 0
for i in range(1, 10):
    sum += perm(9, i)
print(10 + 9*sum)
2 Beğeni

Çünkü algoritmanız verimsiz, brute force yaparken kontrol etmeniz gereken sayıları azaltırsanız birkaç saniyede bitiyor:

from itertools import permutations

is_num = lambda i: i[-1] == 0 or i[0] != 0

numbers = tuple(range(10))
total = 0
for i in range(1, 11):
    total += sum(1 for _ in filter(is_num, permutations(numbers, i)))
print(total)
1 Beğeni

Sanırım üstteki koddan bahsetmiş. Yani tek tek sayılara bakarak olandan.

9 milyar sayiyi string’e cevirip tum karakter ciftlerini islemeyi hangi dilde yapsan yavas olur.

String kullanmazsan birkac order of magnitude hizlanacagini tahmin ediyorum.

(i, j) kontrol ettikten sonra (j, i) kontrol etmene de gerek yok. j’yi i+1’den baslatirsan bi 2 kusur kat da oradan hizlanir.

1 Beğeni

Gelelim olasılık sorularına. @aib bir konuda bahsettiği gibi olasılık soruları simule edilerek çözülebilir. İstenen şartları defalarca rastgele seçimler sonucunda çıkan sonuçlarla ve olay sayısı ile karşılaştırılarak çözülebilir. İlk sorumuz basit ama şaşırtıcı.

Bir adamın iki çocuğundan biri kız olduğuna göre diğerinin erkek olma olasılığı nedir?

Her biri farklı ağırlıkta olan 15 top var. Bu topları ağırlıklarına göre sıralamak istiyorsunuz. Bunun için size tartısıyla yardımcı olacak bir arkadaşınız var. Her tartı işleminde ona dilediğiniz 3 topu veriyorsunuz, o da size ağırlıklarını belirtmeden bu 3 topun ağırlık sıralarını bildiriyor.

Tüm topları doğru biçimde sıralamayı garantilemek için en az kaç tartı işlemi yaptırmanız gerekir?

bilardo-topu1

1/3 veya 1/2: Boy or girl paradox - Wikipedia

Toplarin 15! permutasyonu olduguna ve her olcumun uc topun 3! permutasyonundan birini verdigine gore entropi hesabiyla information theory minimumunun ⌈log(15!)/log(3!)⌉ = 16 olmasi lazim.

Dusunsel analiz yaparsak: Bir topun yerini belirlemek icin en az 7 olcum yapmamiz lazim. Olabilecek yerlerden en kotusu bas ve son; bas diyelim. Elimizde 14 topluk bir grup kaliyor, grupta 7 olcum yapilmis vaziyette.

(Gerisine vaktim kalmadi, kagit-kalem de gerekecek. Sonra devam edeyim.)

Devam:

Ilk topumuz birinci sirada cikti. Kalanlara 2…15 diyelim ve cift sayilar teklerden kucuk cikmis olsun:

1 < 2 < 3
1 < 4 < 5
1 < 6 < 7
1 < 8 < 9
1 < 10 < 11
1 < 12 < 13
1 < 14 < 15

Kalan grupta 2’nin yerini bulmak istiyoruz. 3 disinda hepsiyle karsilastirmamiz lazim:

2 <> 4 <> 6
2 <> 8 <> 10
2 <> 12 <> 14
2 <> 5 <> 7
2 <> 9 <> 11
2 <> 13 <> 15

Buradaki en kotu sonuctan emin degilim. En basta cikarsa elimizde 13 karsilastirma yapilmis 13’lu bir grup kaliyor. Ortada cikarsa 6+7’lik iki grup var. Ciftler bir grup, tekler bir grup dersek ilk asamadaki 7 karsilastirma da cope gitmis oluyor. Ikinci asamadaki karsilastirmalari da cope atacak bir 6+7 grup dagilimi var mi bilmiyorum ama hepsi cope gitse bile 6’li bir grubu, sonra 7’li bir grubu ayri ayri dizmek 13’luk bir grubu dizmekten daha kolay.

Bu noktada da sunu fark ediyoruz:

En kotu durumda her topu her diger topla karsilastirmak zorundayiz. (n×(n-1)÷2)
En iyi durumda her tartma bize 2 karsilastirma veriyor. En kotude 1.
Yani cevap 52.5 ile 105 arasinda gibi.

(Bu noktadaki challenge: 53’u garanti edecek tartmalari ureten kod.)

Fakat 2 tartmadan 5 (hatta daha fazla) karsilastirma cikabiliyor:

A < B < C ve D < E < B ise E < C oldugunu biliyoruz. Veya daha basidi:
A < B < C ve C < D < E ise A < D, A < E, … (toplam 10)

Acaba bunu garanti edecek tartma gruplari cikartabilir miyiz, yoksa her halukarda en kotu durumda 105 karsilastirma icin 53 tartma yapmak zorunda miyiz? (Challenge: n tartma ile 2n’den fazla karsilastirma bilgisi vermeyi garanti eden tartma gruplari bul.)

Neyse, sanirim artik literaturu okuma hakki kazandim.

Edit: Gereken ikili karsilastirma sayisi bile formulu bilinmeyen (ve n*(n-1)/2’den kucuk) bir sayiymis:

4 Beğeni
from random import randint

class Tarti:
    def __init__(self):
        self.sozluk = {}
        self.tartma_sayisi = 0

    def generate(self):
        agirliklar = []
        top_numarasi = 1
        for n in range(15):
            while True:
                agirlik = randint(1, 100)
                if agirlik not in agirliklar:
                    agirliklar.append(agirlik)
                    break
            self.sozluk.update({top_numarasi: agirlik})
            top_numarasi += 1
        return self.sozluk

    def tart(self, x, y, z):
        if x != y != z:
            self.tartma_sayisi += 1
            return sum((self.sozluk[numara] for numara in (x, y, z)))
        else:
            raise ValueError("Sadece 3 'farklı' top tartılabilir!")

    # top numaralarının daima 1'den 15'e kadar olduğunu düşünelim.
    def cozum(self):
        yerel_sozluk = {1: 0}
        ilk_top_agirligi1 = self.tart(1, 2, 3)
        ilk_top_agirligi2 = self.tart(1, 4, 5)
        for numara in range(4, 16):
            yerel_sozluk.update({numara: self.tart(numara, 2, 3) - ilk_top_agirligi1})
        for numara in range(2, 4):
            yerel_sozluk.update({numara: self.tart(numara, 4, 5) - ilk_top_agirligi2})
        _ = {k: v for k, v in sorted(yerel_sozluk.items(), key=lambda item: item[1])}.keys()
        return _
        

generate() fonksiyonu ile self.sozluk içerisinde {numara: agirlik} olacak şekilde 15 tane top oluşturuyoruz.

tart() fonksiyonu parametre olarak 3 ‘farklı’ top kabul ediyor. Sonrasında self.sozluk’teki verilere göre bu 3 topun ağırlığını return ediyor.

  • cozum() fonksiyonu içerisinde her bir topun, 1 numaralı toptan ne kadar ağır veya ne kadar hafif olduğunu hesaplayarak yerel bir sözlüğe atıyoruz.

  • Bunu yaparken de tart() fonksiyonuna parametre olarak gönderdiğimiz 3 topun 2’sini aynı tutuyoruz. Mesela tart(5, 2, 3) - tart(1, 2, 3) bize 5’in 1’e göre ağırlığı hakkında bilgi veriyor.

  • 2 ve 3’ü de başka bir döngü içerisinde hesaplıyoruz. Bir önceki mantık ile hareket edip tart(2, 4, 5) - tart(1, 4, 5) yaparak onların da 1’e göre ağırlıklarını hesaplıyoruz.

  • En sonda ise sözlüğü, değerlerine göre ‘sort’ ederek, 'key'lerini return ediyoruz.

*Not: yerel_sozluk = {1: 0} olma nedeni, diğer tüm topların ağırlığını 1’e göre bulmuş olmamızdır. Yani ‘merkez kabul etmiş olduğumuz için’ de diyebiliriz.

T = Tarti()
print(f"Sözlük: {T.generate()}")
print(f"Çözüm: {T.cozum()}")
print(f"Toplam tartma sayısı: {T.tartma_sayisi}")
Sözlük: {1: 3, 2: 26, 3: 82, 4: 17, 5: 16, 6: 53, 7: 13, 8: 93, 9: 40, 10: 20, 11: 91, 12: 77, 13: 71, 14: 58, 15: 43}
Çözüm: dict_keys([1, 7, 5, 4, 10, 2, 9, 15, 6, 14, 13, 12, 3, 11, 8])
Toplam tartma sayısı: 16
Sözlük: {1: 37, 2: 69, 3: 70, 4: 84, 5: 35, 6: 38, 7: 96, 8: 27, 9: 41, 10: 47, 11: 63, 12: 97, 13: 4, 14: 100, 15: 46}
Çözüm: dict_keys([13, 8, 5, 1, 6, 9, 15, 10, 11, 2, 3, 4, 7, 12, 14])
Toplam tartma sayısı: 16
Sözlük: {1: 89, 2: 29, 3: 55, 4: 71, 5: 33, 6: 18, 7: 10, 8: 62, 9: 52, 10: 79, 11: 75, 12: 99, 13: 38, 14: 85, 15: 56}
Çözüm: dict_keys([7, 6, 2, 5, 13, 9, 3, 15, 8, 4, 11, 10, 14, 1, 12])
Toplam tartma sayısı: 16

Edit: Çözüm yolu yanlış.

3 Beğeni

Merhaba, bize verilen bilgi 3 topun toplam ağırlığı değil, o topların sırası. Bu yüzden tart fonksiyonu kullanamıyoruz.

1 Beğeni