Вивчай
Домашнє завдання #10 · Цикли, вкладені цикли, функції та робота з рядками
100 балів+15 бонусbeginner

Домашнє завдання #10: ASCII-майстерня і таємні послання

Цикли зазвичай тренують на таблиці множення. Нудно. Ми зробимо інакше: спершу цикли малюватимуть — прямо в консолі браузера. А потім ти напишеш шифр, яким Юлій Цезар кодував військові накази дві тисячі років тому, — і зламаєш його методом повного перебору, як справжній криптоаналітик.


Частина 1: ASCII-майстерня

Три функції, кожна малює фігуру в консолі (кожен рядок — окремий console.log). Символи: (заповнено) і (порожньо).

pyramid(n) — піраміда з n рівнів

pyramid(4);
//    █
//   ███
//  █████
// ███████

Рівень i містить 2*i - 1 блоків, а перед ними — пробіли, щоб піраміда була по центру.

christmasTree(n) — ялинка: крона з n рівнів + стовбур

christmasTree(3);
//   █
//  ███
// █████
//   █

Стовбур — один блок по центру. Не дублюй код крони — у тебе вже є pyramid.

chessboard(size) — шахівниця size × size

chessboard(4);
// █░█░
// ░█░█
// █░█░
// ░█░█

Лівий верхній кут — завжди . Тут знадобиться цикл у циклі: зовнішній — по рядках, внутрішній — по клітинках. Клітинка чи — залежить від суми номера рядка і номера стовпця (парна чи непарна).


Частина 2: Шифр Цезаря

Ідея шифру: кожна літера зсувається по абетці на shift позицій. Зсув 3: a → d, b → e, а з кінця абетки — по колу: x → a, y → b, z → c.

encrypt(text, shift) та decrypt(text, shift)

Працюють з латиницею. Правила:

  • Великі літери залишаються великими, малі — малими
  • Все, що не літера (пробіли, коми, цифри), — не змінюється
  • Кінець абетки загортається на початок (z + 1 → a)
  • decrypt повертає текст у вихідний вигляд: decrypt(encrypt(text, s), s) === text

Тест-кейси:

ВикликРезультат
encrypt("Hello, World!", 3)"Khoor, Zruog!"
encrypt("xyz", 3)"abc"
encrypt("Java Script 101", 13)"Wnin Fpevcg 101"
decrypt("Khoor, Zruog!", 3)"Hello, World!"
decrypt("Wnin Fpevcg 101", 13)"Java Script 101"

bruteForce(encrypted) — злам перебором

Ти перехопив шифровку, але не знаєш зсув. Не біда: зсувів усього 25 — перебери всі (ще один цикл у циклі: зовнішній — по зсувах, всередині — розшифровка). Виведи кожен варіант у консоль у форматі Зсув N: текст:

bruteForce("Fdhvdu");
// Зсув 1: Ecguct
// Зсув 2: Dbftbs
// Зсув 3: Caesar   ← око одразу чіпляється за осмислене слово
// ...
// Зсув 25: Geiwev

Всередині bruteForce використай готовий decrypt — не дублюй логіку.


Бонус (+15): Українська абетка

Розшир encrypt/decrypt, щоб вони шифрували й українські літери (латиниця при цьому має продовжувати працювати). В українській абетці 33 літери: абвгґдеєжзиіїйклмнопрстуфхцчшщьюя — тож я із зсувом 1 загортається в а.

ВикликРезультат
encrypt("Привіт", 1)"Рсігїу"
encrypt("яблуко", 2)"бгнхмр"
decrypt("Рсігїу", 1)"Привіт"

Підказка: для української не вийде рахувати через коди символів так само просто, як для латиниці, — простіше тримати абетку рядком і працювати з indexOf.


Підказки

Рівень 1: напрямок думки
  • Кожна фігура — це цикл, який будує рядок-змінну символ за символом, а в кінці ітерації віддає її в console.log
  • Рядок із повторених символів: пробіли + блоки — порахуй, скільки кого треба на рівні i
  • Для шифру: літера → її номер в абетці → номер + зсув (по колу) → нова літера
Рівень 2: які інструменти використати
  • "█".repeat(5) — рядок із 5 блоків; " ".repeat(n - i) — відступ
  • Залишок від ділення % — і для «парна/непарна клітинка» у шахівниці, і для загортання абетки по колу: (index + shift) % 26
  • Код літери: text.charCodeAt(i), назад у літеру: String.fromCharCode(code). Коди: a-z — 97–122, A-Z — 65–90
  • Перевірка «чи це літера»: код у діапазоні 97–122 (мала) або 65–90 (велика)
  • decrypt не обов'язково писати з нуля: розшифровка зсувом s — це шифрування зсувом 26 - s
Рівень 3: псевдокод encrypt
функція encrypt(text, shift):
  result = порожній рядок
  для кожного символа ch у text:
    code = код символа ch
    якщо code у діапазоні малих літер:
      result += літера з кодом 97 + (code - 97 + shift) % 26
    інакше якщо code у діапазоні великих літер:
      result += літера з кодом 65 + (code - 65 + shift) % 26
    інакше:
      result += ch  // пробіли, цифри, розділові знаки — як є
  повернути result

Як здати

  1. Робота — в публічному GitHub-репозиторії курсу my-web-course, у папці hw-10/
  2. У папці: script.js з усіма функціями і демо-викликами (фігури + всі тест-кейси шифру + bruteForce("Fdhvdu")) та index.html-обгортка:
<!DOCTYPE html>
<html lang="uk">
<head><meta charset="UTF-8"><title>HW-10</title></head>
<body>
  <script src="script.js"></script>
</body>
</html>
  1. Відкрий index.html → консоль (F12): там мають красуватися піраміда, ялинка, шахівниця і зламана шифровка
  2. У папці — README.md: 2-3 речення що зроблено + як запустити
  3. Мінімум 3 коміти з осмисленими повідомленнями (не «fix» та «update»)
  4. Надішли посилання на репозиторій у форму на цій сторінці

Критерії оцінки

КритерійТипБали
pyramid(n) — центрована піраміда, збігається з прикладом[код]15
christmasTree(n) — крона + стовбур, повторно використовує pyramid[код]15
chessboard(size) — вкладені цикли, правильне чергування /[код]15
encrypt/decrypt — регістр зберігається, не-літери не змінюються, абетка загортається; усі тест-кейси проходять[код]25
bruteForce — 25 варіантів у форматі Зсув N: текст, використовує decrypt[код]15
Демо-виклики всіх функцій у script.js — консоль показує результати[код]10
Контракт здачі: 3+ осмислені коміти, README[код]5
Бонус: підтримка української абетки (33 літери, латиниця не зламалась)[код]+15

Що далі

Збережи encrypt/decrypt — коли в Block 5 дійдемо до форм та подій, ці функції легко перетворяться на сторінку-шифрувальник: поле вводу, кнопка і таємні послання для друзів.