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

Змішані соки

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

Вступ

Загалом є два типи циклів:

  1. Повторювати, доки не виконається умова.
  2. Перебирати елементи колекції.

Обидва можливі в R, хоча перший трапляється частіше.

while і repeat

Для задач без наперед відомої кількості повторів R має цикл while з умовою та цикл repeat без умови (еквівалентний while (TRUE)).

Базова форма досить проста:

while (condition) {
  do_something()
}

У цьому разі програма повторюватиме цикл, доки condition не перестане бути TRUE.

Є два способи достроково вийти з циклу:

  • break перериває цикл, і виконання продовжується з наступного рядка після закривної фігурної дужки } циклу.
  • return(x) зупиняє виконання поточної функції та повертає значення x тому, хто її викликав.

Маючи ці можливості, іноді зручно створити «нескінченний» цикл за допомогою repeat { ... }, а потім покладатися на те, що всередині тіла циклу знайдеться умова зупинки, яка викличе break або return.

Ці три варіанти еквівалентні, і всі вони завершуються з x == 0.4444...

x <- 12
while (x > 1) {
  x <- x / 3
}

x <- 12
while (TRUE) {
  x <- x/3
  if (x <= 1) break
}

x <- 12
# no boolean clause 
repeat { 
  x <- x/3
  if (x <= 1) break
}

Перебирання вектора

У R це часто не потрібно. Як зазначалося в інших концепціях, багато функцій працюють з цілими векторами.

Однак явних циклів іноді не уникнути. Особливо це стосується випадків, коли:

  • Тіло циклу має побічні ефекти, як-от виведення на екран чи робота з файлами.
  • Цикл триває, доки не буде досягнуто певного критерію, після непередбачуваної кількості ітерацій.

Умова циклу має бути в дужках. Як і з тілами функцій, для однорядкових тіл циклу фігурні дужки необовʼязкові (але їх часто додають).

words <- c("This", "is", "a", "loop")
for (w in words) { print(w) } # the braces are optional here
#> [1] "This"
#> [1] "is"
#> [1] "a"
#> [1] "loop"

Якщо поточна ітерація не задовольняє певну умову, можна одразу перейти до наступної ітерації за допомогою next:

for (n in 1:10) {
    if (is_useless(n)) next
     
    # we decided this iteration could be useful
    do_something_slow(n)
}

Якщо потрібен числовий індекс, скористаймося seq_along().

v <- LETTERS[1:3]
v
#> [1] "A" "B" "C"

for (i in seq_along(v)) { print(sprintf("%s%i", v[i], i)) }
#> [1] "A1"
#> [1] "B2"
#> [1] "C3"

Використовувати i in 1:length(v) не рекомендовано, бо це може спричинити проблеми, коли length(v) дорівнює нулю. Діапазон 1:0 еквівалентний c(1, 0), тож тіло циклу виконається і, ймовірно, зазнає невдачі. Функція seq_along() створена, щоб правильно обробити цей випадок.

Вказівки

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

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

Лі Мей любить заздалегідь казати своїм клієнтам, скільки їм доведеться чекати на замовлений напій з меню. Їй важко запамʼятати точні цифри, бо час приготування напоїв різниться. "Pure Strawberry Joy" займає 0.5 хвилини, "Energizer" і "Green Garden" — по 1.5 хвилини, "Tropical Island" — 3 хвилини, а "All or Nothing" — 5 хвилин. Для всіх інших напоїв (наприклад, спеціальних пропозицій) можемо припустити час приготування 2.5 хвилини.

Щоб допомогти подрузі, напишіть функцію time_to_mix_juice, яка приймає напій з меню як аргумент і повертає кількість хвилин, потрібних для приготування цього напою.

time_to_mix_juice("Tropical Island")
# => 3

time_to_mix_juice("Berries & Lime")
# => 2.5

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

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

Реалізуйте функцію limes_to_cut, яка приймає кількість часточок лайма, які Лі Мей має нарізати, і масив, що представляє запас цілих лаймів, наявних у неї під рукою. З лайма "small" виходить 6 часточок, з лайма "medium" — 8, а з лайма "large" — 10. Вона завжди нарізає лайми в тому порядку, у якому вони розташовані в масиві, починаючи з першого елемента. Вона продовжує, доки не наріже потрібну кількість часточок або доки не закінчаться лайми.

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

limes_to_cut(25, c("small", "small", "large", "medium", "small"))
# => 4

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

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

Реалізуйте функцію order_times, яка приймає чергу замовлень і друкує в stdout час, потрібний для приготування кожного з них.

order_times(c("Energizer", "Tropical Island"))
# => 1.5 
# => 3
Note

Це завдання досить незвичне для Exercism, бо вимагає друку в stdout. Переважна більшість завдань у вправах на Exercism вимагає поверненого значення та/або якогось іншого побічного ефекту.

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

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

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

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

remaining_orders(5, c("Energizer", "All or Nothing", "Green Garden"))
# => c("Green Garden")
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
R Exercism

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

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