> For the complete documentation index, see [llms.txt](https://bytistan.gitbook.io/baytistan/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bytistan.gitbook.io/baytistan/kedi-problemi/seviye-7-karmasa.md).

# Seviye 7: Karmaşa

## Amaç

`settings.py` dosyasına eklediğin ASCII kediyi, bütün terminal üzerinde rastgele parçalar halinde bırakıp sonra adım adım birleştirmelisin.

### Beklenen Davranış

<figure><img src="https://1592666604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy0QTCliryu3DkL9lOYgq%2Fuploads%2Ft34irGpJvzIYE1ACnCse%2Fgiphy(1).gif?alt=media&amp;token=309018e3-73ec-462a-934e-07955e7ed756" alt=""><figcaption><p>1.0</p></figcaption></figure>

* ASCII kedinin bütün parçaları terminale rastgele dağıtılmalı.
* Parçalar adım adım birleşerek kediyi tekrar oluşturmalı.
* Kedi terminalin merkezinde olmalı.

<details>

<summary>İpucu</summary>

```python
self.columns, self.rows = shutil.get_terminal_size()
```

`shutil` kütüphanesinde bulunan bu komut terminalin genişliğini ve yüksekliğini vermektedir.

</details>

## Problemin Çözümü

Bu gerçekten uzun bir kod o yüzden kodun tamamını değil önemli noktaları anlatacağım.

<details>

<summary>Cevap</summary>

```python
from settings import *

import time 
import os
import random
import shutil

class PrintCat:
    def __init__(self):
        self.new_line = "\n"
        self.interval = 0.1 
        self.columns, self.rows = shutil.get_terminal_size()

        self.pic = [
            " " * self.columns 

            for _ in range(self.rows)
        ]

        self.padding_x = ((len(self.pic[0]) - 1) - (len(ascii_art[0]) - 1)) // 2 
        self.padding_y = ((len(self.pic) - 1) - (len(ascii_art)  - 1)) // 2 
        
        self.data = [ 
            {
                "explode_location": (random.randint(0, (self.columns - 1)) ,random.randint(0, (self.rows - 1))),
                "char": char,
                "row": row_index + self.padding_y,
                "column": column_index + self.padding_x,
                "completed": False
            }

            for row_index,row in enumerate(ascii_art)
            for column_index, char in enumerate(row)
        ] 
    
        self.completed = False
        self.count = 0 
    
    def prime_factors(self, number_one, number_two):
        c = 1 
        while True:
            c += 1

            if number_one % c == 0 and number_two % c == 0: 
                return c 
            
            if c > number_one or c > number_two:
                return 1 

    def reset(self):
        self.pic = [
            " " * self.columns 

            for _ in range(self.rows)
        ]
        
        self.completed = True
        self.count = 0
        
    def setup(self):
        self.set_start_pos()
        self.print_cat()
        time.sleep(3)

    def print_cat(self): 
        image = self.new_line.join(self.pic[:-1]) + self.pic[-1]
        print(image, end="") 
        
    def set_start_pos(self):
        for index,item in enumerate(self.data):
            ep = item.get("explode_location")
            char = item.get("char")

            x, y = ep[0], ep[1]
            
            self.pic[y] = self.pic[y][:x] + char + self.pic[y][x + 1:]
    
    def update(self):
        for index,item in enumerate(self.data):
            ep = item.get("explode_location")
            char = item.get("char")

            col = item.get("column") 
            row = item.get("row")

            completed = item.get("completed") 

            x, y = ep[0], ep[1]
            
            if completed:
                self.count += 1
                self.pic[y] = self.pic[y][:x] + char + self.pic[y][x + 1:]
                continue
            
            if self.completed:
                self.completed = False 

            if x == col and y == row:
                self.data[index]["completed"] = True
            else:
                increase_rate = self.prime_factors(abs(col - x), abs(row - y))

                x_increase = -increase_rate if col < x else increase_rate 
                y_increase = -increase_rate if row < y else increase_rate 

                x += 0 if x == col else x_increase 
                y += 0 if y == row else y_increase  

                self.data[index]["explode_location"] = (x,y)

                self.pic[y] = self.pic[y][:x] + char + self.pic[y][x + 1:]

    def run(self):
        self.setup() 

        while True:
            os.system("clear")
            self.reset()
            self.update()
            self.print_cat()
            time.sleep(self.interval) 

            if self.completed:
                break

if __name__ == "__main__":
    print_cat = PrintCat()
    print_cat.run()
```

</details>

### Çalışma Mantığı

Başlangıç konumu (4,6) olan bir nesneyi (10,6) noktasına nasıl götürebilirsiniz. Basit bir mantık ile eğer hedef konumun x değeri başlangıç konumunun x değerinden fazla ise bu değer arttırılmalı ki hedef noktaya ulaşabilsin aynısı y için de geçerli.

<figure><img src="https://1592666604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy0QTCliryu3DkL9lOYgq%2Fuploads%2FE3234YHssRnJShkvWKfZ%2FUntitled-2024-09-24-0616(2).png?alt=media&amp;token=3f2f5777-59d0-4004-8c56-865563ce71a5" alt=""><figcaption><p>1.1</p></figcaption></figure>

Aslında benim kod içerisinde yaptığım tamamen bundan ibaret. Başlangıçta rastgele bütün terminale parçaları dağıtıyorum başlangıç konulmlarını da bir data değişkeni içerisinde tutuyorum.

```python
# ...
    def __init__(self):
        # ...
        self.data = [ 
            {
                "explode_location": (random.randint(0, (self.columns - 1)) ,random.randint(0, (self.rows - 1))),
                "char": char,
                "row": row_index + self.padding_y,
                "column": column_index + self.padding_x,
                "completed": False
            }

            for row_index,row in enumerate(ascii_art)
            for column_index, char in enumerate(row)
        ] 
        # ...
# ...
```

padding\_x ve paddin\_y değerleri ASCII kedinin terminalin merkezinde olması için row ve column değerlerine ekleniyor.

Onlarıda basit bir matematik hesabı ile buluyorum

```python
# ...
    def __init__(self):
        # ...
        self.padding_x = ((len(self.pic[0]) - 1) - (len(ascii_art[0]) - 1)) // 2 
        self.padding_y = ((len(self.pic) - 1) - (len(ascii_art)  - 1)) // 2 
        # ...
# ...
```

Sonrasında column ve row değerlerini kullanarak karakterleri başlangıç pozisyonuna iteliyorum.

<pre class="language-python"><code class="lang-python"> # ...
   def update(self):
        for index,item in enumerate(self.data):
            # ...
            if x == col and y == row:
                self.data[index]["completed"] = True
            else:
<strong>                increase_rate = self.prime_factors(abs(col - x), abs(row - y))
</strong>
<strong>                x_increase = -increase_rate if col &#x3C; x else increase_rate 
</strong><strong>                y_increase = -increase_rate if row &#x3C; y else increase_rate 
</strong>
<strong>                x += 0 if x == col else x_increase 
</strong><strong>                y += 0 if y == row else y_increase  
</strong>
                self.data[index]["explode_location"] = (x,y)

                self.pic[y] = self.pic[y][:x] + char + self.pic[y][x + 1:]
            # ...
# ...
</code></pre>

Eğer x ve y değerleri eşit col ve row değerlerine eşit ise elemanın completed değerini True yapıyorum.

Değilse başlangıç noktası ve bitiş noktası arasındaki fark değerlerinin asal çarpanlarınından herhangi birini buluyorum yukarıda seçili olan satırda.&#x20;

Eleman üzerinden aldığım x ve y değerleri hedef noktandan büyük mü? Küçük mü? Ona bakara pozitif mi? Yoksa negatif? Yöndemi haraket edeceğini buluyorum.

Son olarak bunları bulunan değerler kadar arttırıp yerlerine yerleştiriyorum ve programı çalıştırıyorum.

## Genel Bakış

Bu en zoru değildi ama zorlardan bir tanesiydi, 7 seviye yapmak istedim umarım buraya kadar başarıyla gelmişsindir. Devam etmek isteyenler için örnek sorular :&#x20;

* ASCII kediyi kendi ekseni etrafında 360° derece çevir.
* ASCII kediyi 4 parçaya böl, parçalar köşelerden gelerek merkezde birleşsin.
* ASCII kediyi patlat :) cidden.

Buna benzer kendinde soru üretebilirsin artık senin hayal gücüne kalmış. Kendini geliştirmek için bu tip problemler çözmeyi unutma :)
