Category Archives: Programlama

Tüm programlama içeriklerim

Yazılım görüşmelerinde soruya yaklaşım tekniği

Daniel Habib isimli bir programcı, yazılım görüşmelerinde konu ne olursa olsun nasıl bir yaklaşım sergilemeniz gerektiği konusunda bir spreadsheet oluşturmuş.

1. İnceleme

  • İnput’un ne olduğunu açıkça belirttim mi?
  • İstenen output’un ne olduğunu netleştirdim mi?
  • Elle çözülebilecek basit bir örnek oluşturdum mu?
  • Tüm aksiyomları yazdım mı?
  • Tüm constraints‘ler benim için ok midir?
  • Tüm akla yatkın varsayımları yazıp türettim mi?

2. Strateji

  • Brute force bir çözüm için beyin fırtınası yaptım mı?
  • Brute force çözümün çalışma zamanını analiz ettim mi?
  • Brute force çözümün space gereksinimini analiz ettim mi?
  • İnput’un memory üzerindeki kapladığı büyüklük ne kadar?
  • Daha iyi, daha karmaşık bir çözüm bulabildim mi?
  • Bu çözümün time complexity‘sini analiz ettim mi?
  • Bu çözümün space complexity‘sini analiz ettim mi?
  • Bu çözümü doğrudan ilk uyguladığım basit çözümümle karşılaştırdım mı?
  • Kodlamaya başladığımda kendime güveniyor muyum?
  • Aklıma gelen tüm yaklaşımları düşündüm mü?
  • İstediğim stratejiyi açıkça yazdım mı?
  • Açıkça base case‘leri dikkate aldım mı? Takıldığım durumlarda ne kadar iyi idare ettim?

3. Kodlama

  • Kodum ne kadar temiz yazılmıştı?
  • Off-by-one hatalarını kontrol ettim mi? Yani index’lerin 0’dan başlaması veya while içerisinde <= yerine < kullanımı gibi.
  • Kodlama sırasında hangi fonksiyonları kullanacağımı tahmin edebildim mi?
  • İnceleme kısmında yaptığım “Beyin fırtınası stratejim” sorunu çözdü mü?
  • Kodlama süreci ne kadar sorunsuzdu?
  • Yazdığım kod ile çözümümü anlatabildim mi?
  • Kodumdaki ilginç fonksiyonların avantajlarından yararlandım mı?

4. Review

  • Time complexit’yi kanıtladım mı?
  • Space complexit’yi kanıtladım mı?
  • Farklı test senaryoları yazıp bunları uyguladım mı?
  • Ne kadar önemsiz olursa olsun satır satır mı gittim?
  • Kodumu gözden geçirirken herhangi bir değişiklik yapmam gerekti mi?

Kaynak: https://docs.google.com/spreadsheets/d/1gy9cmPwNhZvola7kqnfY3DElk7PYrz2ARpaCODTp8Go/htmlview?pru=AAABfLycr3M*TqxdBeNP9JuAGHyhyIwE_A

Kaç yaşındasın sen?

Bir gün karşınıza Ozan Güven çıkıp ta “Kaç yaşındasın sen?” derse ne yapardınız? Basit bir soru değil mi bu? Ancak, sorunun ayrıntı düzeyine ve bakış açınıza bağlı olarak cevap değişebilir.

Peki soruyu şöyle değiştirelim o zaman; “Kaç dakikadır yaşıyorsun?”. Bu soruyu yanıtlamak için, kolayca elde edilebilecek olandan çok daha fazla bilgiye ihtiyacımız var:

  • Doğum tarihiniz ve tam saati
  • Doğumunuzun zaman dilimi (veya konumu)
  • Bir yaz saati uygulamasına geri dönüş geçişi sırasında doğduysanız, (bazı saat dilimlerinde) saatler geriye doğru hareket ettiğinde – örneğin, 2:59:59 AM’den 2:00:00 AM’ye kadar. 2:30’da doğduysanız, o gece 2:30 saati aslında iki defa yaşandığı için hangisinde doğduğunuzu bilmeniz gerekir.
  • UTC olarak ifade edilen geçerli evrensel saat.

Çoğu insan tüm bu bilgilere düzenli olarak sahip değildir ve genellikle umursamıyoruz da bu tarz bilgileri. Neden umursayalım ki? Birisi ne kadar süredir hayatta, ölü, evli, çalışıyor veya benzeri bir soru sorduğunda, genellikle “30 yıl” veya “6 ay” veya bazen “2 yıl, 4 ay ve” gibi takvimsel bir cevap veriyor oluruz.

Bu, bir takvimin kullanılması anlamına gelir ve genellikle modern zamanlardaki Gregoryen (yani Miladi) takvimini önemsiyoruz.

Burada temel şudur; takvimsel bir ölçü birimi, zaman geçişinin insanlaştırılmış bir ifadesidir. Bu, bilgisayarın tipik olarak ölçtüğü ve programcılar için genellikle kafa karışıklığı yaratan geçen süreden oldukça farklı bir kavram.

Üstelik buna “Doğu Asya yaş hesaplaması” gibi kavramları eklemiyorum bile. Binlerce yıldır Kore, Japonya, Vietnam, Çin gibi ülkelerde insanlar 1 yaşında doğuyorlar. Ve yaşları doğum günlerinde değil de, yılbaşında artıyor. Yani bir bebek 31 Aralık’ta doğduğunda, ertesi gün aslında iki yaşına giriyor. Sizinkinin ne olduğunu öğrenmek istiyorsanız, şu basit denklemi takip edin: İçinde bulunduğunuz yılı alın, doğum yılınızı çıkarın ve bir ekleyin.

Üstelik Kore gibi ülkelerde, “yaş” kavramı çok önemlidir. Sizden yaşlı insanlara karşı saygılı olma Kore kültürünün önemli bir parçası. Bir kişi sizden 1 yaş büyük bile olsa, o kişi ile birlikte bir şeyler yemenizi, içmenizi ve hatta konuşmanızı değiştirebilir. Çin ve Vietnam’da bu hesaplama genellikle yaşlı insanlar tarafından kullanılırken, Kore’de bu herkes tarafından kullanılıyor.

Yüzlerce yıldır Koreliler yaşı hesaplamak için dünyanın çoğundan farklı bir yöntem kullandılar. Bazen ay yaşı, nominal yaş veya Doğu Asya yaşı hesaplaması olarak anılır, ancak Kore’de buna sadece Kore yaşı denir. Yöntemin kökenleri Asya’nın farklı bölgelerine yayılmadan önce Çin’dedir, ancak bugün Güney Kore herkesin hala kullandığı tek ülkedir.

Ozan güven “Kaç yaşındasın sen?” diye sorduğunda karşısındaki kişi “19” demişti. Buna karşılık olarak ta Ozan güven “16 yaşında bi tane adamsın.” diyerek karşılık vermişti. Yaş kavramının bu kadar karışık olduğu bir dünyada, belki de ozan güven haklıdır, kim bilir..

2038 yılı problemi

2038 yılında bilgisayar sistemlerini etkileyebilecek bu problemi açıklamaya çalıştım bu videoda.

Bundan önce daha iyi anlaşılması adına bahsetmek istediğim y2K, yani 2000 yılı bug‘ı.

Bildiğiniz gibi bilgisayar sistemleri 1950’li yıllarda geliştirilmeye başlandı ve günümüze kadar devam etti. Bu süreçte birçok program yılları yalnızca son iki basamakla temsil ederek 2000 yılını 1900’den ayırt edilemez hale geldi. Bu da 1 ocak 2000’de bir çok sistemde problemler yaşanacağına dair kehanet oluşmasına neden oldu.

Peki ne oldu 1 Ocak 2000 günü?

Aslında çok büyük bir olay yaşanmadı, Avustralya’da otobüslerde bilet kontrolü yapılan makinalar bozuldu, Japonya’da bir kaç mobil markasında hatalar yaşandı, Amerikada bazı slot makinaleri çalışamaz hale geldi. Yani ölümcül bir olay yaşanmadı bilişim sistemlerinde. Korkulduğu gibi olmadı yani.

2038 yılı problemi ise, birçok dijital sistemde zamanı 1 Ocak 1970 UTC gece yarısından (Unix time) bu yana geçen saniye sayısı olarak temsil etmek ve onu işaretli bir 32-bit tamsayı olarak saklamakla ilgilidir. Bu tür uygulamalar, 19 Ocak 2038’de UTC 03:14:07’den sonraki süreleri kodlayamaz. Y2K sorununa benzer şekilde, Yıl 2038 sorunu, zamanı temsil etmek için seçilen yetersiz sayıda bit (rakam) nedeniyle oluşur.

Nedenleri;

  • 1 Ocak 1970’den bu yana, işaretli bir 32-bit tamsayı kullanılarak depolanabilen en son zaman, 19 Ocak 2038 Salı günü 03:14:07’dir (2^31 − 1 = 1 Ocak 1970’ten sonra 2.147.483.647 saniye).
  • Bu tarihten sonraki süreyi artırmaya çalışan programlar, değerin dahili olarak negatif bir sayı olarak saklanmasına neden olur ve bu sistemler, 13 Aralık 1901 Cuma günü 20:45:52’de (1 Ocak 1970’den 2,147,483,648 saniye önce) meydana geldiği şeklinde yorumlayacaktır. ). Bu, sayacın kullanılabilir ikili rakamların veya bitlerin bittiği ve bunun yerine işaret bitini çevirdiği tamsayı taşmasından kaynaklanır.

Hangi sistemler savunmasız?

Öncelikle embeded olarak çalışan ve özellikle tarihleri hesaplama veya loglama için kullanan sistemler. Özellikle uçuş sistemlerinde ve otomobillerde yoğun olarak kullanılıyor bu tarz sistemler. Bu sistemlerdeki ABS gibi kilitlenme önleyici fren sistemleri, ESC ve ESP gibi elektronik stabilite kontrolü yapan kısımlar ve GPS alıcıları kullanıyor olabilir. Ancak bu, tüm bu sistemlerin Y2038 sorunundan etkileneceği anlamına gelmez, çünkü bu tür birçok sistem tarihlere erişim gerektirmez. Bunu yapanlar için, mutlak saatler/tarihler değil de, yalnızca saatler/tarihler arasındaki farkı izleyen sistemler hesaplamanın doğası gereği büyük bir sorun yaşamayacaktır.

Ayrıca mysql’in 2021 ağustos sürümünden önceki versiyonlarında, UNIX_TIMESTAMP fonksiyonu 19 Ocak 2038 Salı günü 03:14:07’den sonra 0 döndürüyormuş.

Problemi veri yapıları hangileri?

Günümüzde kullanılan birçok veri yapısı, gömülü 32 bitlik zaman temsiline sahip. Ama tam bir liste vermek neredeyse imkansız.

Dosya sistemleri (birçok dosya sistemi, süreleri temsil etmek için yalnızca 32 bit kullanır), binary dosya biçimleri (32 bit zaman alanlarını kullanan), veritabanları (32-bit zaman alanları olan), UNIX_TIMESTAMP() benzeri komutlara sahip SQL gibi veritabanı sorgu dilleri vs..

Kısaca 32-bit zaman gösterimleri içeren veri yapılarını kullanan herhangi bir sistem risk arz edecektir.

Peki çözümü nedir?

2038 Yılı sorunu için evrensel bir çözüm yoktur. Örneğin Freebsd ve OpenBsd gibi işletim sistemleri bazı değişiklikler yapmışlar ama bazı değişiklikleri de “backward compatibility” nedeniyle yapamamışlar.

Neden umursayalım ki daha 17 sene var?

Bazen gelecekte bazı şeyler olur ve bunun ne zaman olacağını bilmek isteriz. Bazen, 17 yıllık bir ipotek gibi, 17 yıldan fazla bir süre sonra planlanması gerekir. Bu sorun zaman geçtikçe daha da kötüleşecek, çünkü yazılım geliştirici olmanın en sinir bozucu yanlarından biri, her zaman upgrade yapmayan birilerinin olmasıdır. Ve her zaman, asla upgrade yapmayan bir çok insan olacak, emin olun.

64 bit işlemcileri kullanmaya başladığımızda sorun ortadan kalkacak, değil mi?

64 bit işlemci kullanmanız, 2038 yılı bug’ı konusunda temiz olduğunuz anlamına gelmez. Örneğin, yeni Apple bilgisayarınızda 64 bit işlemci var ama işletim sistemi hala 32 bit tam sayılar ve 32 bit time_t ile çalışıyor.

Tamsayı boyutunu değiştirdiğinizde, tüm yazılımınızı yeniden derlemeniz gerekir. O zaman Mac uygulamalarının 32 bit ve 64 bit sürümleri göndermesi gerekir. Ancak bu durum hem geliştirici, hem de kullanıcı için acı verici ve sorunlu bir süreç.

Ve sırf yeni bir 64 bit işlemci kullanıyor olmanız, herkesin kullanacağı anlamına da gelmez. 32 bit işlemciler sadece PC’lerde ve eski donanımlarda değil, arabanızda, telefonunuzda, saatinizde, TV’nizde, DVD oynatıcınızda da ucuz ve bol bol duruyor olacak.

Rob Pike’tan programlamanın 5 kuralı

Texas üniversitesinin sitesinde bulunan, Adnan Aziz’in yazdığı “”Rob Pike: Programlamanın 5 kuralı” makalesini inceledim.

Rob Pike kimdir peki? Kendisi programlama dünyasında çok saygı duyulan bir abimiz. 2002 – 2021 yılları arasında Google’da çalışmış bu abimiz en fazla Go programlama dilinin yaratıcılarından biri olarak bilinir. Ek olarak Unix takımında yer alıp, Bell laboratuvar‘ında çalışmış. Ayrıca Ken Thompson ile UTF-8’i geliştirmiş.

İşte o 5 kural;

1. Yazdığınız bir programın zamanı nerede harcayacağını bilemezsiniz. Darboğazlar şaşırtıcı yerlerde meydana gelir, bu nedenle darboğazın nerede olduğunu kanıtlayana kadar ikinci bir tahminde bulunmaya ve bir hız kesme işlemi yapmaya çalışmayın.

2. Ölçüm. Ölçene kadar hız için ayarlama yapmayın ve o zaman bile kodun bir kısmı geri kalanını boğmadıkça yapmayın. (Erken optimizasyon, tüm kötülüklerin köküdür.)

3. Havalı algoritmalar, n küçük olduğunda yavaştır ve n genellikle küçüktür. Havalı algoritmaların büyük sabitleri vardır. n’nin sıklıkla büyük olacağını bilene kadar, süslenmeyin. (n büyüse bile, önce Kural 2’yi kullanın.)

4. Havalı algoritmalar, basit olanlardan daha karmaşıktır ve uygulanması çok daha zordur. Basit veri yapılarının yanı sıra basit algoritmalar kullanın. (Kararsızsanız, brute force kullanın)

5. Veri domine eder. Doğru veri yapılarını seçtiyseniz ve işleri iyi organize ettiyseniz, algoritmalar neredeyse her zaman belli olacaktır. Algoritmalar değil veri yapıları programlamanın merkezindedir.

Kaynaklar:

KISS prensipleri: https://en.wikipedia.org/wiki/KISS_principle

The Mythical Man-Month: https://en.wikipedia.org/wiki/The_Mythical_Man-Month

“Nicelık vs nitelık” üzerine

Jeff Atwood 2008 yılında Quantity Always Trumps Quality yazmış, ben yeni gördüm, bu da bizim ayıbımız olsun.

Yazıda alıntı yaptığı kısmı şu şekilde özetleyebilirim;

Bir seramik öğretmeni okulun ilk gününde sınıfı iki gruba ayırdığını duyurur. Sınıfın sol tarafındakilerin tümü, yalnızca ürettikleri işin miktarına göre derecelendirileceğini, sağdakilerin ise yalnızca kalitesine göre derecelendirileceğini söyler. Yaptığı prosedür basit; günün sonunda, tartıyı getirerek sol taraftaki gruptan 50 kiloluk “A” kalitede ve 40 kiloluk “B” vb. devam eden kalitede ürün çıkartılması beklenirken, sağ taraftaki gruptan sadece 1 kiloluk “kaliteli” ürün ürün çıkartılması beklenmiş.

Değerlendirme zamanı gelir ve ilginç bir sonuç ortaya çıkar; en yüksek kalitede eserlerin tümü, miktar açısından derecelendirilen grup (sol taraftaki) tarafından üretilir. Görünüşe göre, “nicelik” grubu yığınlar halinde iş yapmakla ve hatalarından ders alırken, “nitelik” grubu “mükemmellik” hakkında teoriler üretmekle meşguldü.

Yani, yaptığınız ve üzerinde uzun süre düşündüğünüz tasarım ve teorilere istinaden, bu harcanan zamanın bir şeyleri “geliştirmek,” üzerine daha iyi harcanabileceğidir. Buradaki temel düşünce, erken şekilde başarısızlık için harcadığınız zaman, “doğru şekilde yapmaya çalıştığınız” her şeyi öğrenmek için harcadığınız zamandır. Bu, “yanlış” şeyi geliştirmek için zaman harcayarak elde edemeyeceğiniz bir fayda. Bu orijinal ya da yeni bir fikir değil tabi ki. İşin güzel tarafı, Jeff Atwood burada çömlek yapmaktan yazılım geliştirmeye, veya blog yazısı yazmak için gerekli disiplinler için nasıl geçerli olduğunu açıklamış.

Bu tavsiyeyi değerli kılan, bize hata yapmaktan “korkmamayı” öğretmesi. Sadece bu değil, hatalarımızı “kabul etmeyi” de öğrenebiliriz çünkü sonuçta bu şekilde gerçekten “öğreniriz”. Eğer bir şey durgunlaşmışsa, – bu bir yazılım geliştirmesi de olabilir, kişisel bir ilişki de- bu durgunluktan çıkmak için rastgele bir şey yapmanın hiç bir şey yapmamaktan daha iyi olabileceğini düşünüyorum. Bunu yaparsanız, sonuçları analiz edebilir ve neyi “düzeltmemiz” gerektiğini anlayabiliriz.

Sayı 2’nin tam kuvveti mi? [İteratif ve Bit manipülasyonu]

Bir sayının 2’nin bir tam kuvveti olup olmadığını nasıl bulabileceğinizi, hem iteratif yolla hem de bit manipülasyon yöntemleri ile anlatmaya çalıştım.

► İkinin kuvveti https://tr.wikipedia.org/wiki/%C4%B0kinin_kuvveti

Matematikte ikinin kuvveti, n bir tam sayı iken 2^n şeklinde gösterilebilen sayıdır. Bu üslü sayıda 2 taban, n ise üstür.

Sadece tam sayılar içinde düşünülecek olursa, n ancak pozitif bir değer alabilir. Bu durumda sonuç, 1, 2 ya da 2’nin belirli kere kendisiyle çarpılmasıyla elde edilen sayı olacaktır.

İki ikili sayı sisteminin de tabanını oluşturduğundan, ikinin kuvvetlerine bilgisayar biliminde sık rastlanır. Bu sistemde ikinin bir kuvveti her zaman onluk sayı sistemindeki onun kuvvetleri gibi 100…000 ya da 0.00…001 benzeri bir şekilde yazılacaktır.

Videodaki metodun text hali şurada: https://pastecode.io/s/RhOXm02CB7

Programlamada Fibonacci Serisi Ve Sayılarını Bulma

Programlamada fibonacci serisi ve belirli sıradaki fibonacci sayısı nasıl hesaplanır? Binet formülü kullanılarak belirli fibonacci sayısı nasıl hesaplanır?

► Fibonacci dizisi nedir? https://tr.wikipedia.org/wiki/Fibonacci_dizisi

Fibonacci dizisi, her sayının kendinden önceki ile toplanması sonucu oluşan bir sayı dizisidir. Bu şekilde devam eden bu dizide sayılar birbirleriyle oranlandığında altın oran ortaya çıkar, yani bir sayı kendisinden önceki sayıya bölündüğünde altın orana gittikçe yaklaşan bir dizi elde edilir.

        /// <summary>
        /// N adet fibonacci sayısını bir dizi olarak döner.
        /// </summary>
        static int[] Fibonacci(int n)
        {
            var fibSequence = new int[n];
            var prev = 0;
            var curr = 1;

            for(var i = 1; i < n; i++)
            {
                fibSequence[i] = curr;
                curr = curr + prev;
                prev = curr - prev;  
            }

            return fibSequence;
        }

        /// <summary>
        /// N index'li fibonacci sayısını dinamik programlama kullanarak döner.
        /// </summary>
        static int FibonacciNth(int n)
        {
            if (n == 0) return 0;
            if (n == 1) return 1;

            var curr = 1;
            var prev = 0;

            var counter = n - 1;

            while(counter > 0)
            {
                curr = curr + prev;
                prev = curr - prev;
                counter--;
            }

            return curr;
        }

        /// <summary>
        /// N index'li fibonacci sayısını Binet formülünü kullanarak döner.
        /// https://en.wikipedia.org/wiki/Fibonacci_number#Closed-form_expression
        /// 1 ile 75 arasındaki n sayıları için geçerlidir.
        /// </summary>
        static int FibonacciNthClosedForm(int n)
        {
            var rootOfFive = Math.Sqrt(5);
            var phi = (1 + rootOfFive) / 2; // (≈ 1.61803)

            return (int)Math.Floor(Math.Pow(phi, n) / rootOfFive + 0.5);
        }

Bit Manipülasyonları – 3. Kısım

Bit manipülasyonlarını, bilgisayar aritmetiğinde elde ettiğiniz verinin bitleri üzerinde değişiklikler/kontroller yaparak, elde etmek istediğiniz sonuca genellikle daha hızlı bir şekilde erişmenizi sağlayacak işlemler bütünü olarak adlandırabiliriz.

► Bit manipulation: https://en.wikipedia.org/wiki/Bit_manipulation

Bit manipulation is the act of algorithmically manipulating bits or other pieces of data shorter than a word. Computer programming tasks that require bit manipulation include low-level device control, error detection and correction algorithms, data compression, encryption algorithms, and optimization. For most other tasks, modern programming languages allow the programmer to work directly with abstractions instead of bits that represent those abstractions. Source code that does bit manipulation makes use of the bitwise operations: AND, OR, XOR, NOT, and possibly other operations analogous to the boolean operators; there are also bit shifts and operations to count ones and zeros, find high and low one or zero, set, reset and test bits, extract and insert fields, mask and zero fields, gather and scatter bits to and from specified bit positions or fields. Integer arithmetic operators can also effect bit-operations in conjunction with the other operators.

► Bir manipülasyonları nerelerde kullanılır?

Eğer “bit manipülasyonu”nun faydalarını elde edemeyeceğiniz bir proje ise, muhtemelen bunları kullanmamalısınız. Tıpki bir çok enterprise uygulama gibi. İyi tarafları hızlı olmaları, kötü(?) tarafları anlaşılabilirliğin düşük olması, kod okunabilirliğini azaltmaları ve maintain edilebilmelerinin zorluğu diyebilirim. Bunun dışında, en küçük bir “performans” kaybı bile sizin için değerli ise, o zaman bunları kullanmayı düşünebilirsiniz. Örnek olarak, C ile driver geliştirirken, en derin seviyede bir matematiksel işlemler yapıyorsanız bunları kullanabilirsiniz. Genel olarak right shift ve left shift operatörleri, çarpma ve bölme işlemlerine göre genellikle hızlı çalışırlar. Tabi günümüz derleyicileri, bunları olabildiğince optimize ediyorlar hali hazırda.

        /// <summary>
        /// Sayını kaç adet bitten oluştuğunu bulur.
        /// </summary>
        static int BitCount(int n)
        {
            var bitCount = 0;

            while((1 << bitCount) <= n)
            {
                bitCount++;
            }

            return bitCount;

            // Örn: n = 5, yani 101, bizim 1 sayısını 3 defa ötelersek 1000
            // değerine, yani 5'ten büyük bir değer görüyoruz.
        }

        /// <summary>
        /// Belirli bir pozisyondaki bit değerini getirir.
        /// </summary>
        static int GetBit(int n, int position)
        {
            return (n >> position) & 1;

            // Ör: 11010 ve position = 3 olsun.
            // Sağa shift ettiğimizde elimizde 11 değeri kalır.
            // Bunu da 1 ile bitwise AND'lediğimizde, 
            // son bit eğer 1 ise 1, değilse 0 döndürür.
        }

        /// <summary>
        /// Sayı çift mi?
        /// </summary>
        static bool IsEven(int n)
        {
            return (n & 1) == 0;
        }

        /// <summary>
        /// Sayı pozitif mi?
        /// </summary>
        static bool IsPositive(int n)
        {
            if(n == 0)
            {
                return false;
            }

            return ((n >> 31) & 1) == 0;

            // 31 adet shift ile most significant bit'i buluruz.
            // Bu bit 0 ise pozitif, değilse negatiftir.
        }

Asal Çarpanları Bulma Algoritması

Bir sayıyı oluşturan asal çarpanların nasıl en efektif şekilde bulunabileceğini anlattım bu videoda. Önemli olan iki nokta var; birincisi kontrol edeceğimiz sayıları verilen sayının kareköküne kadar (karekökü dahil) iterasyon ile kontrol etmek ve elimizdeki sayıyı bölebildiğimiz kadar o sayıya bölmek, ikincisi de eğer bu iterasyon sonrası sayımız 1’e eşit olmadıysa (videoda anlattığım 99 örneği gibi) son kalanı da listeye eklemek.

► Asal çarpan nedir? https://tr.wikipedia.org/wiki/Asal_%C3%A7arpan

Asal çarpan, bir sayının asal olan çarpanlarına denir. Örnek olarak 72 sayısının asal çarpanları 2 ve 3’ken (2^3 * 3^2), 4, 6, 8, 9, 12, 18, 24, 36, 72 asal çarpan değildir. Aritmetiğin temel teoremine göre bütün bileşik sayılar, asal çarpanların çarpımı olarak yazılabilmektedir.

        /// <summary>
        /// Sayının tüm asal çarpanlarını bulma
        /// </summary>
        static IList<int> PrimeFactors(int n)
        {
            var factors = new List<int>();

            for(var i = 2; i <= Math.Sqrt(n); i++)
            {
                while(n % i == 0)
                {
                    n /= i;
                    factors.Add(i);
                }
            }

            if (n != 1)
                factors.Add(n);

            return factors;
        }

Öklid Algoritması ile En Büyük Ortak Bölen Nasıl Bulunur?

Öklid Algoritması ile en büyük ortak bölenin (ebob) nasıl bulunabileceğini hem iteratif, hem de rekürsif yolla anlatmaya çalıştım bu videoda.

► Öklid Algoritması: https://tr.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/the-euclidean-algorithm

İki A ve B tam sayısının Ortak Bölenlerinin En Büyüğünün (OBEB), A ve B’yi bölen en büyük tam sayı olduğunu hatırlayalım.

Öklid Algoritması, iki tam sayının OBEB’ini hızlıca bulmak için kullanılan bir yöntemdir.

OBEB(A,B)’nin bulunması için Öklid Algoritması şu şekildedir:

► Eğer A=0 ise, OBEB(0,B)=B olacağı için OBEB(A,B)=B olur ve bu noktada durabiliriz.

► Eğer B=0 ise, OBEB(A,0)=A olacağı için OBEB(A,B)=A olur ve bu noktada durabiliriz.

► A sayısını bölüm ve kalan formunda yazın (A=B⋅Q+R)

►OBEB(A,B)=OBEB(B,R) olduğu için, OBEB(B,R)’yi Öklid Algoritmasını kullanarak bulun

► Ortak bölen nedir? https://tr.wikipedia.org/wiki/Ortak_b%C3%B6len

Matematikte, sıfır olmayan iki veya daha fazla pozitif tam sayının en büyük ortak böleni, tam sayıların hepsini de bölen en büyük pozitif tam sayıdır. Örneğin; 8 ve 12’nin ebob’u 4’tür.

En büyük ortak bölen aynı zaman da en büyük ortak faktör (ebof), en yüksek ortak faktör (eyof) ile de isimlendirilir.

        /// <summary>
        /// En büyük ortak böleni bulmak
        /// </summary>
        static int GreatestCommonDivisor(int a, int b)
        {
            while(a != 0 || b != 0)
            {
                if(a > b)
                {
                    a %= b;
                }
                else
                {
                    b %= a;
                }
            }

            return a | b;
        }

        /// <summary>
        /// En büyük ortak bölüne rekürsif yolla bulmak
        /// </summary>
        static int GcdRecursive(int a, int b)
        {
            if(b == 0)
            {
                return a;
            }
            else
            {
                return GcdRecursive(b, a % b);
            }
        }