Треки
/
Factor
Factor
/
Вправи
/
Прапорцевий бум
Прапорцевий бум

Прапорцевий бум

Навчальна вправа

Вступ

Коли нам потрібен ряд із n значень, де кожне залежить від своєї позиції, <iota> і map у Factor діють разом, щоб виконати це завдання без лічильника циклу.

<iota> і map

<iota> (у sequences) приймає невідʼємне ціле число n і повертає віртуальну послідовність цілих чисел 0, 1, …, n-1. Потім map проходить нею, застосовуючи вашу quotation до кожного елемента:

USING: math sequences ;

5 <iota> [ 2 * ] map .   ! => { 0 2 4 6 8 }

Quotation отримує одне ціле число, а саме індекс, і залишає значення для цієї позиції на стеку.

Ітерація та повторення за кількістю

Коли нам потрібні лише побічні ефекти відвідування кожного індексу, а не нова послідовність, each-integer (у math) запускає quotation для 0, 1, …, n-1:

each-integer ( n quot: ( i -- ) -- )

replicate (у sequences) викликає quotation n разів і збирає результати, ігноруючи індекс, що зручно для побудови n незалежних значень:

replicate ( n quot: ( -- elt ) -- seq )
USING: sequences ;

3 [ { 0 0 } ] replicate .   ! => { { 0 0 } { 0 0 } { 0 0 } }

Обмежені діапазони

Коли діапазон індексів не починається з 0 або нам потрібно, щоб він був включним з обох кінців, словник ranges надає літерали в дужковій нотації. Квадратні дужки включають кінцеву точку; круглі дужки її виключають.

[a..b]    ! a, a+1, …, b      (inclusive)
[a..b)    ! a, a+1, …, b-1    (half-open at the top)
USING: math ranges sequences ;

3 7 [a..b] [ 2 * ] map .   ! => { 6 8 10 12 14 }
3 7 [a..b) [ 2 * ] map .   ! => { 6 8 10 12 }

Кілька поширених скорочень з одним аргументом:

[1..b]    ! 1, 2, …, b        (same as 1 b [a..b])
[1..b)    ! 1, 2, …, b-1      (same as 1 b [a..b))
[0..b)    ! 0, 1, …, b-1      (same as 0 b [a..b), and same as `b <iota>`)
6 [1..b] [ sq ] map .      ! => { 1 4 9 16 25 36 }
6 [1..b) [ sq ] map .      ! => { 1 4 9 16 25 }
4 [0..b) [ 1 + ] map .     ! => { 1 2 3 4 }

<iota> — найпоширеніша форма; [a..b] та подібні до них стають у пригоді, коли діапазон починається не з 0 або потребує включної верхньої межі.

Відкриті нижні межі та, можливо, порожні діапазони

Квадратні дужки включають кінцеву точку; круглі дужки її виключають. Той самий прийом ліворуч дає (a..b] та (a..b):

(a..b]    ! a+1, …, b              (lower open, upper inclusive)
(a..b)    ! a+1, …, b-1            (both open)

0 n (a..b] дає { 1 … n } для n > 0 та { } для n = 0, що є природною формою, коли ми перебираємо «кожне додатне ціле число до n включно».

Спадні діапазони

Усі чотири дужкові форми ([a..b], [a..b), (a..b], (a..b)) лічать униз, коли a > b, а не прямують до порожнього результату:

USING: ranges sequences ;

5 1 [a..b] >array .   ! => { 5 4 3 2 1 }
1 0 [a..b] >array .   ! => { 1 0 }   (not empty!)

Побудова рядка тексту за позицією

map повертає ту форму, яку повертає його quotation. Якщо quotation залишає на стеку код символу, >string (у strings) перетворює результат на рядок тексту (англ. string):

USING: math sequences strings ;

4 <iota> [ 2 * CHAR: A + ] map >string .   ! => "ACEG"

CHAR: A при розборі дає ціле число 65. Тут quotation подвоює індекс і додає цю основу, що дає кожну другу велику літеру. Будь-яка арифметика, яку ми додаємо до індексу, визначає, який символ опиниться на цій позиції.

Вибір для кожної позиції

Коли символ залежить від умови щодо індексу, робимо вибір усередині quotation:

USING: kernel math sequences strings ;

5 <iota> [ 3 < [ CHAR: a ] [ CHAR: b ] if ] map >string .
! => "aaabb"

Перші три позиції перевіряють i 3 < як t, тож отримують a; решта отримує b. Та сама форма ([ <test> [ <yes> ] [ <no> ] if ]) покриває перевірки парності за допомогою even? / odd? (у math) та перевірки «кожна k-та позиція» за допомогою mod і zero?.

Вказівки

Святковий робот нанизує гірлянду до великого свята. Кожна гірлянда - це горизонтальний ряд із n маленьких прапорців, і символ кожного прапорця визначає його позиція в ряду, яку рахують зліва, починаючи з 0. Допоможімо роботу відтворити наведені нижче закономірності.

1. Алфавітна гірлянда

Визначте alphabet-bunting так, щоб вона брала невідʼємне ціле число n зі стека й повертала рядок тексту (англ. string) з перших n малих літер алфавіту.

5 alphabet-bunting .
! => "abcde"

0 alphabet-bunting .
! => ""

Можна припустити, що n не більше ніж 26.

2. Лічильна гірлянда

Визначте counting-bunting так, щоб вона брала n і повертала рядок тексту з n цифр, де прапорець на позиції i показує i mod 10.

12 counting-bunting .
! => "012345678901"

3. Смугаста гірлянда

Визначте stripe-bunting так, щоб вона чергувала два символи: парні позиції отримують *, а непарні отримують -.

6 stripe-bunting .
! => "*-*-*-"

1 stripe-bunting .
! => "*"

4. Маркерна гірлянда

Кожен пʼятий прапорець - це особливий маркер. Визначте marker-bunting так, щоб позиції 0, 5, 10, … отримували |, а всі інші отримували ..

11 marker-bunting .
! => "|....|....|"

5. Долинна гірлянда

Робот вішає гірлянду фіксованого розміру з 10 прапорців, яка прикріплюється до гачка в центрі. Відлік іде від найлівішого прапорця на позиції -5 аж до 5 (але не включаючи його), і символ кожного прапорця - це відстань від центру, записана цифрою.

Визначте valley-bunting (без вхідних даних) так, щоб вона повертала цей фіксований рядок тексту.

valley-bunting .
! => "5432101234"
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Factor Exercism

Час розпочати Прапорцевий бум?

Зареєструйтеся на Exercism, щоб вивчати й опановувати Factor, а також 47 концепцій163 вправи та справжнє наставництво від людей, і все це безкоштовно.