Тестовое задание про оптимальный розлив варенья по банкам
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
5.0KB

  1. <template>
  2. <div v-if="isProcessing" class="progress">
  3. <progress>Разливаем...</progress>
  4. </div>
  5. <div v-else>
  6. <h2 v-if="result.state == 'error'" class="error">
  7. {{ result.message }}
  8. </h2>
  9. <div v-for="jam in jams" :key="jam.id">
  10. <h3>
  11. Варенье: {{ jam.id }}, всего сварено: {{ jam.vol }} мл,
  12. <span v-if="jam.restVol > 0" class="error"
  13. >осталось не розлито: {{ jam.restVol }} мл</span
  14. >
  15. <span v-else>розлито полностью</span>
  16. </h3>
  17. <ul>
  18. <li v-for="pot in jam.pots" :key="pot.id">
  19. <span
  20. >Банка <b>{{ pot.id }}</b> ({{ pot.vol }} мл)</span
  21. >
  22. &mdash;
  23. <span> залито {{ pot.jamVol }} мл</span>
  24. &mdash;
  25. <span v-if="pot.isFull"> полная</span>
  26. <b v-else class="error">
  27. недолив {{ pot.vol - pot.jamVol }} мл</b
  28. >
  29. </li>
  30. </ul>
  31. </div>
  32. <div v-if="emptyPots.length > 0">
  33. <hr>
  34. <h4>Остались пустые банки:</h4>
  35. <ul>
  36. <li v-for="pot in emptyPots" :key="pot.id">
  37. <b>{{ pot.id }}</b> ({{ pot.vol }} мл)
  38. </li>
  39. </ul>
  40. </div>
  41. </div>
  42. </template>
  43. <script>
  44. import { _ } from "vue-underscore";
  45. export default {
  46. props: ["propPots", "propJams"],
  47. data() {
  48. return {
  49. isProcessing: false,
  50. pots: [],
  51. jams: [],
  52. result: { state: "initial" },
  53. };
  54. },
  55. mounted: function () {
  56. this.isProcessing = true;
  57. this.pots = _.map(this.propPots, _.clone);
  58. this.jams = _.map(this.propJams, _.clone);
  59. this.result = fillPots(this.pots, this.jams);
  60. // console.log("result", this.result);
  61. // console.log("jams", this.jams);
  62. this.isProcessing = false;
  63. },
  64. computed: {
  65. emptyPots: function () {
  66. return this.pots.filter((p) => p.jamVol === 0);
  67. },
  68. },
  69. };
  70. function fillPots(pots, jams) {
  71. prepare(pots, jams);
  72. // Сперва попытаемся разлить варенья по банкам, заполняя их по максимуму
  73. // Приоритет отдаем самым большим банкам, чтобы не лазать в погреб лишний раз
  74. let isDone = false;
  75. let isFoundSolution;
  76. do {
  77. isFoundSolution = false;
  78. for (const jam of jams) {
  79. for (const pot of pots) {
  80. if (!pot.isFilled && pot.vol <= jam.restVol) {
  81. pot.jamId = jam.id;
  82. pot.jamVol = Math.min(pot.vol, jam.restVol);
  83. pot.isFilled = true;
  84. pot.isFull = true;
  85. jam.restVol -= pot.vol;
  86. jam.pots.push(pot);
  87. isFoundSolution = true;
  88. break;
  89. }
  90. }
  91. }
  92. } while (!isDone && isFoundSolution);
  93. // А теперь разливаем остатки по самым маленьким из оставшихся банок
  94. isDone = true;
  95. for (const jam of jams) {
  96. if (jam.restVol > 0) {
  97. for (let i = pots.length - 1; i > 0; i--) {
  98. if (!pots[i].isFilled && pots[i].vol >= jam.restVol) {
  99. pots[i].jamId = jam.id;
  100. pots[i].jamVol = jam.restVol;
  101. pots[i].isFilled = true;
  102. pots[i].isFull = pots[i].vol === jam.restVol;
  103. jam.restVol = 0;
  104. jam.pots.push(pots[i]);
  105. break;
  106. }
  107. }
  108. if (jam.restVol !== 0) {
  109. isDone = false;
  110. }
  111. }
  112. }
  113. if (!isDone) {
  114. return {
  115. state: "error",
  116. message: "Не удалось разлить варенья",
  117. };
  118. }
  119. return { state: "success" };
  120. function prepare(pots, jams) {
  121. pots.sort(sortByVolDesc);
  122. jams.sort(sortByVolDesc);
  123. for (const pot of pots) {
  124. pot.isFilled = false;
  125. pot.isFull = false;
  126. pot.jamId = null;
  127. pot.jamVol = 0;
  128. }
  129. for (const jam of jams) {
  130. jam.restVol = jam.vol;
  131. jam.pots = [];
  132. }
  133. function sortByVolDesc(a, b) {
  134. if (a.vol > b.vol) {
  135. return -1;
  136. } else if (a.vol < b.vol) {
  137. return 1;
  138. }
  139. return 0;
  140. }
  141. }
  142. }
  143. </script>
  144. <style lang="scss" scoped>
  145. .progress {
  146. height: 100%;
  147. display: flex;
  148. align-items: center;
  149. progress {
  150. width: 100%;
  151. }
  152. }
  153. .error {
  154. color: orangered;
  155. }
  156. </style>