Треки
/
Factor
Factor
/
Вправи
/
Змішані соки
Змішані соки

Змішані соки

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

Вступ

Деякі цикли не можна записати як «зроби це для кожного елемента послідовності»: доводиться повторювати, доки не зміниться певна умова. Саме для цього й потрібен комбінатор while у Factor: quotation-предикат каже «продовжувати?», quotation-тіло виконує роботу одного кроку, а while повторює, доки предикат не дасть f.

while й until

while ( pred body -- )
until ( pred body -- )

pred і body — це quotation; обидва працюють зі стеком даних. while продовжує цикл, доки pred залишає істинне значення; until робить навпаки: повторює, доки pred не стане істинним (тобто доки pred залишає f).

Одне значення стану може передаватися на стеку між предикатом і тілом:

USING: kernel math ;

5 [ dup 0 > ] [ dup . 1 - ] while drop
! prints 5 4 3 2 1

Розглянемо покроково: предикат dup 0 > зазирає до поточного лічильника; тіло dup . 1 - друкує його й зменшує на одиницю; цикл зупиняється, коли лічильник досягає 0. drop у кінці відкидає той фінальний 0 зі стека.

while*: зберегти значення предиката

while* ( pred body -- )

while зважає лише на те, чи залишив його предикат істинне значення, а саме значення відкидає перед виконанням тіла. while* натомість передає це значення тілу. Він стає в пригоді щоразу, коли перевірка й тіло потребують того самого щойно обчисленого результату: результату пошуку, збігу, розібраного токена.

Тут кожне імʼя вказує на наступне в ланцюжку. Предикат шукає поточне імʼя; доки є наступне імʼя, while* передає його тілу, яке друкує його й рухається далі:

USING: assocs kernel locals prettyprint ;

:: print-chain ( start links -- )
    start [ links at ] [ dup . ] while* ;

"a" H{ { "a" "b" } { "b" "c" } } print-chain
! prints "b" then "c"

links at повертає наступне імʼя або f, коли для імені немає запису. Доки він повертає імʼя, while* віддає це імʼя dup ., який друкує його й залишає як ключ для наступного пошуку. Перший f зупиняє цикл: while* відкидає його, тож зайвого на стеку не лишається.

Кілька значень стану з локальними змінними

Коли цикл несе більше ніж одне значення (скажімо, список залишку й поточну суму), перекидання значень на стеку стає надто заплутаним. Найчистіший підхід - оголосити локальні змінні через :::

:: word ( inputs -- outputs ) ... ;

Усередині тіла :> name! додає локальну змінну, яку можна змінювати; для читання використовують name, а для запису name! (який забирає нове значення зі стека й присвоює його).

USING: kernel locals math sequences ;

! Walk a sequence from the front, summing as we go
:: sum-by-hand ( seq -- total )
    seq :> rest!
    0   :> running!
    [ rest empty? ] [
        rest unclip [ rest! ] dip
        running + running!
    ] until
    running ;

Дві локальні змінні тут (rest і running) охоплюють увесь стан циклу: предикат їх переглядає, тіло їх оновлює, а наприкінці повертається підсумкове значення.

unclip ( seq -- rest first ) знімає перший елемент послідовності, що стає в пригоді, коли цикл має брати зі списку по одному елементу за ітерацію. Форма [ rest! ] dip оновлює rest до залишкового хвоста й водночас залишає щойно знятий елемент на стеку, щоб ним скористалося тіло.

Вказівки

Наша подруга Лі Мей тримає бар соків, де продає смачні змішані фруктові соки. Ми часто купуємо в неї й зрозуміли, що могли б трохи полегшити їй життя за допомогою коду на Factor.

1. Визначте, скільки часу потрібно на змішування соку

Лі Мей любить заздалегідь казати відвідувачам, скільки їм доведеться чекати на сік із меню. Їй важко пригадати точні числа, бо час на змішування соків різниться:

  • "Pure Strawberry Joy" займає 0.5 хвилини.
  • "Energizer" і "Green Garden" займають по 1.5 хвилини кожен.
  • "Tropical Island" займає 3 хвилини.
  • "All or Nothing" займає 5 хвилин.
  • Усі інші напої (наприклад, спеціальні пропозиції) займають 2.5 хвилини.

Визначте time-to-mix-juice, яка приймає назву соку зі стека й повертає кількість хвилин, потрібних на змішування цього напою.

"Tropical Island" time-to-mix-juice .
! => 3

"Berries & Lime" time-to-mix-juice .
! => 2.5

2. Поповніть запас часточок лайма

Багато напоїв Лі Мей містять часточки лайма, або як складник, або як частину оздоблення. Тож коли вона починає ранкову зміну, їй треба подбати, щоб контейнер із часточками лайма був повним на весь день.

Визначте wedges-from-lime, яка приймає розмір лайма й повертає кількість часточок, які з нього виходять: 6 з лайма розміру "small", 8 з лайма розміру "medium", 10 з лайма розміру "large".

Потім визначте limes-to-cut, яка приймає кількість часточок needed і масив limes (розміри лаймів у порядку нарізання). Вона нарізає лайми один за одним, по порядку, і зупиняється, щойно в неї буде достатньо часточок або скінчаться лайми. Поверніть кількість лаймів, які їй довелося нарізати.

25 { "small" "small" "large" "medium" "small" } limes-to-cut .
! => 4

3. Складіть список часу змішування кожного замовлення в черзі

Лі Мей любить відстежувати, скільки часу займе змішування замовлень, на які чекають відвідувачі.

Визначте order-times, яка приймає масив замовлень і повертає масив із часом змішування кожного замовлення, у тому ж порядку.

{ "Energizer" "Tropical Island" } order-times .
! => { 1.5 3 }

4. Завершіть зміну

Лі Мей завжди працює до 15:00. Потім її працівник Дмитро переймає справу. Часто, коли зміна Лі Мей закінчується, залишаються напої, які вже замовили, але ще не приготували; тоді Дмитро готує решту соків.

Щоб полегшити передачу справ, визначте remaining-orders, яка приймає кількість хвилин time-left у зміні Лі Мей і масив orders (соки, які вже замовили, але ще не приготували).

Поверніть замовлення, які доведеться перейняти Дмитрові, тобто ті, які Лі Мей не встигає почати до кінця своєї зміни.

time-left завжди більше за 0. Замовлення готують у тому порядку, у якому вони розташовані в масиві. Щойно Лі Мей починає готувати сік, вона завжди доводить його до кінця, навіть якщо їй доведеться попрацювати трохи довше. Якщо вона встигає почати кожне замовлення, поверніть порожній масив.

5 { "Energizer" "All or Nothing" "Green Garden" } remaining-orders .
! => { "Green Garden" }
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Factor Exercism

Час розпочати Змішані соки?

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