Last active
August 29, 2015 14:10
-
-
Save ngzhian/73c61f881116b2f939ec to your computer and use it in GitHub Desktop.
Clock question
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import division | |
from datetime import datetime, time, timedelta | |
import unittest | |
ONE_SECOND = timedelta(seconds=1) | |
HOUR_HAND_DEG_PER_SECOND = 1/120 | |
HOUR_HAND_DEG_PER_MIN = 1/2 | |
HOUR_HAND_DEG_PER_HOUR = 30 | |
MIN_HAND_DEG_PER_SECOND = 1/10 | |
MIN_HAND_DEG_PER_MIN = 6 | |
def simulate_clock(): | |
current_time = datetime(2014, 1, 1, 0, 0, 1) | |
end_time = datetime(2014, 1, 2, 0, 0, 0) | |
total = 0 | |
perpendicular_time = [] | |
while current_time != end_time: | |
current_angle = calculate_angle(current_time) | |
next_time = current_time + ONE_SECOND | |
next_angle = calculate_angle(next_time) | |
if crossed_90_degress(current_angle, next_angle): | |
total = total + 1 | |
perpendicular_time.append( | |
get_time_nearer_to_90(current_time, next_time)) | |
elif is_90(next_angle): | |
total = total + 1 | |
perpendicular_time.append(next_time) | |
current_time = next_time | |
current_angle = next_angle | |
print total | |
return perpendicular_time | |
def crossed_90_degress(current_angle, next_angle): | |
return (current_angle < 90.0 and next_angle > 90.0) or \ | |
(current_angle > 90.0 and next_angle < 90.0) | |
def get_time_nearer_to_90(a_time, other_time): | |
an_angle = calculate_angle(a_time) | |
other_angle = calculate_angle(other_time) | |
a_difference, other_difference = abs(an_angle - 90), abs(other_angle - 90) | |
if a_difference < other_difference: | |
return a_time | |
else: | |
return other_time | |
def is_90(angle): | |
# floating point rounding errors? | |
# might be able to get away with checking for hardcoded time instead | |
return angle == 90.0 | |
def calculate_angle(a_time): | |
angle_of_min_hand = a_time.minute * MIN_HAND_DEG_PER_MIN + \ | |
a_time.second * MIN_HAND_DEG_PER_SECOND | |
angle_of_hour_hand = (a_time.hour % 12) * HOUR_HAND_DEG_PER_HOUR + \ | |
a_time.minute * HOUR_HAND_DEG_PER_MIN + \ | |
a_time.second * HOUR_HAND_DEG_PER_SECOND | |
start = min(angle_of_min_hand, angle_of_hour_hand) | |
end = max(angle_of_min_hand, angle_of_hour_hand) | |
difference = end - start | |
if difference > 180: | |
return 360 - difference | |
else: | |
return difference | |
class TestStackClock(unittest.TestCase): | |
def helper(self, the_time, lt_or_gt, angle): | |
calculated = calculate_angle(the_time) | |
if lt_or_gt == '<': | |
method = self.assertLess | |
if lt_or_gt == '>': | |
method = self.assertGreater | |
method(calculated, angle, | |
'%s has %s degress, should be %s than %s' % | |
(the_time, calculated, 'more', angle)) | |
def test_calculate_angle(self): | |
test_data = [ | |
[(0, 15, 0), '<', 90], | |
[(0, 16, 0), '<', 90], | |
[(0, 17, 0), '>', 90], | |
[(0, 17, 0), '>', 90], | |
[(0, 45, 0), '>', 90], | |
[(0, 49, 0), '>', 90], | |
[(0, 50, 0), '<', 90], | |
[(12, 15, 0), '<', 90], | |
[(12, 16, 0), '<', 90], | |
[(12, 17, 0), '>', 90], | |
[(12, 17, 0), '>', 90], | |
[(6, 15, 0), '>', 90], | |
[(6, 16, 0), '>', 90], | |
[(6, 17, 0), '<', 90], | |
[(6, 45, 0), '<', 90], | |
[(6, 48, 0), '<', 90], | |
[(6, 49, 0), '<', 90], | |
[(6, 50, 0), '>', 90], | |
] | |
for data in test_data: | |
data[0] = time(*data[0]) | |
self.helper(*data) | |
if __name__ == '__main__': | |
results = simulate_clock() | |
FORMAT = '%H:%M:%S' | |
for result in results: | |
print result.strftime(FORMAT) | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment