Jak znaleźć największą i najmnejszą liczbę wygenerowaną randomowo?

0

Cześć, z godnie z sugestią zakładam nowy temat i nie męczę już tamtego. ;) Mam problem w tym zadaniu:

  1. Napisz program przy użyciu listy ArrayList zawierającej kilkanaście ocen z przedmiotu Informatyka w liceum.

  2. Wypełnij listę przykładowymi ocenami.**

  3. Następnie przy pomocy pętli for oblicz średnią ocenę ucznia (średnia arytmetyczna), ale w taki sposób, że pominięte zostaną skrajne
    oceny – JEDNA najmniejsza i JEDNA największa.
    Oceny największą i najmniejszą należy odnaleźć. Przykładowo, dla ocen:

    a) 3,3,4,4,4,5,5,5,6 – do obliczenia średniej wzięte zostaną oceny: 3,4,4,4,5,5,5
    b) 4,4,4,4,4,4,4 – do obliczenia średniej wzięte zostaną oceny: 4,4,4,4,4

I teraz użyłem Collections.sort(); i ładnie mi posortowało, później w klasie Average napisałem instrukcję, że jeśli ocena z indeksem 0 jest jest mniejsza bądź równa ocenie z indeksem 1 && ocena z indeksem 8 jest jest mniejsza bądź równa ocenie z indeksem 9, to niech odejmie od sumy licznika ocenę z indeksem 0 i 9.

package com;

import java.util.*;

public class Main {

    public static void main(String[] args) {

        System.out.println("Zadanie 1");
        List<Integer> list = new ArrayList<>();
        RateList rateList = new RateList(list);
        rateList.rateListGenerator();
        rateList.sortRateList();

        Average average = new Average(list);
        System.out.println(String.format("Średnia z wszystkich ocen:  %,.2f", average.countAverage()));

        System.out.println("\nZadanie 2");
        Books bookList = new Books();
        bookList.printPositions();

    }
}
class RateList {

    private Random random = new Random();

    private List<Integer> rateList;

    public RateList(List<Integer> rateList) {
        this.rateList = rateList;
    }

    public List<Integer> rateListGenerator() {

        for (int i = 0; i < 10; i++) {
            int rateGenerator = random.nextInt(6) + 1;
            rateList.add(i, rateGenerator);
        }

        for (Integer item : rateList) {
            System.out.println("Ocena: " + item);
        }
        return rateList;
    }

    public List<Integer> sortRateList() {

        Collections.sort(rateList);
        for (Integer item : rateList) {
            System.out.println("Posortowana lista ocen: " + item);
        }

        System.out.println("Rozmiar listy: " + rateList.size());

        return rateList;
    }
}

class Average {

    private List<Integer> rateList;

    public Average(List<Integer> rateList) {
        this.rateList = rateList;
    }

    public float countAverage() {

        int sum = 0;

        if (rateList.get(0) <= rateList.get(1) && rateList.get(8) <= rateList.get(9)) {
            for (int i = 0; i < rateList.size(); i++) {
                sum = sum + rateList.get(i);
            }
            sum = sum - rateList.get(0) - rateList.get(9);
        }

        else {
            for (int i = 0; i < rateList.size(); i++) {
                sum = sum + rateList.get(i);
            }
        }
        System.out.println("Suma licznika po odjęciu oceny pierwszej i ostatniej: " + sum);
        return (float) sum / (float) rateList.size();
    }
}

Wszystko działa, ale mentor ma "ale" i chce, żeby najmniejszą i największą liczbę odnaleźć bez sortowania, macie jakieś pomysły? :)

5

Ale hardcore z tego mentora. Tutaj masz kod na sztywno wyszukujacy najmniejsza liczbe:

int smallest = list.get(0);

for(int i = 0; i < list.size(); i++) {
    int number = list.get(i);
    if (smallest > number) {
        smallest = number;
    }
}
System.out.println(smallest);

Największa chyba wiesz juz jak zrobic. Powodzenia :)

2

@p_agon: Super! Dziękuje za pomoc! :D

2

W czasie liniowym powinieneś to zrobić, bez żadnego sortowania

0

@Charles_Ray: @p_agon: czy tak zrobiony konstruktor w klasie Average jest poprawny? Bo nie za bardzo wiem jak przenieść metody findBiggest() i findSmallest() bez dziedziczenia po klasie RateList, a w konsekwencji tego mam w metodzie main() w konstruktorze dwie listy.

Na chwilę obecną tak to się prezentuje:

package com;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class Main {

    public static void main(String[] args) {
        System.out.println("Zadanie 1");
        List<Integer> list = new ArrayList<>();
        RateList rateList = new RateList(list);
        rateList.generateRates();
        //rateList.findSmallest();
        //rateList.findBiggest();

        Average average = new Average(list, list);
        System.out.println(String.format("Średnia z wszystkich ocen:  %,.2f", average.countAverage()));

        System.out.println("\nZadanie 2");
        Books bookList = new Books();
        bookList.printPositions();

    }
}
class RateList {

    private Random random = new Random();

    private List<Integer> rateList;

    public RateList(List<Integer> rateList) {
        this.rateList = rateList;
    }

    public List<Integer> generateRates() {

        for (int i = 0; i < 10; i++) {
            int rateGenerator = random.nextInt(6) + 1;
            rateList.add(i, rateGenerator);
        }

        for (Integer item : rateList) {
            System.out.println("Ocena: " + item);
        }
        return rateList;
    }

    public int findSmallest() {
        /*
        Collections.sort(rateList);
        for (Integer item : rateList) {
            System.out.println("Posortowana lista ocen: " + item);
        }

        System.out.println("Rozmiar listy: " + rateList.size());

         */

        int smallest = rateList.get(0);

        for(int i = 0; i < rateList.size(); i++) {
            int number = rateList.get(i);
            if (smallest > number) {
                smallest = number;
            }
        }
        System.out.println("Najmniejsza: " + smallest);

        return smallest;
    }

    public int findBiggest() {

        int biggest = rateList.get(0);

        for(int i = 0; i < rateList.size(); i++) {
            int number = rateList.get(i);
            if (biggest < number) {
                biggest = number;
            }
        }
        System.out.println("Najawiększa: " + biggest);
        return biggest;
    }
}

class Average extends RateList {

    private List<Integer> rateList;

    public Average(List<Integer> rateList, List<Integer> rateList1) {
        super(rateList);
        this.rateList = rateList1;
    }

    public float countAverage() {

        int sum = 0;

        for (int i = 0; i < rateList.size(); i++) {
            sum = sum + rateList.get(i);
        }

        System.out.println("Suma licznika przed odjęciem oceny jednej największej i jednej najmniejszej: " + sum);
        return (float) (sum - findSmallest() - findBiggest()) / (float) rateList.size();
    }
}

Edit: Wydaje mi się, że obiekt Average powinien przyjmować jedną listę, a nie dwie te same.

2

Myk w tym zadaniu, to pojedyncze przejście przez listę. Zatem sortowania itp. odpadają.

W dużym skrócie


 for( int i : list){
  if(i > max) max = i;
  if(i < min) min = i;
  sum += i;
}

System.out.println((sum-min-max)/(list.size()-2));

W pojedynczej pętli szukasz min, max i wyliczasz sumę wszystkich elementów. Potem liczysz średnią, ale od sumy musisz odjąć skrajne wartości, a wielkość zbioru (długość listy) zmniejszyć o 2.

0

Hej, to znowu ja, czy jakaś dobra dusza mogła by mi powiedzieć czy potrzeby mojego szacownego mentora zostały już zaspokojone poniższym kodzie? :)

A o to uwagi mentora:

  1. Linia 10 - po co RateList otrzymuje pusta liste? Pusta liste sam moze sobie zrobic przeciez.
  2. Metoda generateRates() powinna zwrócić listę, którą przekażesz klasie Average w konstruktorze.
  3. Taki kod jest bardzo nieczytelny. W linii 9 tworzysz sobie liste, a potem ona jest w różnych klasach modyfikowana i używana do obliczeń - bardzo ciężko prześledzić to, co się z tą listą dzieje.
  4. Klasa Books to takie combo - po nazwie się bym spodziewał, ze służy ona do przechowywania książek. Powininna ona (jak w przypadku ocen wyżej) generować losowo ksiązki i ewentualnie umieć wypisać wygenerowane książki. Do tego powinna być klasa np. BookFilter, która filtruje te książki (metoda zwracająca przefiltrowaną listę książek). To magiczne 2000 może być jej parametrem.
package com;

import java.util.*;

public class Main {

    public static void main(String[] args) {

        RateList rateList = new RateList();
        rateList.generateRates();
        rateList.printList();
        Average average = new Average(rateList.generateRates());
        System.out.println(String.format("Średnia z ocen (po odjęciu największej i najmniejszej):  %,.2f", average.countAverage()));

        System.out.println("\n\n");
        BooksFilter booksFilter = new BooksFilter();
        booksFilter.printPositions();

    }
}
class RateList {

    private final Random random = new Random();

    private List<Integer> rateList;

    public RateList() {
        rateList = new ArrayList<>();
    }

    public List<Integer> generateRates() {

        for (int i = 0; i < 10; i++) {
            int rateGenerator = random.nextInt(6) + 1;
            rateList.add(i, rateGenerator);
        }
        return rateList;
    }

    public List<Integer> printList() {

        for (Integer item : rateList) {
            System.out.println("Ocena: " + item);
        }

        return rateList;
    }
}

class Average {

    private List<Integer> rateList;

    public Average(List<Integer> rateList) {
        this.rateList = rateList;
    }

    public int findSmallest() {

        int smallest = rateList.get(0);

        for(int i = 0; i < rateList.size(); i++) {
            int number = rateList.get(i);
            if (smallest > number) {
                smallest = number;
            }
        }

        return smallest;
    }

    public int findBiggest() {

        int biggest = rateList.get(0);

        for(int i = 0; i < rateList.size(); i++) {
            int number = rateList.get(i);
            if (biggest < number) {
                biggest = number;
            }
        }
        return biggest;
    }

    public float countAverage() {

        int sum = 0;

        for (int i = 0; i < rateList.size(); i++) {
            sum = sum + rateList.get(i);
        }
        return (float) (sum - findSmallest() - findBiggest()) / (float) rateList.size();
    }
}

class Book {
    private String bookName;
    private int publicationYear;

    public Book(String bookName, int publicationYear) {
        this.bookName = bookName;
        this.publicationYear = publicationYear;
    }

    public int getPublicationYear() {
        return publicationYear;
    }

    @Override
    public String toString() {
        return "Książka: " + '"' + bookName + '"' +" rok wydania: " + publicationYear;
    }
}

class BooksGenerator {

    private final Random random = new Random();

    public List<Book> generateBooks() {

        List<Book> booksList = new LinkedList<Book>();

        String chars = "abcdefghijklmnoprstuwyzABCDEFGHIJKLMNOPRSTUWYZ";

        int booksNumber = random.nextInt(20) + 10;
        for (int i = 0; i < booksNumber; i++) {
            String bookName = "";
            int loopLaps = random.nextInt(10) + 1;
            for (int j = 0; j < loopLaps; j++) {
                int bookNameLength = random.nextInt(chars.length());
                bookName = bookName + chars.charAt(bookNameLength);
            }
            int yearGenerator = random.nextInt(21) + 1990;
            booksList.add(new Book(bookName, yearGenerator));
        }
        return booksList;
    }
}

class BooksFilter extends BooksGenerator {

    public List<Book> checkYear() {

        List<Book> booksList = generateBooks();
        List<Book> newBooksList = new LinkedList<>();
        for (int i = 0; i < booksList.size(); i++) {
            if (booksList.get(i).getPublicationYear() > 2000) {
                newBooksList.add(booksList.get(i));
            }
        }
        return newBooksList;
    }

    public List<Book> printPositions() {

        List<Book> booksList = checkYear();
        for (Book item : booksList) {
            System.out.println(item);
        }
        return booksList;
    }
}
1

Szczerze, to tych uwag jest tak dużo, więc tylko parę:

  1. Czemu służy ta RateList? Jeśli jest to lista ocen, to powinna mieć metody do operowania na tych ocenach, czyli np .average(), a ona zajmuje się generowanie losowych wartości i ich drukowaniem, czyli niczym co ma coś szczególnego z ocenami. W dodatku te metody zwracają ukrytą w środku listę, wiec można z nią robić co się chce w miejscach najmniej oczekiwanych np.:
        List<Integer> list = rateList.generateRates();
        rateList.printList().clear();
        Average average = new Average(list);

    Zgadnij co się stanie? Jeśli chcesz zwracać tę listę, to zwracaj ją getter, bo to będzie widoczne.

  2. Metody findSmallest ifindBiggest mają nietrafione nazwy w odniesieniu do klasy, jakby zwracały ekstrema średnich, a nie wartości użytych do liczenia średniej. Jeśli chcesz oddzielić obliczenia od listy to może RateStatistics z metodami average, min i max. Wspomniane wyżej metody są błędne, sprawdź co się dzieje dla pustych list.
  3. Nazwa metody average też nie za bardzo pasuje do sposobu liczenia, bo wykluczasz kilka wartości, więc może averageWithExclusions.
  4. Wspomniane metody findXXX są zbędne, bo w treści zadania nic o nich nie wspomniano. @Koziołek podał Ci sposób na przejście przez listę raz obliczając wszystko co potrzebne do tej średniej. Wykonujesz, aż trzy przejścia przez listę. Akurat w tym przypadku metody, które poprawiają czytelność kodu, fatalnie wpływają na wydajność metody, która jest głównym celem zadania.

Zostaje jeszcze metoda losująca, która ma magic numbers, pola instancyjne generatora pseudolosowego, który mógłby być polem statycznym, itd.

Wg mnie zdefiniuj jedną klasę RateList z konstruktorem przyjmującym listę ocen, którą generujesz poza tą klasą (np. metodą statyczną klasy RateList, która zwracałby listę losowa ocen), i z metodą averageWithExclusions i nadpisaną metodą toString (zamiast print zwracającego listę). Jeśli ta klasa ma mieć jakiś sens, to powinieneś zadbać o to, by w liście z ocenami były tylko liczby od 1 do 6, choć w tym przypadku najlepszy byłby enum. Drugie rozwiązanie do klasa RandomRateList z konstruktorem o parametrze określającym ile ocen ma być wygenerowanych i getterem zwracającym listę i klasa RateStatistics przyjmująca w konstruktorze obiekt klasy RandomRateList i metodą average.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0