Призываем программистов
Обещаем, что это последний материал про «Игру престолов». Зато это задача, которая решается с помощью программирования!
Фермер решил завести 20 драконов, чтобы продавать яйца по 50 серебряных за штуку. Рептилии (драконы же рептилии?) несут по два яйца в неделю, и каждую неделю все яйца продаются. С этих денег фермер покупает ещё по два дракона в неделю по 300 серебряных, чтобы увеличить свой доход. Но расходы велики: чтобы кормить и содержать питомцев, хозяин каждый день тратит 500 серебряных.
Фермер решил: если прибыли от рептилий так и не будет, через год он продаст их всех одной любительнице драконов, а если будет — продолжит дело. Как вы думаете, продаст он их или нет?
Решение
Как будем решать
Можно было бы составить сложную формулу, которая выводит зависимость прибыли от дня года, и начертить график. Там, где график пересёк бы ноль и пошёл вверх, мы бы увидели прибыль. Но формулы — это для математиков, а мы программисты. Мы напишем программу, которая симулирует экономику нашего фермера, перебирая день за днём. Сегодня потратил столько-то, завтра продал яйца и заработал столько-то, послезавтра потратил ещё столько-то… — и будем проверять, когда появится прибыль.
Тот же принцип используют учёные, когда делают симуляции — например, чёрных дыр или Большого взрыва: они задают исходные физические параметры своим объектам и дают компьютеру задание рассчитать каждую секунду их взаимодействия. Вот у нас как про чёрные дыры, только про драконов.
Задачу будем решать на JavaScript, потому что он у вас уже работает в браузере и вы можете спокойно повторить решение прямо сейчас, используя консоль (в меню «Вид» → «Разработчикам» → «Консоль»).
Шаг 1. Знакомство с функцией
Основную математику мы пропишем в функции: она будет заниматься симуляцией экономики фермера. Функция — это мини-программа внутри нашей программы: сначала мы пишем, что она будет делать, а потом вызываем её внутри программы и всё необходимое исполняется. В данном случае нам нужна программа внутри программы, чтобы иметь возможность выйти из неё, когда закончится год.
Чтобы задать функцию, которую мы назовём runDragonSimulator, используем такой код:
function runDragonSimulator() { }
Вначале идёт команда function, которая говорит компьютеру: мы хотим сделать новую функцию, которая будет называться runDragonSimulator. В круглых скобках пишутся параметры функции, оказывающие влияние на её работу. В нашем случае таких параметров нет, функция всегда будет действовать одинаково, поэтому в этих скобках сейчас ничего не указываем. А внутри фигурных скобок {} мы напишем тело функции — код, который выполнится, когда мы вызовем эту функцию.
Почему функция называется именно так — прочитайте в нашей статье о названии функций.
Когда компьютер встретит наименование функции, он поймёт, что нужно выполнить тот кусок кода, который стоит между фигурными скобками. Он его выполнит, а потом снова вернётся к программе — с того же места, где он прервался на функцию.
Например, заведём пару функций, которые будут выводить в консоль определённые слова:
function question() {
console.log('Валар моргулис');
// И можно выполнить какие угодно ещё команды, в любом количестве
}
function answer() {
console.log('Валар дохаэрис');
// Тут тоже можно выполнить любые дополнительные команды
}
Теперь если мы просто напишем названия этих функций, то компьютер выполнит те команды, которые мы описали в нашей функции:
question();
> 'Валар моргулис'
answer();
> 'Валар дохаэрис'
У функции есть свойство: её можно прервать в любой момент командой return. Когда компьютер в функции доходит до выполнения команды return, он прекращает осуществлять задачу ровно в этом месте и возвращается в главную программу.
Нам это поможет вот для чего. Так как мы не можем сказать точно, в какой момент доходы фермера от драконов превысят расходы, мы будем постоянно проверять, произошло это или нет. Если не произошло — работаем дальше, а если вышли в плюс по доходам — прерываем выполнение командой return и выводим данные о доходах.
Если схематично построить логику нашего решения, оно будет выглядеть так:
- Считаем дни, сколько прошло всего и с начала месяца.
- Ежедневно тратим деньги на корм и содержание драконов.
- Каждую неделю продаём все яйца.
- На полученные деньги каждую неделю покупаем ещё двух драконов.
- Если после этого доходы всё ещё меньше расходов — возвращаемся в первый пункт, в противном случае прерываем подсчёты и подводим итоги: пишем, сколько мы заработали и сколько времени на это ушло.
Шаг 2. Установка переменных
Переменные — это ячейки памяти компьютера, где будут храниться нужные нам данные. Нам понадобятся переменные для дохода и расходов, для общего количества дней и для подсчёта каждого седьмого дня, который приносит нам доход.
Переменные в языке JavaScript задаются словами var или let. У них есть разница в видимости, сейчас она нас не волнует, но в будущем о них поговорим. Для этого примера используем var:
Теперь задаём количество драконов в самом начале и стартовые значения дохода и расхода:
Весь основной код мы поместим в нашу функцию:
Шаг 3. Цикл
Основное, что нам нужно будет делать всё время, — выполнять код до тех пор, пока не сработает наше условие, что доход больше расхода. Для этого используем новый цикл — while:
while ( условие ) { команды }
Смысл такой: пока условие верное, команды выполняются раз за разом. После каждой отработки всех команд цикл возвращается в начало и снова проверяет — выполняется ли до сих пор условие. Если да, снова делаем все команды, если нет — цикл на этом прекращается.
Мы поставим такое условие: пусть всё работает, пока доходы меньше расходов, а мы посмотрим, что настанет раньше — пройдёт один год или мы выйдем в плюс:
Шаг 4. Подсчёты
Началась ежедневная рутина: подсчёт дней, понедельный и общий, и постоянные траты на корм и уход за драконами.
Чтобы увеличить количество прошедших дней на единицу, можно использовать привычную команду day = day + 1. Она берёт старое значение day, прибавляет к нему единицу и результат помещает снова в day. А можно сделать изящнее:
day += 1;
Команда += 1 увеличивает значение нашей переменной на единицу. Если бы мы написали day +=3, то это бы увеличило значение day на 3.
Что у нас происходит каждый день: меняется текущий день недели, возрастает общее количество прошедших дней, тратим 500 серебряных на содержание драконов:
day += 1;
dayZ += 1;
expense += 500;
Теперь надо проверить, вдруг сегодня уже седьмой день, — и тогда мы соберём по два яйца с каждого дракона, продадим их и купим ещё рептилий:
Мы увеличиваем размер нашего дохода на ту сумму, которую нам принесёт продажа яиц, а затем обнуляем количество прошедших дней с начала недели: седьмой день закончился, начинаем отсчёт сначала.
Шаг 5. Проверки
Теперь надо проверить, вдруг прошёл уже один год и общая сумма наших доходов до сих пор не превысила все наши расходы? Если так, то сообщаем об итогах эксперимента и останавливаем выполнение функции:
Но что будет, если наш цикл однажды закончится сам? Речь про условие while (margin < expense).
Если однажды это условие не выполнится, это значит, что доходы перестали быть меньше расходов, то есть мы вышли в плюс. Тогда нужно вывести количество дней, сколько у нас ушло на это, а также прибыль, которую мы получили:
console.log('За ' + dayZ + ' дней вы вышли в плюс. Всего вы потратили ' + expense + ' и заработали ' + margin + ' c. Первая прибыль: ' + (margin — expense));
Собираем всё
Все части программы у нас уже есть. Собираем готовый код:
Обратите внимание: сначала мы создали функцию, описали все её ветки и логику. Но когда мы её описываем, она ещё не работает. Мы как бы задали правила игры, но саму игру не запустили. И только на последней строке кода мы говорим runDragonSimulator(); — и вот тогда программа действительно активируется и выполняет всё, как мы её просили.
Такую программу можно доработать под себя и использовать уже для оценки реальных проектов — насколько они рентабельны и какие нужны условия для того, чтобы они стали прибыльными.
Подписывайтесь на наш канал, чтобы ваши драконы вас слушались!