Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Небольшая задача 
V
    Опции темы
brave
Дата 17.10.2012, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 7.3.2010

Репутация: нет
Всего: нет



Всем привет, решил(или не совсем решил:)) небольшую задачку. Тех, у кого есть немного времени, прошу прокомментировать и указать на недостатки. Тянут ли задачи такого типа на уровень джуниора?

Задача:

Определить класс, описывающий покупку одного и того же штучного товара по одной и той же цене в течение одного месяца и содержащий сведения о дне покупки и количестве приобретенных единиц.
Допускаются еще три варианта покупок:
1. со скидкой, задаваемой процентом от стоимости;
2. со скидкой в цене (например, цена товара 5000 руб., скидка 300 руб.);
3. с надбавкой за транспортные расходы на доставку товара.
Создать консольное приложение, в котором последовательно выполнить следующие задания:
– определить набор покупок различного вида (не менее 10);
– вывести на консоль в табличном виде (можно без границ) набор покупок (полный состав атрибутов);
– вычислить и вывести стоимость всех покупок;
– отсортировать покупки по возрастанию дня покупки и вывести их на консоль;
– определить, была ли покупка в десятый день месяца.

Требования:
– Использовать объектно-ориентированный подход для описания покупок.
– Массив или коллекцию покупок инициализировать в коде с помощью конструктора или метода. Как следствие, не использовать внешние источники данных: консоль (т.е. ввод с клавиатуры), файлы, СУБД, XML и т.п.
– Приложение должно быть консольным. Не использовать графический интерфейс! Таким образом, приложение ничего не должно вводить, а только выводить результаты на консоль.

Код

import java.text.*;
import java.util.*;

public class First
{
    
   public static void main(String[] args) 
   {
       catalog = new LinkedList<Purchase>();
       catalog.add(new Purchase("Pen", 100.0, "12-10-2012", 2, 0.0, 10, 0));
       catalog.add(new Purchase("Pencil", 120.0, "1-10-2012", 7, 5.0, 0, 0));
       catalog.add(new Purchase("Book", 2000.0, "16-10-2012", 1, 0.0, 100, 50));
       catalog.add(new Purchase("Wallet", 5050.0, "7-10-2012", 2, 0.0, 250, 150));
       catalog.add(new Purchase("Paper", 500.0, "30-10-2012", 10, 10.0, 0, 20));
       catalog.add(new Purchase("Ink", 1000.0, "2-10-2012", 5, 10.0, 0, 0));
       catalog.add(new Purchase("Ruler", 200.0, "4-10-2012", 20, 15.0, 0, 0));
       catalog.add(new Purchase("Button", 100.0, "29-10-2012", 50, 20.0, 0, 0));
       catalog.add(new Purchase("Rubber", 150.0, "19-10-2012", 4, 2.0, 10, 0));
       catalog.add(new Purchase("Sharpener", 300.0, "23-10-2012", 1, 0.0, 0, 0));
           
       for (int i = 0; i < catalog.size(); i++)
       {
           Purchase e = catalog.get(i);
           double totalDiscount = e.getQuantity() * e.getPrice() * e.getPercentDiscount() / 100 + e.getPriceDiscount();
           totalAmount += (e.getQuantity() * e.getPrice() - totalDiscount + e.getShipping());    
           
           Calendar cal = Calendar.getInstance();
           cal.setTime(catalog.get(i).getDate());
           if (cal.get(Calendar.DAY_OF_MONTH) == 10) tenthDay = true;
       }
       
       sort();       
       print();
       
       System.out.println();
       System.out.println("Total amount of all articles: " + totalAmount + " BYR");
       
       if (tenthDay) System.out.println("There was a purchase on the tenth day of this month.");
       System.out.println("There was no purchase on the tenth day of this month.");           
   }
      
   static void print()
   {
       System.out.println("| Article  |  Price  | Quantity | Discount, % | Discount, BYR | Shipping, BYR |  Amount  |     Day     |");
       System.out.println("|__________|_________|__________|_____________|_______________|_______________|__________|_____________|");
       for (int i = 0; i < catalog.size(); i++)
       {
           Purchase e = catalog.get(i);
           double totalDiscount = e.getQuantity() * e.getPrice() * e.getPercentDiscount() / 100 + e.getPriceDiscount();
           System.out.format("|%9s  %7.2f       %2d        %5.2f         %6.2f          %6.2f       %8.2f     %10s |", 
                   e.getArticle(), e.getPrice(), e.getQuantity(), e.getPercentDiscount(), e.getPriceDiscount(), e.getShipping(), 
                   (e.getQuantity() * e.getPrice() - totalDiscount + e.getShipping()), e.getDay());
           System.out.println();
       }       
   }
   
   static void sort()
   {
       for (int j = catalog.size() - 1; j > 0; j--)
       for (int i = 0; i < j; i++)
       {
           if (catalog.get(i).getDate().compareTo(catalog.get(i + 1).getDate()) > 0)
               Collections.swap(catalog, i, i + 1);
       } 
   }
       
   static List<Purchase> catalog; 
   static double totalAmount;
   static boolean tenthDay;
}

class Purchase  
{
  public Purchase(String article, double price, String day, int quantity, double percentDiscount, 
          double priceDiscount, double shipping)
  {
      this.article = article;
      this.quantity = quantity;
      this.price = price;
      this.percentDiscount = percentDiscount;
      this.priceDiscount = priceDiscount;
      this.shipping = shipping;
      
      try
      {
         this.day = formatter.parse(day);
      }
      catch(ParseException e)
      {
          e.printStackTrace();
      }
  }    
    
  public String getArticle()
  {
      return article;
  }
  
  public void setArticle(String newArticle)
  {
      article = newArticle;
  }
  
  public String getDay()
  {
      return formatter.format(day);
  }
  
  public Date getDate()
  {
      return day;
  } 
  
  public void setDay(String newDay)
  {
      try
      {
          day = formatter.parse(newDay);
      }
      catch(ParseException e)
      {
          e.printStackTrace();
      }
  }
  
  public int getQuantity()
  {
      return quantity;
  }
  
  public void setQuantity(int newQuantity)
  {
      quantity = newQuantity;
  }
  
  public double getPrice()
  {
      return price;
  }
  
  public void setPrice(double newPrice)
  {
      price = newPrice;
  }
  
  public double getPercentDiscount()
  {
      return percentDiscount;
  }
  
  public void setPercentDiscount(double newDiscount)
  {
      percentDiscount = newDiscount;
  }

  public double getPriceDiscount()
  {
      return priceDiscount;
  }

  public void setPriceDiscount(double newDiscount)
  {
      priceDiscount = newDiscount;
  }

  public double getShipping()
  {
      return shipping;
  }

  public void setShipping(double newValue)
  {
     shipping = newValue; 
  }
  
  public String toString()
  {
      double totalDiscount = quantity * price * percentDiscount / 100 + priceDiscount;
      return article + " " + price + " " + quantity + " " + percentDiscount + " " + priceDiscount + " " + shipping + " "
              + (quantity * price - totalDiscount + shipping) + " " + formatter.format(day);
  }
  
  private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
  private String article;
  private Date day = null;
  private int quantity;
  private double price;
  private double percentDiscount;
  private double priceDiscount;
  private double shipping;
}

PM MAIL   Вверх
Mirkes
Дата 18.10.2012, 06:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Не очень эффективно, но правильно. Почти.
Строка "There was no purchase on the tenth day of this month." будет печататься всегда, поскольку в этой строке нет ключевого слова else. Этот фрагментп рограммы должен выглядеть так:
Код

       if (tenthDay) 
             System.out.println("There was a purchase on the tenth day of this month.");
       else
             System.out.println("There was no purchase on the tenth day of this month.");           



--------------------
Mirkes
PM MAIL   Вверх
brave
Дата 18.10.2012, 07:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 7.3.2010

Репутация: нет
Всего: нет



Цитата(Mirkes @ 18.10.2012,  06:44)
Не очень эффективно, но правильно. Почти.
Строка "There was no purchase on the tenth day of this month." будет печататься всегда, поскольку в этой строке нет ключевого слова else. Этот фрагментп рограммы должен выглядеть так:
Код

       if (tenthDay) 
             System.out.println("There was a purchase on the tenth day of this month.");
       else
             System.out.println("There was no purchase on the tenth day of this month.");           

Точно, else пропустил. Спасибо!

А где именно потеря эффективности?
PM MAIL   Вверх
Mirkes
Дата 18.10.2012, 07:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



В сортировке.
Код

   static void sort()
   {
       for (int j = catalog.size() - 1; j > 0; j--)
       for (int i = 0; i < j; i++)
       {
           if (catalog.get(i).getDate().compareTo(catalog.get(i + 1).getDate()) > 0)
               Collections.swap(catalog, i, i + 1);
       } 
   }


Метод сортировки очень медленный. На десятке и даже сотне ничего, но на больших объемах медленный.
В нем плохо большое количество присваиваний. Правда в вслучаи коллекции они быстрые.




--------------------
Mirkes
PM MAIL   Вверх
brave
Дата 18.10.2012, 08:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 7.3.2010

Репутация: нет
Всего: нет



Цитата(Mirkes @ 18.10.2012,  07:46)
В сортировке.
Код

   static void sort()
   {
       for (int j = catalog.size() - 1; j > 0; j--)
       for (int i = 0; i < j; i++)
       {
           if (catalog.get(i).getDate().compareTo(catalog.get(i + 1).getDate()) > 0)
               Collections.swap(catalog, i, i + 1);
       } 
   }


Метод сортировки очень медленный. На десятке и даже сотне ничего, но на больших объемах медленный.
В нем плохо большое количество присваиваний. Правда в вслучаи коллекции они быстрые.

Спасибо, использовал bubblesort, чтобы попроще. Можно реализовать через quicksort. А как решить проблему присваиваний? Есть какой-то способ сделать этот метод эффективнее?
PM MAIL   Вверх
Mirkes
Дата 18.10.2012, 10:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Цитата(brave @  18.10.2012,  08:19 Найти цитируемый пост)
Спасибо, использовал bubblesort, чтобы попроще. Можно реализовать через quicksort. А как решить проблему присваиваний? Есть какой-то способ сделать этот метод эффективнее? 

На эту тему есть обширная литература как на русском, так и на английском. Из абсолютной классики Кнут. К сожалению я не могу назвать подхлдящего источника.


--------------------
Mirkes
PM MAIL   Вверх
brave
Дата 18.10.2012, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 7.3.2010

Репутация: нет
Всего: нет



Цитата(Mirkes @ 18.10.2012,  10:46)
Цитата(brave @  18.10.2012,  08:19 Найти цитируемый пост)
Спасибо, использовал bubblesort, чтобы попроще. Можно реализовать через quicksort. А как решить проблему присваиваний? Есть какой-то способ сделать этот метод эффективнее? 

На эту тему есть обширная литература как на русском, так и на английском. Из абсолютной классики Кнут. К сожалению я не могу назвать подхлдящего источника.

Ок, я имел ввиду, что не так с присваиваниями, проблема в их количестве?
PM MAIL   Вверх
Mirkes
Дата 18.10.2012, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Вообще-то я посоветовал почитать книги.
В данном конкретном случае суть сортировки состоит в том, что вы перемещаете максимальное значение несортированной части массива в его конец и уменьшаете размер несортированной части на 1.
Для этого достаточно ОДНОЙ перестановки двух элементов.
Ваш код
Код

   static void sort()
   {
       for (int j = catalog.size() - 1; j > 0; j--)
       for (int i = 0; i < j; i++)
       {
           if (catalog.get(i).getDate().compareTo(catalog.get(i + 1).getDate()) > 0)
               Collections.swap(catalog, i, i + 1);    //перестановка!
       } 
   }

В худшей ситуации, когда исходно массив был отсортирован по убыванию, вы получите n^2 операций перестановок. Точнее n(n-1)/2. Столько же сравнений. И дважды столько получений даты из коллекции. Полагаю, что это операции одного уровня затрат по времени. 
При данном алгоритме невозможно уменьшить число сравнений. А вот с перестановками и извлеченями из коллекции можно поиграть.
Код

   private void sort() //Static ни к чему, а вот private по существу, поскольку это сортировка внутренних данных класса и не зачем
                               // разрешать ее выполнять снаружи.
   int maxNumber;
   Data maxData, cmpData;
   {
       for (int j = catalog.size() - 1; j > 0; j--){
          maxNumber=j;
          maxData=catalog.get(i).getDate();
          for (int i = 0; i < j; i++){
                  cmpData=catalog.get(i + 1).getDate();
                  if (maxData.compareTo(cmpData) > 0){
                        maxNum=i;
                        maxData=cmpData;
                  }
           }
           if (i!=j)
               Collections.swap(catalog, i, j);
       }
   }

Число сравнений то же.
Число перестановок n-1 -уменьшилось в n/2 раз
Число извлечений из массива не более n(n+1)/2 - уменьшилось не менее чем в два раза (почти). В среднем уменьшится раза в 4.
Вот собственно и вся оптимизация. На 10 или 100 значениях заметно не будет. На нескольких тысячах уже весьма ощутимо.


--------------------
Mirkes
PM MAIL   Вверх
brave
Дата 18.10.2012, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 7.3.2010

Репутация: нет
Всего: нет



Цитата(Mirkes @ 18.10.2012,  13:35)
Вообще-то я посоветовал почитать книги.
В данном конкретном случае суть сортировки состоит в том, что вы перемещаете максимальное значение несортированной части массива в его конец и уменьшаете размер несортированной части на 1.
Для этого достаточно ОДНОЙ перестановки двух элементов.
Ваш код
Код

   static void sort()
   {
       for (int j = catalog.size() - 1; j > 0; j--)
       for (int i = 0; i < j; i++)
       {
           if (catalog.get(i).getDate().compareTo(catalog.get(i + 1).getDate()) > 0)
               Collections.swap(catalog, i, i + 1);    //перестановка!
       } 
   }

В худшей ситуации, когда исходно массив был отсортирован по убыванию, вы получите n^2 операций перестановок. Точнее n(n-1)/2. Столько же сравнений. И дважды столько получений даты из коллекции. Полагаю, что это операции одного уровня затрат по времени. 
При данном алгоритме невозможно уменьшить число сравнений. А вот с перестановками и извлеченями из коллекции можно поиграть.
Код

   private void sort() //Static ни к чему, а вот private по существу, поскольку это сортировка внутренних данных класса и не зачем
                               // разрешать ее выполнять снаружи.
   int maxNumber;
   Data maxData, cmpData;
   {
       for (int j = catalog.size() - 1; j > 0; j--){
          maxNumber=j;
          maxData=catalog.get(i).getDate();
          for (int i = 0; i < j; i++){
                  cmpData=catalog.get(i + 1).getDate();
                  if (maxData.compareTo(cmpData) > 0){
                        maxNum=i;
                        maxData=cmpData;
                  }
           }
           if (i!=j)
               Collections.swap(catalog, i, j);
       }
   }

Число сравнений то же.
Число перестановок n-1 -уменьшилось в n/2 раз
Число извлечений из массива не более n(n+1)/2 - уменьшилось не менее чем в два раза (почти). В среднем уменьшится раза в 4.
Вот собственно и вся оптимизация. На 10 или 100 значениях заметно не будет. На нескольких тысячах уже весьма ощутимо.

Спасибо за детальный анализ. Значит, основная проблема - это эффективность метода сортировки. Буду разбираться на досуге.

P.S. метод sort я объявил как статик, чтобы была возможность использовать его в методе main.
PM MAIL   Вверх
Mirkes
Дата 19.10.2012, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Цитата(brave @  18.10.2012,  15:02 Найти цитируемый пост)
P.S. метод sort я объявил как статик, чтобы была возможность использовать его в методе main. 

Согласен, недосмотрел smile 
А анализ методов сортировки лучше изучать по литературе, а не по моим наброскам.


--------------------
Mirkes
PM MAIL   Вверх
VSB
Дата 20.10.2012, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 113
Регистрация: 23.8.2007

Репутация: нет
Всего: 2



А если использовать стандартную сортировку слиянием?
Код

static void sort()
{
    Collections.Sort(catalog, new Comparator<Purchase>()
        {
            @Override
            public int compare(Purchase o1, Purchase o2)
            {
                return o1.getDate().compareTo(o2,getDate());
            }
        }
    );
}

PM MAIL   Вверх
brave
Дата 22.10.2012, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 7.3.2010

Репутация: нет
Всего: нет



Да, действительно.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0958 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.