Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]"problem plecakowy" - usprawnienie kodu
Forum PHP.pl > Forum > Przedszkole
mike287
Cześć,
dostałem zadanie ostatnio do rozwiązania tzw. "problem plecakowy", poniżej zamieszczam kod. Usłyszałem że jest zbyt mało obiektowy... czy macie jakieś wskazówki co można poprawić, albo jak do tego podejść ?
Chodzi mi o jakieś wskazówki, bo patrze na to i nie wiem co mam rozumieć przez za mało obiektowy kod...

informacje o przedmiotach jakie mam "wsadzic do plecaka zaciagam z pliku csv, gdzie w pierwszym wierszu sa nazwy kolumn, ktorych nie potrzebuje wiec dlatego napisane jest w kodzie tak by to pominąć.

  1.  
  2. <?php
  3.  
  4. class BagTask
  5. {
  6. private $arr;
  7. private $count;
  8. private $finalArr = [];
  9. private $weight;
  10. private $bagArr;
  11.  
  12. public function __construct($arr, $weight)
  13. {
  14. $this->arr = file($arr);
  15. $this->weight = $weight;
  16.  
  17. $this->countOfItemsInArray();
  18. $this->prepareArray();
  19. $this->changeKeyNames();
  20. $this->sort();
  21. $this->toBag();
  22. $this->summary();
  23. $this->showBag();
  24.  
  25. // var_dump($this->bagArr);
  26. }
  27.  
  28. /**
  29.  * Metoda countOfItemsInArray zwraca ilosc wierszy w tablyc arr (tam są przedtrzymywane dane z pliku csv)
  30.  */
  31.  
  32. public function countOfItemsInArray()
  33. {
  34. $this->count = count($this->arr);
  35. return $this->count;
  36. }
  37.  
  38. /**
  39.  * Metoda prepareArray tworzy tablice finalArr, wyrzuca "," między elementami i tworzy nowy wspólczynnik waga/wartość na 3 pozycji.
  40.  */
  41. public function prepareArray()
  42. {
  43.  
  44. $partArr = [];
  45. $finalArr = [];
  46.  
  47. for($i = 1; $i < $this->countOfItemsInArray(); $i++)
  48. {
  49. array_push($partArr, explode(",", $this->arr[$i]));
  50. array_push($finalArr, $partArr[$i-1]);
  51.  
  52. array_push($finalArr[$i-1], $partArr[$i-1][2] / $partArr[$i-1][1]);
  53.  
  54. }
  55. return $this->finalArr = $finalArr;
  56. }
  57.  
  58. /**
  59.  * Metoda changeKeyNames nadaje kluczom nazwy, zamiast liczb.
  60.  */
  61. public function changeKeyNames(){
  62.  
  63. $this->finalArr = array_map(function($arr) {
  64.  
  65. return array(
  66. 'id' => $arr[0],
  67. 'weight' => $arr[1],
  68. 'value' => $arr[2],
  69. 'W/V' => $arr[3]
  70. );
  71. }, $this->finalArr);
  72.  
  73. }
  74.  
  75. /**
  76.  * Metoda sort sortuje tablice tablic po współczynniku W/V od największego.
  77.  */
  78. public function sort(){
  79.  
  80. usort($this->finalArr, function ($item1, $item2) {
  81. if ($item1['W/V'] == $item2['W/V']) return 0;
  82. return $item1['W/V'] > $item2['W/V'] ? -1 : 1;
  83. });
  84.  
  85. }
  86.  
  87. /**
  88.  * Metoda toBag uzupełnia tablice plecaka pobierając z posegregowanej tablicy finalArr elementy
  89.  * na wejściu sprawdzając wagę elementu i zestawia ją z limitem jaki pozostał.
  90.  */
  91. public function toBag()
  92. {
  93. $bagLimit = 0;
  94. $bagArr = [];
  95. for ($i = 0; $i < $this->countOfItemsInArray()-1; $i++)
  96. {
  97. if($this->finalArr[$i]['weight'] <= $this->weight)
  98. {
  99. $bagLimit += $this->finalArr[$i]['weight'];
  100.  
  101. if ($bagLimit <= $this->weight)
  102. {
  103. array_push($bagArr, $this->finalArr[$i]);
  104. }
  105. }
  106. }
  107.  
  108. return $this->bagArr = $bagArr;
  109. }
  110.  
  111. /**
  112.  * Metoda countOfItemsInTheBag, podaje ilość elementów wsadzonych do plecaka
  113.  */
  114.  
  115. public function countOfItemsInTheBag()
  116. {
  117. $countOfItemsInTheBag = count($this->bagArr);
  118.  
  119. return $countOfItemsInTheBag;
  120. }
  121.  
  122. /**
  123.  * Metoda weightOfBag, zwraca wagę plecaka
  124.  */
  125.  
  126. public function weightOfBag()
  127. {
  128. $weight = 0;
  129. foreach ($this->bagArr as $key)
  130. {
  131. $weight += $key['weight'];
  132. }
  133. return $weight;
  134. }
  135.  
  136. /**
  137.  * Metoda valueOfBag, zwraca wartość plecaka
  138.  */
  139. public function valueOfBag()
  140. {
  141. $value = 0;
  142. foreach ($this->bagArr as $key)
  143. {
  144. $value += $key['value'];
  145. }
  146. return $value;
  147. }
  148.  
  149. /**
  150.  * Metoda showBag, zwraca informacje wyjściowe na temat plecaka
  151.  */
  152. public function showBag()
  153. {
  154. $i = 0;
  155. foreach ($this->bagArr as $value)
  156. { $i++;
  157.  
  158. echo "przedmiot ".$i." o id ".$value['id']." jego waga - ".$value['weight']." wartość to ".$value['value']."<br>";
  159.  
  160. }
  161. }
  162.  
  163. /**
  164.  * Metoda summary, wyświetla informacje na temat przedmiotów w plecaku
  165.  */
  166. public function summary()
  167. {
  168. echo "liczba elementów znajdujących się w plecaku to ".$this->countOfItemsInTheBag()."<br>";
  169. echo "limit plecaka = ".$this->weight."<br>";
  170. echo "wykorzystana waga plecaka = ".$this->weightOfBag()."<br>";
  171. echo "całkowita wartość plecaka = ".$this->valueOfBag()."<br>";
  172.  
  173. }
  174.  
  175. }
  176.  
  177. $bag = new BagTask('csvArray.csv', 1);
  178.  
Tomplus
Swoją drogą, problem plecakowy dotyczy bardziej pojemności kontenerów, a nie ilości przedmiotów w kontenerze.

Ja w takich przypadkach posługuję się gotową klasą:
https://github.com/dvdoug/BoxPacker
mike287
zastanawia mnie co w tym kodzie jest takiego ze jest "zbyt mało obiektowy", widzialem tez roznego rodzaju rozwiazania problemu plecakowego, ale napisalem swoj i chcialem sie poradzic co tu mozna zmienic zeby byl lepszy
rad11
Poczytaj o https://pl.m.wikipedia.org/wiki/SOLID_(prog...anie_obiektowe) te wiadomosci napewno pozwola Ci zrobic z Twojego kodu bardziej obiektowy
emillo91
Możliwe, że chodzi tutaj o dużą ilość pętli. Na przykład metoda toBag mogłaby być od razu implementowana w metodzie countOfItemsInTheBag(). Wszystko wyświetlasz w konstruktorze i może o to chodzi.
markuz
Masz 1 klasę a na szybko narzucają się przynajmniej 2 - Bag, Element (chociaż nazwa element jest trochę za ogólna i przydało by się ją skrócić do konkretnego problemu np. Apple jeżeli w Bag możemy trzymać tylko jabłka, ew. przedmiot).

W konstruktorze jako arr podajesz nazwę pliku CSV - czyli przy zmianie sposobu wczytywaniu danych trzeba zmieniać twoją klasę - tam mógłby być jakiś interfejs np. Source + implementacja Source z CSV np. CSVSource dzięki czemu masz już 4 klasy.

Co tam robi zakomentowany var_dump?
Dlaczego nie używasz PHP 7.1?

Nie ma żadnego wyjątku a jak np. bag się przepełni to powinien zostać rzucony wyjątek.

Patrząc na wnętrze konstruktora już wiadomo, że ten kod coś nie halo wink.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.