Facebook Careers Puzzle—usrbincrash solution in Ruby
From Facebook’s Job Puzzles page:
You are on a cargo plane full of commercial goods when the pilot announces that the plane is short on fuel. Unless cargo is ejected from the plane, you will run out of fuel and crash. The pilot provides you with the number of pounds of weight that must be ejected from the plane. Fortunately, the manifest of the plane is both completely accurate, digitized, and you are a programmer of some repute. Unfortunately, your boss is going to be extremely unhappy, and wants you to exactly minimize the losses to the absolute minimum possible without crashing the plane. The manifest does not contain the exact quantities of every type of good, because you have so many on board. You may assume that you will not run out of any good in the course of saving the plane. You also realize this kind of program could be handy to others who find themselves in similar situations.
Write a program that takes a single argument on the command line. This argument must be a file name, which contains the input data. The program should output to standard out the minimum losses your boss will incur from your ejection of goods (see below). Your program will be tested against several manifests of several crashing planes; each with different data. Additionally, your program must be fast, and give the correct answer.
This puzzle is interesting in that there are many ways to approach it. It’s a modified Knapsack problem: we are trying to go over a certain weight while minimizing the cost. There is no limit to how many times each object can be used, making the problem easier in terms of complexity.
I originally solved it very quickly using a naive recursive approach. While correct, it was very inefficient and would blow the stack when any large weight was used as input, even if the problem was easy.
My final solution used the following algorithm:
- Sort objects by weight/cost, higher ratios (most efficient) first.
- Delete objects that will never be used, which are those that are less efficient and weigh more than a more efficient object.
- Keep using the most efficient object until you equal or go over the target weight. If you hit it spot on, return the cost.
- If you go over, subtract the weight and recursively repeat the step above with the next most efficient object to determine if less cost can be achieved.
The following solution in Ruby passed the Facebook puzzle robot:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |