Guest User

Untitled

a guest
Jun 21st, 2018
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.96 KB | None | 0 0
  1. // Slurp Developer Assignment
  2.  
  3. /*
  4. This file contains the following sections:
  5. 1. Util functions
  6. 2. Classes
  7. 3. Main functions
  8. */
  9.  
  10. // ----------------------------------------------------------------------------
  11. // UTILS
  12.  
  13. // Make a 2d array with dim rows and columns, with all values init to 0
  14. function generateZeroHeightArray(dim) {
  15. var arr = new Array(dim);
  16. for (let i = 0; i < dim; i++) {
  17. row = new Array(dim);
  18. for (let j = 0; j < dim; j++) { row[j] = 0; }
  19. arr[i] = row;
  20. }
  21. return arr;
  22. }
  23.  
  24. // ** Used to verify results in testing **
  25. // Print the 2d array nicely
  26. function printArray(arr, size) {
  27. let arrStr = ""
  28. for (let i = 0; i < size; i++) {
  29. let rowStr = ""
  30. for (let j = 0; j < size; j++) {
  31. rowStr += arr[i][j] + " "
  32. }
  33. arrStr = rowStr + "\n" + arrStr
  34. }
  35. console.log(arrStr)
  36. }
  37.  
  38. // Create array of all 6 permutations of the 3 elements
  39. function permutations(a, b, c) {
  40. return [[a, b, c], [a, c, b], [b, a, c], [b, c, a], [c, a, b], [c, b, a]];
  41. }
  42.  
  43.  
  44.  
  45. // ----------------------------------------------------------------------------
  46. // CLASSES
  47.  
  48. class Bag {
  49. constructor(x, y, z) {
  50. this.x = x;
  51. this.y = y;
  52. this.z = z;
  53. }
  54. getX() { return this.x; }
  55. getY() { return this.y; }
  56. getZ() { return this.z; }
  57. getVolume() { return this.x * this.y * this.z; }
  58.  
  59. // return array of all possible orientations of a bag with the given dimensions
  60. static allBags(x, y, z) {
  61. const perms = permutations(x, y, z);
  62. let bags = []
  63. for (let perm of perms) {
  64. bags = bags.concat(new Bag(perm[0], perm[1], perm[2]));
  65. }
  66. return bags;
  67. }
  68. }
  69.  
  70. class Box {
  71. /* Instance variables:
  72. dimension : the side length of this Box in centimeters
  73. heights : a 2D array of integers representing a top view of the bags
  74. in this Box, with each value representing the total height of
  75. stacked Bags at that 1cm by 1cm location. */
  76. constructor(dimension) {
  77. this.dimension = dimension;
  78. this.heights = generateZeroHeightArray(dimension);
  79. }
  80.  
  81. // Given an array with the 6 possible x-y-z orientations of a coffee bag,
  82. // determine if the bag will fit in this Box. If so, add it to this box.
  83. // If not, return false to indicate that the bag does not fit.
  84. // @bags -- an array of Bag objects with dimensions in different orientations
  85. addBag(bags) {
  86. // add the bag at the first x,y,z location it will fit in
  87. for (let row = 0; row < this.dimension; row++) { // row idx is x position
  88. for (let col = 0; col < this.dimension; col++) { // col idx is y position
  89. let height = this.heights[row][col];
  90. // try adding the bag at different orientations until it fits
  91. for (let bag of bags) {
  92. if (this.doesBagFit(bag, row, col, height)) {
  93. this.updateHeights(row + bag.getX(), col + bag.getY(), height + bag.getZ());
  94. return true;
  95. }
  96. }
  97. }
  98. }
  99. return false;
  100. }
  101.  
  102. // Does the bag fit in this box if placed at the given x,y,z location?
  103. // @bag -- a Bag
  104. // @x, @y, @z -- location coordinates in the box (in centimenters)
  105. doesBagFit(bag, x, y, z) {
  106. let xFits = (x + bag.getX()) <= this.dimension;
  107. let yFits = (y + bag.getY()) <= this.dimension;
  108. let zFits = (z + bag.getZ()) <= this.dimension;
  109. return xFits && yFits && zFits;
  110. }
  111.  
  112. // From 0,0 to x,y, set all heights in the array to at least
  113. // as tall as height.
  114. // @x, @y -- location coordinates in the box (in cm)
  115. // @height -- the new height
  116. updateHeights(x, y, height) {
  117. for (let i = 0; i < x; i++) {
  118. for (let j = 0; j < y; j++) {
  119. this.heights[i][j] = Math.max(height, this.heights[i][j]);
  120. }
  121. }
  122. }
  123.  
  124. // ** This function is just for use in testing. **
  125. // Calculate the volume of this box that is recorded as occupied
  126. // in the heights array. (sums all numbers in the array)
  127. getOccupiedVolume() {
  128. /* outerReducer: combine the sums of each inner array in the 2d array */
  129. const outerReducer = (totalVolume, row) => ( row.reduce(innerReducer,0) + totalVolume )
  130. /* innerReducer: add all the numbers in an array */
  131. const innerReducer = (totalVol, cell) => ( cell + totalVol )
  132. return this.heights.reduce(outerReducer,0);
  133. }
  134. }
  135.  
  136.  
  137.  
  138. // ----------------------------------------------------------------------------
  139. // MAIN FUNCTIONS
  140.  
  141. // CONSTANTS -- The bags
  142. // Arrays of bags in all 6 orientations
  143. const smallBags = Bag.allBags(23, 16, 2);
  144. const medBags = Bag.allBags(26, 22, 2);
  145. const largeBags = Bag.allBags(26, 14, 10);
  146.  
  147. // Use this function to run the program.
  148. // Validates inputs then runs the algorithm.
  149. // int, int, int, int => int
  150. function main(small, med, large, boxDimension) {
  151. let errorMsg = validateArgs(small, med, large, boxDimension);
  152. if (errorMsg !== false) {
  153. return "Invalid input: " + errorMsg;
  154. } else {
  155. return packBoxes(small, med, large, boxDimension).length;
  156. }
  157. }
  158.  
  159. // given quantities of each size of bag and the size of the box,
  160. // determine # of boxes needed to hold all bags
  161. // int, int, int, int => array of Box
  162. function packBoxes(small, med, large, boxDimension) {
  163. var boxes = []
  164. // add the large bags
  165. for (var i = 0; i < large; i++) {
  166. boxes = addBagToBoxes(largeBags, boxes, boxDimension)
  167. }
  168. // add the medium bags
  169. for (var i = 0; i < med; i++) {
  170. boxes = addBagToBoxes(medBags, boxes, boxDimension)
  171. }
  172. // add the small bags
  173. for (var i = 0; i < small; i++) {
  174. boxes = addBagToBoxes(smallBags, boxes, boxDimension)
  175. }
  176. return boxes;
  177. }
  178.  
  179. // ** Helper function for packBoxes **
  180. // Try to fit the bag into some box in the box array.
  181. // If it fits in none, make new box and add it to array.
  182. // Return the array of boxes that contains the bag
  183. function addBagToBoxes(bags, boxes, boxDimension) {
  184. for (let box of boxes) {
  185. if (box.addBag(bags)) {
  186. return boxes;
  187. }
  188. }
  189. // add new box for the bag if it didn't fit in any existing box
  190. var anotherBox = new Box(boxDimension);
  191. anotherBox.addBag(bags);
  192. return boxes.concat(anotherBox);
  193. }
  194.  
  195. // ** Helper function for main function **
  196. // Validate program arguments + argument types
  197. function validateArgs(small, med, large, boxDimension) {
  198. let errorMsg = false;
  199. if (!Number.isInteger(parseInt(small))) {
  200. errorMsg = "non-integer argument: " + small + " (" + typeof small + ")";
  201. } else if (!Number.isInteger(parseInt(med))) {
  202. errorMsg = "non-integer argument: " + med + " (" + typeof med + ")";
  203. } else if (!Number.isInteger(parseInt(large))) {
  204. errorMsg = "non-integer argument: " + large + " (" + typeof large + ")";
  205. } else if (!Number.isInteger(parseInt(boxDimension))) {
  206. errorMsg = "non-integer argument: " + boxDimension + " (" + typeof boxDimension + ")";
  207. } else if (small < 0) {
  208. errorMsg = "number of 200g bags is less than 0: " + small;
  209. } else if (med < 0) {
  210. errorMsg = "number of 400g bags is less than 0: " + med;
  211. } else if (large < 0) {
  212. errorMsg = "number of 1000g bags is less than 0: " + large;
  213. } else if (!(boxDimension >= 30 && boxDimension <= 100)) {
  214. errorMsg = "box dimension is not between 30 and 100 cm: " + boxDimension;
  215. }
  216. return errorMsg;
  217. }
Add Comment
Please, Sign In to add comment