Найти тему
NM.getJavaPractice();

Trucks And Containers

Оглавление
Цель: научиться работать с циклами и, в частности, с операцией целочисленного деления.
Цель: научиться работать с циклами и, в частности, с операцией целочисленного деления.

❗️ Задача:

Представьте, что вы доставляете груз в ящиках одинакового размера. У вас есть грузовики и контейнеры. В каждый грузовик помещается максимум 12 контейнеров. В каждый контейнер — не более 27 ящиков. Ящики, контейнеры и грузовики пронумерованы.

Напишите программу, которая распределит ящики по контейнерам и грузовикам в зависимости от их количества.

Программа должна также выводить необходимое для этого число грузовиков и контейнеров исходя из количества ящиков, введённого пользователем после запуска программы. Пример вывода программы для двух ящиков:

Грузовик: 1
ㅤКонтейнер: 1
ㅤㅤЯщик: 1
ㅤㅤЯщик: 2
Необходимо:
грузовиков - 1 шт.
контейнеров - 1 шт.

✒️ Приступим!

-2

Класс Cargo

📌 Создадим класс Cargo, в котором и реализуем необходимые методы.

Для хранения состояния его экземпляров (объектов) в классе укажем следующие поля (переменные класса):

Константы, исходя из условия задачи:

- public static final int BOXES_PER_CONTAINER = 27; - количество ящиков, помещающихся в контейнер

- public static final int CONTAINERS_PER_TRUCK = 12; - количество контейнеров, помещающихся в грузовик

Значения, необходимые для решения задачи:

- private int boxCount; - количество ящиков

- private int containerCount; - количество контейнеров

- private int trucksCount; - количество грузовиков

✎ Создадим конструктор для инициализации объектов класса Cargo. Исходя из условия задачи, очевидно, что мы будем задавать значение количества перевозимых ящиков и на его основании считать требуемое количество контейнеров и грузовиков:

public Cargo(int boxCount) {
ㅤthis.boxCount = boxCount;
}

📌 Для дальнейшей реализации поставленной задачи потребуется, посчитать количество контейнеров и количество грузовиков, создадим для этого отдельный метод.

Для начала необходимо определить правильную формулу для их подсчета:

Количество контейнеров, очевидно, будет равно количеству ящиков, деленному на нашу константу (количество ящиков, помещающихся в контейнер BOXES_PER_CONTAINER), однако оба этих поля типа int, соответственно необходимо не забывать о том, что в Java при целочисленном делении, в случае когда одно число не делится на другое нацело, остаток от деления в получаемом результате просто отбрасывается, соответственно нам необходимо "перехватить" этот остаток и если он есть добавить дополнительный контейнер.

Для проверки делится ли число нацело на другое можем воспользоваться арифметической операцией % - "остаток от деления"

(25 % 10 = 5, 20 % 10 = 0).

Добавим эту проверку в нашу формулу в виде тернарного оператора:

containerCount = boxCount / BOXES_PER_CONTAINER + (boxCount % BOXES_PER_CONTAINER == 0 ? 0: 1)

✎ По аналогии посчитаем количество требуемых грузовиков:

trucksCount = containerCount / CONTAINERS_PER_TRUCK + (containerCount % CONTAINERS_PER_TRUCK == 0 ? 0 : 1)

private void calculateContainersAndTrucksCount() {
ㅤcontainerCount = boxCount / BOXES_PER_CONTAINER
ㅤㅤ+ (boxCount % BOXES_PER_CONTAINER == 0 ? 0: 1);
ㅤtrucksCount = containerCount / CONTAINERS_PER_TRUCK
ㅤㅤ+ (containerCount % CONTAINERS_PER_TRUCK == 0 ? 0 : 1);
}

Так как этот метод мы сделали приватным, укажем его в конструкторе, для того что бы при создании экземпляра класса Cargo расчет производился автоматически:

public Cargo(int boxCount) {
ㅤthis.boxCount = boxCount;
ㅤcalculateContainersAndTrucksCount();
}

📌 Реализуем в этом же классе метод, который будет выводить в консоль информацию, в следующем виде:

Необходимо:

грузовиков - 1 шт.

контейнеров - 1 шт.

public void containersAndTrucksCountMessage() {
ㅤSystem.out.println("Необходимо:" + "\n"
ㅤㅤㅤ+ "грузовиков - " + trucksCount + " шт." + "\n"
ㅤㅤㅤ+ "контейнеров - " + containerCount + " шт.");
}

📌 Реализуем в этом же классе метод, который распределит наши ящики по контейнерам, а контейнеры по грузовикам, с выводом информации в консоль в следующем виде:

Грузовик: 1

Контейнер: 1

Ящик: 1

Ящик: 2

public void containerDistributionMessage() {
ㅤint boxIndex = 1;
ㅤint containerIndex = 1;
ㅤfor (int truckIndex = 1; truckIndex <= trucksCount; truckIndex++) {
ㅤㅤSystem.out.println("Грузовик: " + truckIndex);
ㅤㅤint containersInThisTruck = 1;
ㅤㅤwhile (containerIndex <= containerCount
ㅤㅤㅤ&& containersInThisTruck <= CONTAINERS_PER_TRUCK) {
ㅤㅤㅤㅤSystem.out.println("\tКонтейнер: " + containerIndex);
ㅤㅤㅤㅤint boxesInThisContainer = 1;
ㅤㅤㅤㅤwhile (boxIndex <= boxCount
ㅤㅤㅤㅤㅤ&& boxesInThisContainer <= BOXES_PER_CONTAINER) {
ㅤㅤㅤㅤㅤㅤSystem.out.println("\t\tЯщик: " + boxIndex);
ㅤㅤㅤㅤㅤㅤboxesInThisContainer++;
ㅤㅤㅤㅤㅤㅤboxIndex++;
ㅤㅤㅤㅤ}
ㅤㅤㅤㅤcontainerIndex++;
ㅤㅤㅤㅤcontainersInThisTruck++;
ㅤㅤ}
ㅤ}
}

В этом методе инициализировано много переменных, однако они все проименованы таким образом, что бы код был читаем и понятен.

↘️ Пройдем одну итерацию цикла for:

Инициализируем переменные управления циклами boxIndex, containerIndex и truckIndex (внутри цикла for)

truckIndex = 1, выводим в консоль - <"Грузовик: " + truckIndex> и инициализируем переменную int containersInThisTruck = 1, отображающую создание первого контейнера в этом грузовике

Первый вложенный цикл while для обработки распределения контейнеров, который будет работать на первой итерации цикла for до тех пор, пока containerIndex не превысит посчитанное количество containerCount или пока количество создаваемых контейнеров containersInThisTruck не превысит CONTAINERS_PER_TRUCK.

В теле этого цикла:

- выводим в консоль - <""\tКонтейнер: " + containerIndex>

- инициализируем переменную int boxesInThisContainer = 1, отображающую создание первого ящика в этом контейнере;

- запускаем второй вложенный цикл.

Второй вложенный цикл while для обработки распределения ящиков, который будет работать на первой итерации первого цикла while до тех пор, пока boxIndex не превысит посчитанное количество boxCount или пока количество создаваемых ящиков boxesInThisContainer не превысит BOXES_PER_CONTAINER.

В теле этого цикла:

- выводим в консоль <"\t\tЯщик: " + boxIndex>;

- "создаем" следующий ящик (то есть увеличиваем его количество на 1 boxesInThisContainer++);

- инкрементируем переменную управления данным циклом (boxIndex++), что бы наш второй цикл while продолжал работать, пока не нарушится одно из условий его работы.

❺ Тело первого цикла еще не закончилось, после того, как второй цикл while завершит работу, мы проводим аналогичные действия:

- "создаем" следующий контейнер для заполнения containersInThisTruck++;

- инкрементируем переменную управления первым вложенным циклом containersInThisTruck++.

✏️ P.S. в настоящем проекте реализация распределения ящиков по контейнерам, а контейнеров по грузовикам осуществлена с использованием вложенных циклов, поскольку таков был контекст поставленной задачи, но можно обойтись и одним циклом, вариант решения оставлю здесь.

int truckIndex = 1;
int containerIndex = 1;
int boxes = 0;
System.out.println("Грузовик: " + truckIndex);
System.out.println("\tКонтейнер: " + containerIndex);
while (boxes < boxCount) {
ㅤSystem.out.println("\t\tЯщик: " + ++boxes);
ㅤif ((containerIndex % CONTAINERS_PER_TRUCK == 0)
ㅤㅤㅤ&& (boxes % BOXES_PER_CONTAINER == 0)) {
ㅤㅤSystem.out.println("Грузовик: " + ++truckIndex);
ㅤ}
ㅤif (boxes % BOXES_PER_CONTAINER == 0) {
ㅤSystem.out.println("\tКонтейнер: " + ++containerIndex);
ㅤ}
}

Можно считать задачу выполненной, проверим вывод в консоль в классе Main.

Класс Main

📌 Реализуем ввод количества контейнеров через консоль

System.out.println("Введите количество коробок: ");

int boxes = new Scanner(System.in).nextInt();

public class Main {
ㅤpublic static void main(String[] args) {
ㅤㅤSystem.out.println("Введите количество коробок: ");
ㅤㅤint boxes = new Scanner(System.in).nextInt();
ㅤㅤCargo cargo = new Cargo(boxes);
ㅤㅤcargo.containersAndTrucksCountMessage();
ㅤㅤcargo.containerDistributionMessage();
ㅤ}
}

▶️ Run 'Main.main()'

-3
-4