Skip to content

Instantly share code, notes, and snippets.

@ngzhian
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ngzhian/73c61f881116b2f939ec to your computer and use it in GitHub Desktop.
Save ngzhian/73c61f881116b2f939ec to your computer and use it in GitHub Desktop.
Clock question
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