Level 4 question from the Google foobar challenge (one of my favorite questions from the challenge).
How many ways can you hit a guard with a laser without hitting your-self?
===============================

Uh-oh - you've been cornered by one of Commander Lambdas elite guards! Fortunately, you grabbed a beam weapon from an abandoned guard post while you were running through

the station, so you have a chance to fight your way out. But the beam weapon is potentially dangerous to you as well as to the elite guard: its beams reflect off walls, meaning you'll have to be very careful where you shoot to avoid bouncing a shot toward yourself!

Luckily, the beams can only travel a certain maximum distance before becoming too weak to cause damage. You also know that if a beam hits a corner, it will bounce back in exactly the same direction. And of course, if the beam hits either you or the guard, it will stop immediately (albeit painfully).

Write a function solution(dimensions, your_position, guard_position, distance) that gives an array of 2 integers of the width and height of the room, an array of 2 integers of your x and y coordinates in the room, an array of 2 integers of the guard's x and y coordinates in the room, and returns an integer of the number of distinct directions that you can fire to hit the elite guard, given the maximum distance that the beam can travel.

The room has integer dimensions [1 < x_dim <= 1250, 1 < y_dim <= 1250]. You and the elite guard are both positioned on the integer lattice at different distinct positions (x, y) inside the room such that [0 < x < x_dim, 0 < y < y_dim]. Finally, the maximum distance that the beam can travel before becoming harmless will be given as an integer 1 < distance <= 10000.

For example, if you and the elite guard were positioned in a room with dimensions [3, 2], your_position [1, 1], guard_position [2, 1], and a maximum shot distance of 4, you could shoot in seven different directions to hit the elite guard (given as vector bearings from your location): [1, 0], [1, 2], [1, -2], [3, 2], [3, -2], [-3, 2], and [-3, -2]. As specific examples, the shot at bearing [1, 0] is the straight line horizontal shot of distance 1, the shot at bearing [-3, -2] bounces off the left wall and then the bottom wall before hitting the elite guard with a total shot distance of sqrt(13), and the shot at bearing [1, 2] bounces off just the top wall before hitting the elite guard with a total shot distance of sqrt(5).


Test cases
==========
Your code should pass the following test cases.
Note that it may also be run against hidden test cases not shown here.

-- Python cases --
Input:
solution.solution([3,2], [1,1], [2,1], 4)
Output:
  7

Input:
solution.solution([300,275], [150,150], [185,100], 500)
Output:
  9

Analysis:
Let us work with the given example in this problem:
Room Size [3, 2]; Player Location [1, 1]; Guard Location [2, 1] and a distance 4 units.

My first idea was to set a fix general coordinate system and calculate the new angle each time the laser bounced off the wall. Unfortunately I ran into a few problems with this idea, mainly that there can be an infinite amount of angles that you can shoot in.

The other approach is to mirror the room in question, to determine the possible locations of each guard and whether we can shoot him. This is the method that we will use.

O = Player Position; X = Guard position
Figure 1.

Figure 2. shows us that we have mirrored the room along the North wall.
Shooting the guard in the mirrored room is the equivalent of shooting the guard at 63 deg angle and have it bounce off the wall in the same room. [After the first bounce, the laser in the red has the same distance and angle as the laser in the white]

1) Get all the 1st quadrant's Guard + Player positions. (positive x; positive y)

max_x = player_x_position + laser_distance
5 = 1 + 4, the same goes for the y position.
ceil(max_x / room_x)  --> celing(5/3) = 2 
ceil(max_y / room_y)  --> celing(5/2) = 3 
As you can see, we need to perform mirror 3x along the y axis of the room, but only 2x along the x axis. (see Figure 3.)

Figure 2.

2) Reflect the position of all the 1st quadrant to the other 3 quadrants.
A list for each position was generated in the first step :
[x_coords, y_coords, Player = 1 or Guard = 7]

 position_list_first_quadrant = 
          [[1, 1, 1], [2, 1, 7], [2, 3, 7] ..] 

We can simply multiply the x and y by the appropriate sign to get back all the other quadrants
2nd Quadrant : [-1 * x, y]
3rd Quadrant : [-1 * x, -1 * y]
4th Quadrant : [x, -1 * y]

Figure 3.

3) Filter all the Player + Guard positions by distance.
If you feed 2 points into the following formula derived from the Pythagorean theorem, it will give you the distance between them. Filter all possibilities that are !GREATER! (equal is still good) to our laser distance.

$$ distance = \sqrt {(x_2-x_1)^2 +(y_2-y_1)^2}$$

Where: $$ x_1, y_1 $$ are the coordinates of the original player's position. $$ x_2, y_2 $$ are the coordinates of the mirrored player + guards.

In Figure 4 there is a guard in position [2, 5]; and player in position [1, 1].
We can quickly find that the distance between them is ~4.123 > 4.0 , therefore we can quickly eliminate this position from our list.

4) Filter all the Player + Guard positions by angle.
Now let's filter all the player + guards that have the same angle. Remember we can't shoot a guard that is behind a player or another guard, we can only shoot the closest character for each unique angle.

From Wiki: "The function atan2(y,x) is defined as the angle in the Euclidean plane, given in radians, between the positive x axis and the ray to the point (x, y) ≠ (0, 0)."
The atan2 function is available from the math module in python 2.7 standard lib.
For atan(delta_y, delta_x) get the delta value from guard to player to get a unique angle.

If you take a look at Figure 4. you can see that everything behind the guard at [2, 1] is unshootable.

Figure 4.
Conclusion:

In the example we are told that there is 7 ways to shoot the guard : [1, 0], [1, 2], [1, -2], [3, 2], [3, -2], [-3, 2], and [-3, -2].
If we look at figure 4. Starting from the players position then going towards each possible guard, each answers match up with a different guard.