Как найти лучшую серию шагов в массиве?
Самостоятельно выполняю задание яндекс практикума, и на последнем задании столкнулся с проблемой.
Суть приложения:
Имеется двумерный массив данных (int [][] array = new int[12][30];): 12 месяцев и в каждом по 30 дней.
Пользователь самостоятельно вводит количество пройденных шагов по каждому дню, изначально массив заполнен нулями.
Есть цель по шагам в день (int targetStepsPerDay = 10000;) : 10 000 шагов.
Мне нужно найти максимальное количество подряд идущих дней, в течение которых количество шагов за день было выше целевого, т.е. выше 10000 шагов.
При выполнении функции на экран должно выводиться количество идущих подряд дней в каждом из которых количество шагов было больше чем целевое значение.
Пример вывода: "В 1-м месяце количество подряд идущих дней: 3 дня."
Не представляю как это реализовать, всю голову сломал, помогите, пожалуйста, разобраться.
Код в классе main:
package com.FirstSprint;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
StepTracker stepTracker = new StepTracker(); // Создал объект на основе класса StepTracker
Converter converter = new Converter(); // Создал объект на основе класса Converter
Scanner scanner = new Scanner(System.in);
printMenu(); // Меню для печати
int userInput = scanner.nextInt();
while (userInput != 11) {
// Обработка разных случаев
if (userInput == 1) {
System.out.println("\n 1 - Январь; 2 - Февраль; 3 - Март; 4 - Апрель; 5 - Май; 6 - Июнь; 7 - Июль; 8 - Август; 9 - Сентябрь; 10 - Октябрь; 11 - Ноябрь; 12 - Декабрь. \n");
System.out.print("Введите номер месяца: ");
int month = scanner.nextInt();
System.out.print("Введите номер дня от 1 до 30: ");
int day = scanner.nextInt();
System.out.print("Введите количество пройденных шагов за " + day + " день месяца: " );
int steps = scanner.nextInt();
stepTracker.isDailyStepsNotNegative(month, day, steps); // Новая функция которая должна заменять отрицательное кол-во шагов на 0.
} else if (userInput == 2) {
System.out.print("Введите номер месяца: ");
int month = scanner.nextInt();
//stepTracker.printArray();
stepTracker.printMonth(month);
} else if (userInput == 3) {
System.out.println("\n Статистика за год: ");
stepTracker.printArray();
} else if (userInput == 4) {
System.out.print("\nВведите номер месяца: \n");
int month = scanner.nextInt();
stepTracker.summOfStepsPerMonth(month);
} else if (userInput == 5) {
System.out.println("\n Стандартная цель по шагам за день = 10000 шагов.");
System.out.println("\n Установка цели по шагам:");
System.out.println("\n 1 - Январь; 2 - Февраль; 3 - Март; 4 - Апрель; 5 - Май; 6 - Июнь; 7 - Июль; 8 - Август; 9 - Сентябрь; 10 - Октябрь; 11 - Ноябрь; 12 - Декабрь. \n");
System.out.print("Введите номер месяца: ");
int monthSt = scanner.nextInt();
System.out.print("Введите номер дня от 1 до 30: ");
int daySt = scanner.nextInt();
System.out.print("Введите цель по шагам за " + daySt + " день " + monthSt + "-го месяца: " );
int stepsSt = scanner.nextInt();
stepTracker.changeTargetOfSteps(stepsSt);
} else if (userInput == 6) {
System.out.print("Введите номер месяца: ");
int month = scanner.nextInt();
stepTracker.maxAmountOfStepsPerMonth(month);
} else if (userInput == 7) {
System.out.print("Введите номер месяца: ");
int month = scanner.nextInt();
stepTracker.findAverage(month);
} else if (userInput == 8) {
System.out.print("\nВведите количество шагов: ");
int steps = scanner.nextInt();
converter.convertSteps(steps);
} else if (userInput == 9) {
System.out.print("\nВведите количество шагов: ");
int steps = scanner.nextInt();
converter.convertCalories(steps);
} else if (userInput == 10) {
**Здесь должна быть функция которая находит максимальное количество подряд идущих дней, в течение которых количество шагов за день было выше целевого.**
} else if (userInput == 11) {
// Это выход из программы
} else {
System.out.println("\nТакой команды нет. Введите команду от 1 до 11."); // Команды будут позже
}
printMenu(); // Печатаем меню еще раз перед завершением предыдущего действия
userInput = scanner.nextInt(); // Повторное считывание данных от пользователя
}
System.out.println("Программа завершена.");
}
private static void printMenu() {
System.out.println("\n Что вы хотите сделать?\n");
System.out.println("1) Ввести количество шагов за месяц и за день.");
System.out.println("2) Напечатать статистику за месяц. ");
System.out.println("3) Напечатать статистику за год. ");
System.out.println("4) Узнать общее количество шагов за месяц.");
System.out.println("5) Изменить цель по количеству шагов в день.");
System.out.println("6) Показать максимально пройденное количество шаго в месяце");
System.out.println("7) Показать среднее количество шагов в месяце");
System.out.println("8) Показать пройденную дистанцию в месяце");
System.out.println("9) Узнать количество сожженных килокалорий");
System.out.println("10) Показать лучшую серию");
System.out.println("11) Выйти из приложения");
System.out.print("\n Введите команду: ");
}
Код в классе StepTracker:
package com.FirstSprint;
import java.util.Arrays;
public class StepTracker {
int targetStepsPerDay = 10000;
int [][] array = new int[12][30];
public void printMonth (int month) { // Функция печатает статистику за определенный месяц
for (int i = 0; i < array.length; i++) {
if (month>=1 && month<=12) {
System.out.println("\nСтатистика за " + (month) + " месяц: \n");
System.out.println(Arrays.toString(array[month-1]));
break;
} else {
System.out.println("Ошибка!\nВведен некорректный номер месяца.\n" + "Введите месяц от 1 до 12.\n");
break;
}
}
}
public void printArray () { // Функция печатает статистику за весь год
for (int[] a: array) {
System.out.println(Arrays.toString(a));
}
}
public void isDailyStepsNotNegative(int month, int day, int steps) { // Новая функция которая должна заменять отрицательное кол-во шагов на 0.
if (steps > 0) {
array[month - 1][day - 1] = steps;
} else {
array[month - 1][day - 1] = (steps * 0);
}
}
public void summOfStepsPerMonth(int month) { // Функция считает общее количество шагов за выбранный месяц.
int sum = 0;
for (int i = 0; i < array[month-1].length; i++) {
sum += array[month-1][i];
}
System.out.println("\nВ "+ month + "-м месяце вы прошли " + sum + " шагов.");
}
public void changeTargetOfSteps (int stepsSt) { // функция меняет стандартную цель по шагам по выбранному дню каждого месяца.
if (stepsSt > targetStepsPerDay) {
targetStepsPerDay = stepsSt;
} else if (stepsSt < targetStepsPerDay && stepsSt > 0) {
targetStepsPerDay = stepsSt;
} else if (stepsSt < 0) {
System.out.println("\nОшибка! Целевое количество шагов не может быть меньше 0. \nВведите цифру больше 0.\n");
}
System.out.println("Новая цель по шагам за текущий день = " + targetStepsPerDay);
}
public void maxAmountOfStepsPerMonth (int month) { // Функция находит максимальное количество шагов в выбранном месяце.
int maos = 0;
for (int i = 0; i < array[month-1].length; i++) {
if (array[month-1][i] > maos) {
maos = array[month-1][i];
}
}
System.out.println("\nМаксимальное количество шагов: " + maos);
}
public void findAverage (int month) { // Функция считает среднее количество шагов в месяце
int sum = 0;
for (int i = 0; i < array[month-1].length; i++) {
sum += array[month-1][i];
}
System.out.println("\nСреднее количесвто шагов в выбранном месяце: " + (float)sum / 30);
}
public void bestSeries() { **\\Здесь должна быть функция которая находит максимальное количество подряд идущих дней, в течение которых количество шагов за день было выше целевого.**
}
}
Понимаю что текста очень много, но без помощи со стороны я не смогу разобраться как это реализовать.
Молю о помощи!
Ответы (2 шт):
Смотрите ниже я реализовал алгоритм подсчета лучшей серии с объяснениями что и где происходит. Вам же нужно будет встроить данный алгоритм в вашу программу:
Код программы:
public class Test {
public static void main(String[] args) {
int[][] array = fillArray(); //тут заполняем массив случайными числами 0-15000
printArray(array); // просто выводим массив на экран
System.out.println("------------");
System.out.print("Лучшая серия составляет: ");
System.out.print(getBestDays(array)); //сам алгоритм подсчета лучшей серии
System.out.println(" дней!");
}
public static int getBestDays(int[][] array) {
int result = 0; //колличество дней подряд с выполнением цели начальное
int count = 0; //переменная счетчик
int target = 10000; // сама цель из условия
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] > target) count++;//если колличество шагов больше цели - накапливаем счетчик
else {
//если колличество шагов меньше цели - серия закончилась!
if (count > result) {
result = count; //если серия лучше результата что у нас уже есть - записываем в
count = 0; //результат эту серию и сбрасываем счетчик
} else { //если серию хуже результата то просто сбрасываем счетчик и идем
count = 0; //дальше по массиву в поисках новой серии
}
}
}
}
return result; // мы прошли весь массив и возвращаем результат
// (в нем уже хранится лучшая серия)
}
public static int[][] fillArray() {
Random random = new Random();
int[][] array = new int[12][30];
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
array[i][j] = random.nextInt(15000);
}
}
return array;
}
public static void printArray(int[][] array) {
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
}
Выход:
3861 5436 13999 6011 6035 1397 11213 9707 8686 6862 4074 14184 5232 4350 7042 14547 9896 13506 3401 6530 4726 3939 8387 14193 6523 5091 12248 8229 11862 9619
3644 3269 2579 6644 165 509 2367 11568 3021 3592 5159 13500 10528 13529 13037 10365 11535 3158 2388 10595 2298 2066 13771 7422 12789 989 6957 13108 11033 6755
18 6701 1163 11710 5814 10499 2562 10240 5191 13449 10658 9089 13276 7134 10917 2136 14016 12094 2121 9138 3406 11478 1741 4077 6911 2746 10853 14976 13175 1548
2877 3401 10109 147 7353 3426 2961 10678 13531 6625 2208 14603 3886 8146 7946 1177 2807 10635 12957 2158 6556 8876 2586 14966 11373 12440 1005 1441 1806 6453
539 12159 9166 6956 540 10714 2818 14301 2103 4248 9947 5507 13821 8668 14390 8687 3949 3000 3690 10764 13311 2369 7996 4286 7028 7647 6318 8983 6274 5264
342 4328 3134 11600 3658 12024 13554 6086 4458 13068 7190 294 8918 9683 13882 3326 6718 453 6746 6904 7312 10192 4178 12723 12684 5366 7401 13158 8348 830
9642 13098 11927 8445 9940 11811 14837 10529 14500 3251 8492 4866 3113 11043 14600 1157 13109 13423 10586 7446 11643 12148 1991 1226 6771 2680 9177 8111 4083 5966
11508 1144 1384 9317 12278 4560 7730 12581 225 14098 8245 14205 2821 7971 7427 8011 5254 13317 10639 2793 9861 11648 9117 576 14210 11727 5830 2092 1055 9093
1399 7156 112 9074 10296 10012 14831 13533 7098 8801 6900 9304 4290 4384 8121 10795 11202 5523 12235 4726 5567 7049 1684 1574 10253 2137 12318 11675 7942 12251
1042 14868 12297 259 7431 7911 12039 12850 12502 2889 2233 7347 13953 12022 14974 9423 10572 4630 6633 4782 1523 1484 5790 4267 11323 5212 1573 14458 13214 7881
1039 9696 2262 11280 3950 11255 1866 3396 11537 13453 558 7999 9100 3112 620 3833 6846 12480 9265 12200 12844 7081 6371 2557 12123 4739 2574 14695 14051 8560
614 12190 4446 12441 3734 2597 968 4565 5991 13885 9497 7279 8244 14691 11949 7899 9602 5117 7957 2453 13485 14254 8455 1207 1414 10019 4848 2277 2953 2105
------------
Лучшая серия составляет: 6 дней!
В моем коде вас интересует только функция getBestDays, в ней вся логика как обработать двухмерный массив на лучшую серию. Две другие функции только для того чтобы создать сам массив, который у вас уже итак будет. Так как вы с клавиатуры вводите значения. Если будут вопросы - задавайте
Проходите по массиву, для каждого значения, удовлетворяющего условию, инкрементируете счётчик и сразу же проверяете максимум; иначе как только обнаружен день с меньшим числом шагов, счётчик сбрасывается:
// StepTracker
int targetStepsPerDay = 10000;
int [][] array = new int[12][30];
public int bestSeries() {
int maxCount = 0;
int count = 0;
for (int[] days : array) {
for (int steps : days) {
if (steps >= targetStepsPerDay) {
if (++count > maxCount) {
maxCount = count;
}
} else {
count = 0;
}
}
}
return maxCount;
}
В таком случае не придётся дополнительно перепроверять случай, когда самая длинная последовательность придётся на конец года.
Для поиска самой длинной последовательности в заданном месяце достаточно убрать "верхний" цикл, выбрав конкретный месяц:
/**
@param month 1..12 - номер месяца
*/
public int bestSeries(int month) {
int maxCount = 0;
int count = 0;
for (int steps : array[month - 1]) {
if (steps >= targetStepsPerDay) {
if (++count > maxCount) {
maxCount = count;
}
} else {
count = 0;
}
}
return maxCount;
}