Clear        


                
                    using _26_RecursiveMethods.Demos.TasKagitMakas;

namespace _26_RecursiveMethods
{
    internal class Program
    {
        // Recursive methodlar kendi içerisinde kendisini çağıran methodlardır.
        // Methodun kendisini çağırmasından dolayı sanki bir döngü işlemi yapılıyormuş gibi düşünülebilir.
        // Methodun kendisini sonsuz kere çağırmasının önüne geçmek için mutlaka methodu sonlandıran bir koşul yazılmalıdır.
        // Genelde organizasyon şeması gibi hiyerarşik yapılarda kullanılır.



        static void Main(string[] args)
        {
            DisplayNumbersByLoop(1, 10);

            Console.WriteLine();

            DisplayNumbersByRecursion(10, 20, 2);

            Console.WriteLine();

            List<int> list = new List<int>() { 1, 2, 3, 4, 5 };

            int itemToFind = 3;
            int? itemResult = FindItemInListByLoop(list, itemToFind);

            // 1. yöntem
            //if (itemResult == null) // eğer sonuç null ise (itemResult'ın tipi nullable yani null değere sahip olabilir)
            //    Console.WriteLine("Item not found.");
            //else // eğer sonuç null değilse
            //    Console.WriteLine(itemResult + " found.");
            // 2. yöntem:
            if (!itemResult.HasValue) // eğer sonucun değeri yoksa yani null ise
                Console.WriteLine("Item not found.");
            else // eğer sonucun değeri varsa yani null değilse
                Console.WriteLine(itemResult.Value + " found.");

            itemResult = FindItemInListByRecursion(list, itemToFind);
            Console.WriteLine(itemResult.HasValue ? itemResult.Value + " found." : itemToFind + " not found.");

            Console.WriteLine();

            itemToFind = 6;

            itemResult = FindItemInListByLoop(list, itemToFind);
            Console.WriteLine(itemResult.HasValue ? itemResult.Value + " found." : itemToFind + " not found.");

            itemResult = FindItemInListByRecursion(list, itemToFind);
            Console.WriteLine(itemResult.HasValue ? itemResult.Value + " found." : itemToFind + " not found.");



            #region Taş Kağıt Makas Demo
            TasKagitMakasDemo tasKagitMakasDemo = new TasKagitMakasDemo();
            tasKagitMakasDemo.Calistir();
            #endregion
        }



        /// <summary>
        /// for döngüsü üzerinden başlangıç (start), bitiş (end) ve arttırma (increment)
        /// parametrelerini kullanarak sayıları yazdırır.
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="increment"></param>
        static void DisplayNumbersByLoop(int start, int end, int increment = 1)
        {
            for (int i = start; i <= end; i += increment)
            {
                Console.WriteLine(i);
            }
        }



        /// <summary>
        /// Methodun kendi içerisinde kendisini çağırarak (recursion) başlangıç (start), bitiş (end) ve arttırma (increment)
        /// parametrelerini kullanarak sayıları yazdırır.
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="increment"></param>
        static void DisplayNumbersByRecursion(int start, int end, int increment = 1)
        {
            if (start > end) // başlangıç değeri bitiş değerinden büyük olduğunda methodu sonlandır
            {
                return;
            }
            Console.WriteLine(start);
            start += increment;
            DisplayNumbersByRecursion(start, end, increment); // methodun tekrar kendisini çağırması
        }



        /// <summary>
        /// Gönderilen liste parametresi (list) içerisinde foreach döngüsü üzerinden sayı (itemToFind) parametresini 
        /// arayan ve eğer sayıyı listede bulursa sayıyı, bulamazsa null dönen method.
        /// </summary>
        /// <param name="list"></param>
        /// <param name="itemToFind"></param>
        /// <returns>int?</returns>
        static int? FindItemInListByLoop(List<int> list, int itemToFind)
        {
            // 1. yöntem:
            //Nullable<int> result = null;
            // 2. yöntem:
            int? result = null; // Değer tiplerin Nullable tipi içerisine değer tip tanımlanarak veya yanına
                                // ? yazılarak null değer kullanmaları sağlanabilir.
                                // Burada sayı listede bulunamazsa ilk değer olarak null atandığından
                                // method sonucunda null dönecektir, sayının bulunması durumunda da method sayıyı dönecektir.

            foreach (var item in list)
            {
                if (item == itemToFind)
                {
                    result = item;
                    break;
                }
            }
            return result;
        }



        /// <summary>
        /// Gönderilen liste parametresi (list) içerisinde recursion üzerinden sayı (itemToFind) parametresini 
        /// arayan ve eğer sayıyı listede bulursa sayıyı, bulamazsa null dönen method.
        /// </summary>
        /// <param name="list"></param>
        /// <param name="itemToFind"></param>
        /// <param name="result"></param>
        /// <returns>int?</returns>
        static int? FindItemInListByRecursion(List<int> list, int itemToFind, int? result = null)
        {
            if (list[0] == itemToFind) // eğer listenin ilk elemanı aranan sayıya eşitse
            {
                result = list[0]; // listenin ilk elemanını sonuç olarak ata
            }
            else // eğer listenin ilk elemanı aranan sayıya eşit değilse
            {
                list.RemoveAt(0); // listenin ilk elemanını çıkar
                if (list.Count > 0) // eğer listede hala elemanlar varsa
                {
                    result = FindItemInListByRecursion(list, itemToFind, result); // tekrar methodu çağır ve
                                                                                  // sonucu result değişkenine ata,
                                                                                  // recursive methodun doğru bir şekilde
                                                                                  // çalışması için mutlaka sonuç
                                                                                  // için bir parametre kullanılmalı
                                                                                  // ve method sonucu bu parametreye atanmalıdır
                }
            }
            return result; // sonucu dön
        }
    }
}