# Clock angle problem in Java

Some time ago I ran into the following interview question:

Write a program that for a given hour and minutes values calculates an angle in degrees between the hour and the minute hands. Return information whether the minute hand overlaps the hour hand. As an additional subtask, write a method for calculating all times when the minute hand overlaps the hour hand.

This kind of problem is not very complicated; however, it is not very easy either. Even if you fail to resolve it correctly, the approach to a solution gives an interviewer lots of knowledge on your ability to deal with problem-solving tasks.

The following steps help you correctly approach many different problems. You can use it as a framework, especially during interviews.

1. Write down all the known facts.
2. Draw a few examples with real values to spot some common patterns.
3. Pay attention to some edge cases like minimum or maximum values, negative or zero numbers; nullable objects etc. Note that each problem will have a different set of edge cases.

## Calculate an angle between the hour and the minute hands

First I will write down all the known facts and highlight the most important details. Highlighting will help you not to miss any significant information.

• The clock is round, so the maximum angle for both hours and minutes is 360°, starting at 12 o’clock.
• The clock face has only 12 hours, so for any 24-hour time, we will have to reduce an hour to 12-hour format. The reduction will not have any impact on the angle value. The best way to achieve the modification is to use the modulo operation, which will also work with the 12-hour format. That will give us hour values from 0 (for 12 AM or 12 PM) to 11.
• There are 12 hours on the clock so 360° divided by 12 hours gives 30° per hour.
• There are 60 minutes on the clock so 360° divided by 60 minutes gives 6° per minute.
• The difference between two adjacent minutes is 6 degree. That indicates seconds change impacts the minute hand angle. Note that from time to time you may be asked to add seconds to the angle equations. Otherwise, you may assume the seconds’ value is 0. I present solution with the seconds included in the angle equations. However, you should be able to easily remove the seconds if asked to present a simplified solution (hours and minutes values only). So the minute hand moves an extra 0.1° per second (6° divided by 60 seconds).
• Minutes change impacts the hour hand. But how much the hand will turn with every minute? The angle between two adjacent hours is 30°. The hour hand turns 30° in 60 minutes, so 30° divided by 60 minutes gives us 0.5° per minute for an additional hour hand movement.
• Note that the minute hand depends on seconds value, and so the hour hand. However, the second value has a very marginal impact on the hour hand; hence, I do not take seconds into account in the hour hand angle calculations.

Now, once we have all the facts written down, we can build our formulas. We will do it in pseudocode first, and later I present an example in Java.

Algorithm clock angles : input: h - hour value, m - minutes value, s - seconds value, output: a - angle value

\begin{aligned} h &\gets h\mod 12 \\ m_{angle} &\gets 6 \times m + 0.1 \times s \\ h_{angle} &\gets 30 \times h + 0.5 \times m \\ a &\gets h_{angle} - m_{angle} \end{aligned}

Let’s perform some checks

Time (H:MM)Angle (°)Correct
3:0090°Yes
6:00180°Yes
9:00270°Yes
1:50-245°No

As you can see, we have a problem with 1:50 because of the way we calculate angle difference. To fix that we need to take the difference between 360° and the absolute value of that negative value angle (in our case 360° - |-245°| => 115°). This operation will not have any impact on angle value whatsoever but will help us to get the correct numerical value. After calculations amendments, our algorithm will look as follows:

Algorithm clock angles : input: hour value h, minutes value m, output: angle value a

\begin{aligned} h &\gets h\mod 12 \\ m_{angle} &\gets 6 \times m + 0.1 \times s \\ h_{angle} &\gets 30 \times h + 0.5 \times m \\ a &\gets h_{angle} - m_{angle} \\ a &\gets \begin{cases} \displaystyle 360 - |a| &\text{if } a \lt 0 \\ \displaystyle a &\text{otherwise} \end{cases} \end{aligned}

Now, let’s focus on the overlapping problem. The minute hand overlaps the hour hand when both hands are having the same direction (angle). So, when the angle between the minute and hour hands is 0, the minute hand overlaps the hour hand.

This is a sample class implementing the algorithm in Java.

public class ClockAngle {

private static final double HOUR_ANGLE = 360.0 / 12;
private static final double MINUTE_ANGLE = 360.0 / 60;
private static final double HOUR_DELTA_ANGLE = HOUR_ANGLE / 60;
private static final double MINUTE_DELTA_ANGLE = MINUTE_ANGLE / 60;

private final int angle;
private final int hourAngle;
private final int minAngle;

public ClockAngle(final int hour, final int min) {
this(hour, min, 0);
}

public ClockAngle(final int hour, final int min, final int sec) {

if (hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 59) {
throw new IllegalArgumentException("Invalid hours, minutes or seconds value");
}

this.minAngle = (int) (min * MINUTE_ANGLE + MINUTE_DELTA_ANGLE * sec);
this.hourAngle = (int) (hour % 12 * HOUR_ANGLE + HOUR_DELTA_ANGLE * min);

int angle = hourAngle - minAngle;

if (angle < 0) {
angle = 360 + angle;
}

this.angle = angle;
}

public int getHourAngle() { return hourAngle; }

public int getMinAngle() { return minAngle; }

/** @return angle in degrees from the minute to the hour hand */
public int getMinHourAngle() { return this.angle; }

/** @return angle in degrees from the hour to the minute hand */
public int getHourMinAngle() { return 360 - this.angle; }

/** @return {@code true} if the minute hand is on top of the hour hand; otherwise {@code false} */
public boolean isMinOverHour() { return this.angle == 0; }
}


## Finding out all times when the minute hand overlaps the hour hand

From the above example, we know that the minute angle must be equal to the hour angle. From the above equations, we will create a formula showing the dependency of minutes on hours. Then iterating through hour values (0 through 11) we will get minute value.

Let’s use variables from our algorithm mentioned above (h for an hour and m for a minute). As we use hour values from 0 .. 11 we do not have to use hours mod 12 any more. Another thing to mention is that I removed seconds from the equations. The second value is calculated later on from the minute fraction value.

\begin{aligned} h_{angle} &= m_{angle} \\ \Rightarrow 30 \times h + 0.5 \times m &= 6 \times m \\ \Rightarrow 5.5 \times m &= 30 \times h \\ \Rightarrow m &\thickapprox 5.45 \times h \end{aligned}

A sample implementation in Java. Note the CONST variable 30 / 5.5 calculation value instead of 5.45 for better accuracy.

public Collection<LocalTime> overlaps() {

final double CONST = 30 / 5.5;
final List<LocalTime> times = new ArrayList<>(11);

for (int h = 0; h < 12; h++) {
final double m = CONST * h;
final int s = (int) Math.round((m - (int) m) * 60);

if (s == 60) continue;

times.add(LocalTime.of(h, (int) m, s));
}

return times;
}


Let’s calculate all overlapping hour and minute pairs. As mentioned above, in the calculations we get fractions of minutes. The fractions are nothing but seconds. You get seconds value by multiplying 60 seconds and a fraction value, e.g. case for 3 o’clock and 16 minutes, the fraction is 0.36 which gives 0.36 * 60 seconds is around 22 seconds.

HourMinuteSecond
000
1527
21055
31622
42149
52716
63244
73811
84338
9495
105433

## Conclusions

I presented this problem and its potential solution purely for learning purposes. You should go through this and do as many calculations and tasks on your own as you can. Learning different solutions by heart is never a good idea. It is straightforward to notice that you “read from your memory” rather than solving the problem. Note that “correctness” of your solution is not that important as the approach your take and your ability to deal with problem-solving tasks.

I hope that this post will help you to improve your skills and hopefully give you a change of finding a better job or getting a better position.

Enjoy coding!