Loading...

Във форума е въведено ограничение, което позволява на потребителите единствено да разглеждат публикуваните въпроси.

nbzhk avatar nbzhk 2 Точки

Оптимизация на код, 10. SoftUni Course Planning

Здравейте, успях да реша задачата, но мисля, че го направих прекалено сложно. Бих се радвал, ако някой изкаже мнение за кода, дали е четлив и какво мога да оптимизирам. Най - много "swap" ме затрудни и като, че ли там най - нечетливо стана...

Ето го моя код: https://pastebin.com/kMJvNfnp

А ето го и условието: 

1. *SoftUni Course Planning

On the first input line, you will receive the initial schedule of lessons and exercises that will be part of the next course, separated by a comma and space ", ". But before the course starts, there are some changes to be made. Until you receive "course start", you will be given some commands to modify the course schedule. The possible commands are:

Add:{lessonTitle} - add the lesson to the end of the schedule, if it does not exist

Insert:{lessonTitle}:{index} - insert the lesson to the given index, if it does not exist

Remove:{lessonTitle} - remove the lesson, if it exists

Swap:{lessonTitle}:{lessonTitle} - change the place of the two lessons, if they exist

Exercise:{lessonTitle} - add Exercise in the schedule right after the lesson index, if the lesson exists and there is no exercise already, in the following format "{lessonTitle}-Exercise". If the lesson doesn't exist, add the lesson at the end of the course schedule, followed by the Exercise.

Each time you Swap or Remove a lesson, you should do the same with the Exercises, if there are any, which follow the lessons.

Input

  • On the first line -the initial schedule lessons -strings, separated by comma and space ", ".
  • Until "course start", you will receive commands in the format described above.

Output

  • Print the whole course schedule, each lesson on a new line with its number(index) in the schedule:
    "{lesson index}.{lessonTitle}".
  • Allowed working time / memory: 100ms / 16MB.

Examples

Input

Output

Comment

Data Types, Objects, Lists

Add:Databases

Insert:Arrays:0

Remove:Lists

course start

1.Arrays

2.Data Types

3.Objects

4.Databases

 

We receive the initial schedule.

Next, we add the Databases lesson because it doesn't exist.

We Insert the given index lesson Arrays because it's not present in the schedule.

After receiving the last command and removing lesson Lists, we print the whole schedule.

Arrays, Lists, Methods

Swap:Arrays:Methods

Exercise:Databases

Swap:Lists:Databases

Insert:Arrays:0

course start

1.Methods

2.Databases

3.Databases-Exercise

4.Arrays

5.Lists

We swap the given lessons because both exist.

After receiving the Exercise command, we see that such a lesson doesn't exist, so we add the lesson at the end, followed by the exercise.

We swap Lists and Databases lessons. The Databases-Exercise is also moved after the Databases lesson.

We skip the next command because we already have such a lesson in our schedule.

 

 

1
Fundamentals Module
MartinBG avatar MartinBG 4803 Точки
Best Answer

Тази задача трудно може да се реши по красив начин, ако се придържаме към условието да използваме само List<String> - логиката, необходима за менажирането му е "обречена" да бъде сложна. Когато в практиката се наложи да работим с такъв код е най-добре да го изолираме в отделен клас или метод, който да "скрие" имплементацията от ползвателите на тази функционалнст.

В случая може да изнесем логиката за всяка команда в отделен метод.

Другото, което може да направим е да сменим if-else if ... конструкцията със switch:

        while (!"course start".equals(command = scanner.nextLine())) {
            String[] commandElements = command.split(":");
            String action = commandElements[0];
            String lessonTitle = commandElements[1];

            switch (action) {
            case "Add": {
                add(schedule, lessonTitle);
                break;
            }
            case "Insert": {
                int index = Integer.parseInt(commandElements[2]);
                insert(schedule, lessonTitle, index);
                break;
            }
            case "Remove": {
                remove(schedule, lessonTitle);
                break;
            }
            case "Swap": {
                String secondLessonTitle = commandElements[2];
                swap(schedule, lessonTitle, secondLessonTitle);
                break;
            }
            case "Exercise": {
                exercise(schedule, lessonTitle);
                break;
            }
            default:
                throw new IllegalArgumentException("Unknown command: " + command);
            }
        }

В Java 17+ горното може да се напише и така:

            switch (action) {
            case "Add" -> add(schedule, lessonTitle);
            case "Insert" -> {
                int index = Integer.parseInt(commandElements[2]);
                insert(schedule, lessonTitle, index);
            }
            case "Remove" -> remove(schedule, lessonTitle);
            case "Swap" -> {
                String secondLessonTitle = commandElements[2];
                swap(schedule, lessonTitle, secondLessonTitle);
            }
            case "Exercise" -> exercise(schedule, lessonTitle);
            default -> throw new IllegalArgumentException("Unknown command: " + command);
            }

 

Други коментари по кода:

- Избягвайте повторенията на литерали (напр.  "-Exercise") - вместо това използвайте статични константи

- При сравнението на литерал с променива е по-безопасно да използвате литерала като обект, а променливта - като аргумент (!"course start".equals(command) вместо !command.equals("course start"))

- Изпозвайте готовите методи за работа с контейнери, вместо да пишете собствена логика:

    private static boolean alreadyExists(List<String> schedule, String lessonTitle) {
        for (int i = 0; i < schedule.size(); i++) {
            if (schedule.get(i).equals(lessonTitle)) {
                return true;
            }
        }
        return false;
    }

// може да е

    private static boolean alreadyExists(List<String> schedule, String lessonTitle) {
        return schedule.contains(lessonTitle);
    }

 

 

Това е цялото с решение с горните и още няколко промени:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

public class P10SoftUniCoursePlanning {

    private static final String EXERCISE_SUFFIX = "-Exercise";

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        List<String> schedule = Arrays
                .stream(scanner.nextLine().split(", "))
                .collect(Collectors.toList());

        String command;

        while (!"course start".equals(command = scanner.nextLine())) {
            String[] commandElements = command.split(":");
            String action = commandElements[0];
            String lessonTitle = commandElements[1];

            switch (action) {
            case "Add": {
                add(schedule, lessonTitle);
                break;
            }
            case "Insert": {
                int index = Integer.parseInt(commandElements[2]);
                insert(schedule, lessonTitle, index);
                break;
            }
            case "Remove": {
                remove(schedule, lessonTitle);
                break;
            }
            case "Swap": {
                String secondLessonTitle = commandElements[2];
                swap(schedule, lessonTitle, secondLessonTitle);
                break;
            }
            case "Exercise": {
                exercise(schedule, lessonTitle);
                break;
            }
            default:
                throw new IllegalArgumentException("Unknown command: " + command);
            }
        }

        for (int i = 0, counter = 1; i < schedule.size(); i++, counter++) {
            System.out.printf("%d.%s%n", counter, schedule.get(i));
        }
    }

    private static void add(List<String> schedule, String lessonTitle) {
        if (!alreadyExists(schedule, lessonTitle)) {
            schedule.add(lessonTitle);
        }
    }

    private static void insert(List<String> schedule, String lessonTitle, int index) {
        if (!alreadyExists(schedule, lessonTitle)) {
            schedule.add(index, lessonTitle);
        }
    }

    private static void remove(List<String> schedule, String lessonTitle) {
        if (alreadyExists(schedule, lessonTitle)) {
            schedule.remove(lessonTitle);
        }
    }

    private static void swap(List<String> schedule, String firstLessonTitle, String secondLessonTitle) {
        if (alreadyExists(schedule, firstLessonTitle) && alreadyExists(schedule, secondLessonTitle)) {
            int firstIndex = findIndex(schedule, firstLessonTitle);
            int secondIndex = findIndex(schedule, secondLessonTitle);

            Collections.swap(schedule, firstIndex, secondIndex);

            if (exerciseExist(schedule, schedule.get(secondIndex))) {
                int exerciseIndex = findIndex(schedule, schedule.get(secondIndex) + EXERCISE_SUFFIX) + 1;
                schedule.add(secondIndex + 1, schedule.get(secondIndex) + EXERCISE_SUFFIX);
                schedule.remove(exerciseIndex);
            }
            if (exerciseExist(schedule, schedule.get(firstIndex))) {
                int oldExerciseIndex = findIndex(schedule, schedule.get(firstIndex) + EXERCISE_SUFFIX) + 1;
                schedule.add(firstIndex + 1, schedule.get(firstIndex) + EXERCISE_SUFFIX);
                schedule.remove(oldExerciseIndex);
            }
        }
    }

    private static void exercise(List<String> schedule, String lessonTitle) {
        if (alreadyExists(schedule, lessonTitle) && !exerciseExist(schedule, lessonTitle)) {
            int indexToAdd = findIndex(schedule, lessonTitle) + 1;
            schedule.add(indexToAdd, lessonTitle + EXERCISE_SUFFIX);
        } else if (!alreadyExists(schedule, lessonTitle)) {
            schedule.add(lessonTitle);
            schedule.add(lessonTitle + EXERCISE_SUFFIX);
        }
    }

    private static boolean alreadyExists(List<String> schedule, String lessonTitle) {
        return schedule.contains(lessonTitle);
    }

    private static int findIndex(List<String> schedule, String lesson) {
        return schedule.indexOf(lesson);
    }

    private static boolean exerciseExist(List<String> schedule, String lesson) {
        String lessonExercise = lesson + EXERCISE_SUFFIX;
        return schedule.contains(lessonExercise);
    }
}

 

1
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.