14

There was a question asked in an interview:

In a Formula-1 challenge, there are n teams numbered 1 to n. Each team has a car and a driver. Car’s specification are as follows:

  • Top speed: (150 + 10 * i) km per hour
  • Acceleration: (2 * i) meter per second square.
  • Handling factor (hf) = 0.8
  • Nitro : Increases the speed to double or top speed, whichever is less. Can be used only once.

Here i is the team number. The cars line up for the race. The start line for (i + 1)th car is 200 * i meters behind the ith car.

All of them start at the same time and try to attain their top speed. A re-assessment of the positions is done every 2 seconds(So even if the car has crossed the finish line in between, you’ll get to know after 2 seconds). During this assessment, each driver checks if there is any car within 10 meters of his car, his speed reduces to: hf * (speed at that moment). Also, if the driver notices that he is the last one on the race, he uses ‘nitro’.

Taking the number of teams and length of track as the input, calculate the final speeds and the corresponding completion times.

I don't understand how to approach this kind of problems. For each instance should I be checking all C(n,2) combinations of every pair of drivers and compute the result? But how can I figure out at what instance I should make the calculations?

medvedev1088
  • 3,645
  • 24
  • 42
Alex
  • 1,178
  • 3
  • 9
  • 24
  • 1
    i'm not sure, but if i have got your question , i think you have to implemented in "client-server" model.you have a server which is responsible for holding the match.clients are cars(teams).at each step clients tell the server their information,and server store it.and they can access to all other cars informations.so at each step they receive the a complete list of cars and their info.so they can find out if there are cars within 10 meters with time of O(n).just like real Formula 1 which shows all drivers rankings and the place they are on the screen! – Iman Mirzadeh May 16 '15 at 08:22

2 Answers2

8

If you check the Conway's Game of Life you will find that there is a lot in common with the Race Problem.

Here is the analogy:

  • The initial state (the seed of the system):
    • Game of Life: initial pattern on the grid. Every cell having the following parameters:
      • x and y coordinate
      • whether the cell is alive or dead
    • Race Problem: n cars each one having predetermined parameters and the length of the track l. Every car has the following parameters:
      • top speed
      • acceleration
      • handling factor
      • position on track
      • current speed
  • The rules are applied at discrete moments which are called ticks.
    • Game of Life: the rules are applied simultaneously to every cell from the previous generation producing a next generation. Each generation is a pure function of the preceding one.
    • Race Problem: the rules are applied simultaneously to every car from the previous state producing a next state. This happens every 2 seconds. Same as in Game of Life each step is a pure function of the preceding one which means that it only depends on the parameters of the cars from the previous state.

What's different is that the Game of Life never ends whereas the Race Problem should terminate when the current position of every car is greater or equal to the track length l (Although the last statement is arguable: due to the handling factor it's possible that in some conditions some cars will never reach the finish line).

The key point is that calculations are done at discrete moments which answers your question:

But how can I figure out at what instance I should make the calculations?

You can take the idea from the Algorithms section to solve this problem. You need to have 2 arrays of cars: one representing the current state and the other representing the next step. On each iteration you recalculate the current position and the speed of every car following the rules from the assignment and check whether the loop should terminate. Before the next iteration you swap the array roles so that the successor array in the last iteration becomes the current array in the next iteration.

The high level pseudo-code may look like this:

n = ..; // initial number of cars
l = ..; // track length
Car[] currentState = initializeState(n, l);
Car[] nextState = clone(currentState);
for (int iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
    calculateNextState(currentState, nextState, iteration);
    swap(currentState, nextState);
    if (shouldTerminate(currentState, l) {
        break;
    }
}

printResultOrClaimNotTerminated(currentState);

The rules are applied in the calculateNextState(..) function. In the most naive implementation you check every pair of cars which gives you

O (C(n, 2)) = O (n * (n - 1) / 2) = O (n ^ 2)

complexity for each iteration. However you can think of possible optimizations here. For example you can sort the cars by current position first (O (n * log(n))) and then traverse the sorted array checking only adjacent cars (O (2 * n)). You can do this since if the 10 meters condition doesn't satisfy for adjacent cars it won't satisfy for non-adjacent cars. This will give you the resulting complexity of:

O (n * log(n))

which is much better. The sorted array of cars will naturally give you the car with last position to which you need to apply the nitro boost rule. Probably there can be other optimizations. This answers your question:

For each instance should I be checking all C(n,2) combinations of every pair of drivers and compute the result?

medvedev1088
  • 3,645
  • 24
  • 42
0

Car Objects And Game Object

I assume that you have created the necessary objects for the car, encapsulated within a game object.

Ideas to Speed up each update step to not do all C(n,2) checks

You can speed up the update position and parameters step, by not having to check all C(n,2) combinations. One simple heuristic you can use is that we don't need to check interactions between cars that are far away. For example a car in the first quarter of the race track will not interact with a car in third quarter of the race track. I think based on the parameters of your question, you want to divide up the race track into 10m long sections. Maintain an list for each section and keep track of all the cars in each section. After updating positions, check for interaction between cars in consecutive sections only.

Similarly, keep track of which car is in the last position on each update step and toggle the nitrobooster accordingly.

Choice of TimeStep

In your question the timeStep seems to be fixed at 2 seconds. However in a general setting when you are coding a game for example, this choice is a crucial one. You can play around with a few different numbers (10,50,100,500 milliseconds for example).

If you choose the timeStep to be a higher number, (for example) the car may pass through another car and avoid detection of collision. If on the other hand you choose the timeStep to be too small, and if time taken for the operations is larger than the timeStep, the game will run slower than real time.

Community
  • 1
  • 1
ConfusedMan
  • 562
  • 1
  • 4
  • 12