---
tags: 1_basic
---
# DEMO. Ефекти 1. Хаос
Note:
План:
- перший код, вічний цикл, прінти
- завдання на вивід ASCII-арту
- філософська ідея, що програміст може легко створити хаос, і що потрібно вміти контролювати цей хаос
- психологія мозку, прокрастинація та вигорання, і як цьому протидіяти
---
## Зав'язка
Світ повний Хаосу. Будь-який програміст про це знає, але все навіть гірше. Будь-який програміст може додати ще більше Хаосу в наш Світ.
І перше, що потрібно навчитись, це контролювати Хаос, який привноситься у Світ.
А уже після того можна котролювати Світ.
---
*`demo_chaos.py`*
```python=
import random
a = 0
b = 0
while True:
try:
a = random.randrange(0, 100)
b = random.randrange(0, 5)
print(" "*a + "погані думки"*b)
except:
pass
```
---
## Фікс 1
```diff=
import random
a = 0
b = 0
while True:
try:
a = random.randrange(0, 100)
b = random.randrange(0, 5)
print(" "*a, "погані думки"*b)
except:
- pass
+ break
```
---
## Фікс 2
```diff=
import random
a = 0
b = 0
-while True:
- try:
+try:
+ while True:
a = random.randrange(0, 100)
b = random.randrange(0, 5)
print(" "*a + "погані думки"*b)
- except:
- pass
+except:
+ pass
```
---
## Фікс 3
```diff=
import random
+import time
a = 0
b = 0
while True:
+ time.sleep(0.01)
try:
a = random.randrange(0, 100)
b = random.randrange(0, 5)
print(" "*a + "погані думки"*b)
except:
pass
```
---
Живий кодинг, експерименти, демо
Note:
Копія коду для тих, хто не був присутній на лекції і не дивився відео.
---
### DEMO.Effects1.A0.0 (обов'язкове завдання)
Python скрипт виконується рядок за рядком, рядок за рядком. Деякі рядки важливі, деякі -- ігноруються, деякі -- непотрібні.
Вибери один з виправлених варіантів програми *`demo_chaos.py`*.
0. Вкажи який варіант вибрав
1. Які рядки можна видалити з програми, і програма буде продовжувати працювати як задумувалось?
2. Які рядки можна видалити з програми, програма буде працювати, але не так як задумувалось?
3. Які рядки НЕ можна видаляти з програми, бо вона тоді програма не запуститься і видасть помилку?
Програма маленька, тому перебери всі варіанти.
----
### DEMO.Effects1.A0.1 (обов'язкове завдання)
(написання коду)
Контроль Хаосу. В рядках 7 та 8 оригінального *`demo_chaos.py`* вказані числа. Спробуй змінити ці числа на якісь інші.
0. Ці числа можна змінити так, щоб Хаос був вузьким

1. Ці числа можна змінити так, щоб Хаос з'їхав вліво

2. Ці числа можна змінити так, щоб Хаос зник!

Віднайди ці числа!
3. А ще, можна ж змінити затримку в рядку `time.sleep(0.01)`! При якій найменшій затримці все ще можна вийти з програми по <kbd>Ctrl</kbd>+<kbd>C</kbd>?
----
### DEMO.Effects1.A0.2 (обов'язкове завдання)
Запустити програму на своєму комп'ютері. Прочитай код і знайди, що спільного з демонстрацією Хаосу.
P.S. Якщо раптом ти дівчина і тебе звати Наталка -- знайди і зміни ім'я в коді :smiley_cat:
```python=
import random
import time
# сорі за суржик
phrases = [
"{}, вставай!",
"все пропало, {}!",
"ми все уронілі, {}!",
"{}, ти спіш?",
]
cat1 = r"""
|\---/|
| o_o |
\_^_/
"""
cat2 = r"""
/\_/\
( o.o )
> ^ <
"""
cat3 = r"""
|\__/,| (`\
_.|o o |_ ) )
-(((---(((--------
"""
def prepare_cat(cat):
"""
Перетворити картинку котика в список рядків. І зробити картинку прямокутною,
додавши в кінці кожного рядку прогаликів
In[]: cat = r'''
|\__/|
| OO |._
-(((---(((-
'''
In[]: prepare_cat(cat)
Out[]: [
'|\__/| ',
'| OO |._ ',
'-(((---(((-'
]
"""
lines = cat.split("\n")
max_length = max([ len(line) for line in lines ])
return [ x.ljust(max_length) for x in lines[1:-1]]
def symbol_reverse(sym):
"""
Віддзеркалити символ. Це потрібно для відзеркалення картинки котика.
Наприклад, якщо котик виглядає як
cat = r'|\_/| '
то при розвертанні рядка нахилені символи / та \ поміняються місцями:
r'|\_/| '[::-1] == r' |/_\|'
От для цих несиметричних символів і потрібна ця функція.
"""
if sym == '(':
return ')'
elif sym == ')':
return '('
elif sym == '/':
return '\\'
elif sym == '\\':
return '/'
elif sym == '>':
return '<'
elif sym == '<':
return '>'
else:
return sym
def ascii_mirror(cat_lines, offset=0):
"""
Віддзеркалити всього котика. Параметр offset автоматично посуне котика
вліво.
"""
result = []
for line in cat_lines:
line_reverse = line[::-1]
line_correct = ''.join([ symbol_reverse(x) for x in line_reverse ])
result.append(line_correct.rjust(offset))
return result
# нормальні котики
all_cats = [ prepare_cat(cat) for cat in [cat1, cat2] ]
# дзеркальні котики
all_cats += [ ascii_mirror(prepare_cat(cat)) for cat in [cat3] ]
try:
while True:
time.sleep(0.7)
cat = random.choice(all_cats)
phrase = random.choice(phrases)
name = "Наташ"
if random.random() < 0.5: # картинка справа
print("\n".join(cat))
print(phrase.format(name))
else: # картинка зліва
cat = ascii_mirror(cat, offset=60)
print("\n".join(cat))
print(phrase.format(name).rjust(60))
except KeyboardInterrupt:
pass
```
---
### Додаткові завдання
---
#### DEMO.Effects1.A1.0
Хаос можна зробити і без `random`. Наприклад,
```python3=
import itertools
print(list(itertools.repeat("Ми прийшли з миром")))
```
> :warning: Перед запуском цієї програми переконайся, що на комп'ютері не запущено нічого важливого і все збережено. Бо **комп ЗАВИСНЕ**!!
А питання ось у чому -- чому комп зависає після запуску програми? Як від цього захиститись?
<details>
<summary>Підказка</summary>
P.S. Подивись, що відбувається в диспетчері задач!
</details>details>
#### DEMO.Effects1.A1.1
Якщо використати `print()` кілька разів, то можна "намалювати" ASCII-арт.
```python3
print(r"(.\\//.)")
print(r" \ () / ")
print(r" (_/\_) ")
```
Завдання -- вивести ASCII-арт замість тексту в демо Хаос. Арт вибираєш який завгодно, хочеш -- свій, хочеш -- шукай тут https://www.asciiart.eu/ .
P.S. Замість `time.sleep()` можна написати `input()`. Тоді програма буде після кожної ітерації зупинятись і чекати коли ти натиснеш <kbd>Enter</kbd>.

#### DEMO.Effects1.A1.2
Бекграунд термінала як правило чорний, а текст -- світлий. А що як спробувати намалювати щось фоновим кольором, наприклад, печеру? Якщо стіни печери зробити білими символами, то печера якраз і вийде чорною.

<details>
<summary>Підказка</summary>
Якщо в одному рядку вивести на екран <span style="font-family: monospace; border: 1px solid black;">a</span> символів, потім 20 прогаликів, а потім <span style="font-family: monospace; border: 1px solid black;">80 - a - 20</span> символів, то всього буде виведено <span style="font-family: monospace; border: 1px solid black;">a + 20 + (80 - a - 20) == 80</span> символів. Незалежно від того, яке <span style="font-family: monospace; border: 1px solid black;">a</span>.
</details>details>
#### DEMO.Effects1.A1.3
Досі ми виводили на екран рядок за рядком, бо так працює простий `print()`. Але це не обов'язково, можна виводити все в один рядок. Для цього знадобиться таке знання:
- `print(..., end='', flush=True)` -- не буде переводити курсор на новий рядок після виводу на екран
- `print('\b', end='', flush=True)` -- перевід курсору на один символ назад. Наприклад, `print('Hello, \b\b\bboy')` виведе на екран `Hellboy`.
- `print('\r', end='', flush=True)` -- перевід курсору на початок рядка. Наприклад,
```python
print('\r' + ' '*80, end='', flush=True)
```
переведе курсор на початок і виведе 80 прогаликів, фактично, очистисть рядок
Завдання: зробити Хаос у вигляді одного рядка!

#### DEMO.Effects1.A1.4
В демо Хаос заміни `a = random.randrange()` на `a = (a + 1) % 70`. Стало трошки менше хаосу?
Тепер використай це знання щоб візуалізувати прогрес-бар.

---
### Додаткові завдання (складні!)
#### DEMO.Effects1.A2.0
#### DEMO.Effects1.A2.1
#### DEMO.Effects1.A2.2
---
### Real-world завдання, для експертів
#### DEMO.Effects1.A3.0