Skip to content

Instantly share code, notes, and snippets.

@paulgroves
Last active November 3, 2015 09:10
Show Gist options
  • Save paulgroves/83171e4d5bb8aaad7ff1 to your computer and use it in GitHub Desktop.
Save paulgroves/83171e4d5bb8aaad7ff1 to your computer and use it in GitHub Desktop.
Calculate angles between clock hands
class Clock
DEGREES = 360.0
MINUTES = 60.0
HOURS = 12.0
attr_accessor :hour, :minute
def initialize(hour:, minute:)
validate_inputs!(hour, minute)
self.hour = hour >= HOURS ? hour - HOURS : hour
self.minute = minute
end
def angle_between_hands
hands = [minute_hand_degrees, hour_hand_degrees]
format_result(hands.max - hands.min)
end
def minute_hand_degrees
minute * minute_in_degree
end
def hour_hand_degrees
hour_main + hour_fraction
end
private
def format_result(result)
result >= DEGREES ? DEGREES - result : result
end
def validate_inputs!(hour, minute)
raise ArgumentError unless (0..24).include?(hour)
raise ArgumentError unless (0..59).include?(minute)
end
def hour_main
minute_in_degree * (hour * (MINUTES / HOURS))
end
def hour_fraction
minute * (hour_in_degrees / MINUTES)
end
def minute_in_degree
DEGREES / MINUTES
end
def hour_in_degrees
DEGREES / HOURS
end
end
require_relative './clock.rb'
RSpec.describe Clock do
context '#angle_between_hands' do
it '9:30 should be 105!' do
expect(Clock.new(hour: 9, minute: 30).angle_between_hands).to eq 105
end
it 'should raise with invalid minute' do
expect{ Clock.new(hour: 0, minute: 77) }.to raise_error(ArgumentError)
end
it 'should raise with invalid hour' do
expect{ Clock.new(hour: 25, minute: 0) }.to raise_error(ArgumentError)
end
let(:one_oclock_result) { [30.0, 24.5, 19.0, 13.5, 8.0, 2.5, 3.0, 8.5, 14.0, 19.5, 25.0, 30.5, 36.0, 41.5, 47.0, 52.5, 58.0, 63.5, 69.0, 74.5, 80.0, 85.5, 91.0, 96.5, 102.0, 107.5, 113.0, 118.5, 124.0, 129.5, 135.0, 140.5, 146.0, 151.5, 157.0, 162.5, 168.0, 173.5, 179.0, 184.5, 190.0, 195.5, 201.0, 206.5, 212.0, 217.5, 223.0, 228.5, 234.0, 239.5, 245.0, 250.5, 256.0, 261.5, 267.0, 272.5, 278.0, 283.5, 289.0, 294.5] }
let(:two_oclock_result) { [60.0, 54.5, 49.0, 43.5, 38.0, 32.5, 27.0, 21.5, 16.0, 10.5, 5.0, 0.5, 6.0, 11.5, 17.0, 22.5, 28.0, 33.5, 39.0, 44.5, 50.0, 55.5, 61.0, 66.5, 72.0, 77.5, 83.0, 88.5, 94.0, 99.5, 105.0, 110.5, 116.0, 121.5, 127.0, 132.5, 138.0, 143.5, 149.0, 154.5, 160.0, 165.5, 171.0, 176.5, 182.0, 187.5, 193.0, 198.5, 204.0, 209.5, 215.0, 220.5, 226.0, 231.5, 237.0, 242.5, 248.0, 253.5, 259.0, 264.5] }
let(:three_oclock_result) { [90.0, 84.5, 79.0, 73.5, 68.0, 62.5, 57.0, 51.5, 46.0, 40.5, 35.0, 29.5, 24.0, 18.5, 13.0, 7.5, 2.0, 3.5, 9.0, 14.5, 20.0, 25.5, 31.0, 36.5, 42.0, 47.5, 53.0, 58.5, 64.0, 69.5, 75.0, 80.5, 86.0, 91.5, 97.0, 102.5, 108.0, 113.5, 119.0, 124.5, 130.0, 135.5, 141.0, 146.5, 152.0, 157.5, 163.0, 168.5, 174.0, 179.5, 185.0, 190.5, 196.0, 201.5, 207.0, 212.5, 218.0, 223.5, 229.0, 234.5] }
let(:four_oclock_result) { [120.0, 114.5, 109.0, 103.5, 98.0, 92.5, 87.0, 81.5, 76.0, 70.5, 65.0, 59.5, 54.0, 48.5, 43.0, 37.5, 32.0, 26.5, 21.0, 15.5, 10.0, 4.5, 1.0, 6.5, 12.0, 17.5, 23.0, 28.5, 34.0, 39.5, 45.0, 50.5, 56.0, 61.5, 67.0, 72.5, 78.0, 83.5, 89.0, 94.5, 100.0, 105.5, 111.0, 116.5, 122.0, 127.5, 133.0, 138.5, 144.0, 149.5, 155.0, 160.5, 166.0, 171.5, 177.0, 182.5, 188.0, 193.5, 199.0, 204.5] }
let(:five_oclock_result) { [150.0, 144.5, 139.0, 133.5, 128.0, 122.5, 117.0, 111.5, 106.0, 100.5, 95.0, 89.5, 84.0, 78.5, 73.0, 67.5, 62.0, 56.5, 51.0, 45.5, 40.0, 34.5, 29.0, 23.5, 18.0, 12.5, 7.0, 1.5, 4.0, 9.5, 15.0, 20.5, 26.0, 31.5, 37.0, 42.5, 48.0, 53.5, 59.0, 64.5, 70.0, 75.5, 81.0, 86.5, 92.0, 97.5, 103.0, 108.5, 114.0, 119.5, 125.0, 130.5, 136.0, 141.5, 147.0, 152.5, 158.0, 163.5, 169.0, 174.5] }
let(:six_oclock_result) { [180.0, 174.5, 169.0, 163.5, 158.0, 152.5, 147.0, 141.5, 136.0, 130.5, 125.0, 119.5, 114.0, 108.5, 103.0, 97.5, 92.0, 86.5, 81.0, 75.5, 70.0, 64.5, 59.0, 53.5, 48.0, 42.5, 37.0, 31.5, 26.0, 20.5, 15.0, 9.5, 4.0, 1.5, 7.0, 12.5, 18.0, 23.5, 29.0, 34.5, 40.0, 45.5, 51.0, 56.5, 62.0, 67.5, 73.0, 78.5, 84.0, 89.5, 95.0, 100.5, 106.0, 111.5, 117.0, 122.5, 128.0, 133.5, 139.0, 144.5] }
let(:seven_oclock_result) { [210.0, 204.5, 199.0, 193.5, 188.0, 182.5, 177.0, 171.5, 166.0, 160.5, 155.0, 149.5, 144.0, 138.5, 133.0, 127.5, 122.0, 116.5, 111.0, 105.5, 100.0, 94.5, 89.0, 83.5, 78.0, 72.5, 67.0, 61.5, 56.0, 50.5, 45.0, 39.5, 34.0, 28.5, 23.0, 17.5, 12.0, 6.5, 1.0, 4.5, 10.0, 15.5, 21.0, 26.5, 32.0, 37.5, 43.0, 48.5, 54.0, 59.5, 65.0, 70.5, 76.0, 81.5, 87.0, 92.5, 98.0, 103.5, 109.0, 114.5] }
let(:eight_oclock_result) { [240.0, 234.5, 229.0, 223.5, 218.0, 212.5, 207.0, 201.5, 196.0, 190.5, 185.0, 179.5, 174.0, 168.5, 163.0, 157.5, 152.0, 146.5, 141.0, 135.5, 130.0, 124.5, 119.0, 113.5, 108.0, 102.5, 97.0, 91.5, 86.0, 80.5, 75.0, 69.5, 64.0, 58.5, 53.0, 47.5, 42.0, 36.5, 31.0, 25.5, 20.0, 14.5, 9.0, 3.5, 2.0, 7.5, 13.0, 18.5, 24.0, 29.5, 35.0, 40.5, 46.0, 51.5, 57.0, 62.5, 68.0, 73.5, 79.0, 84.5] }
let(:nine_oclock_result) { [270.0, 264.5, 259.0, 253.5, 248.0, 242.5, 237.0, 231.5, 226.0, 220.5, 215.0, 209.5, 204.0, 198.5, 193.0, 187.5, 182.0, 176.5, 171.0, 165.5, 160.0, 154.5, 149.0, 143.5, 138.0, 132.5, 127.0, 121.5, 116.0, 110.5, 105.0, 99.5, 94.0, 88.5, 83.0, 77.5, 72.0, 66.5, 61.0, 55.5, 50.0, 44.5, 39.0, 33.5, 28.0, 22.5, 17.0, 11.5, 6.0, 0.5, 5.0, 10.5, 16.0, 21.5, 27.0, 32.5, 38.0, 43.5, 49.0, 54.5] }
let(:ten_oclock_result) { [300.0, 294.5, 289.0, 283.5, 278.0, 272.5, 267.0, 261.5, 256.0, 250.5, 245.0, 239.5, 234.0, 228.5, 223.0, 217.5, 212.0, 206.5, 201.0, 195.5, 190.0, 184.5, 179.0, 173.5, 168.0, 162.5, 157.0, 151.5, 146.0, 140.5, 135.0, 129.5, 124.0, 118.5, 113.0, 107.5, 102.0, 96.5, 91.0, 85.5, 80.0, 74.5, 69.0, 63.5, 58.0, 52.5, 47.0, 41.5, 36.0, 30.5, 25.0, 19.5, 14.0, 8.5, 3.0, 2.5, 8.0, 13.5, 19.0, 24.5] }
let(:eleven_oclock_result) { [330.0, 324.5, 319.0, 313.5, 308.0, 302.5, 297.0, 291.5, 286.0, 280.5, 275.0, 269.5, 264.0, 258.5, 253.0, 247.5, 242.0, 236.5, 231.0, 225.5, 220.0, 214.5, 209.0, 203.5, 198.0, 192.5, 187.0, 181.5, 176.0, 170.5, 165.0, 159.5, 154.0, 148.5, 143.0, 137.5, 132.0, 126.5, 121.0, 115.5, 110.0, 104.5, 99.0, 93.5, 88.0, 82.5, 77.0, 71.5, 66.0, 60.5, 55.0, 49.5, 44.0, 38.5, 33.0, 27.5, 22.0, 16.5, 11.0, 5.5] }
let(:tweleve_oclock_result) { [0.0, 5.5, 11.0, 16.5, 22.0, 27.5, 33.0, 38.5, 44.0, 49.5, 55.0, 60.5, 66.0, 71.5, 77.0, 82.5, 88.0, 93.5, 99.0, 104.5, 110.0, 115.5, 121.0, 126.5, 132.0, 137.5, 143.0, 148.5, 154.0, 159.5, 165.0, 170.5, 176.0, 181.5, 187.0, 192.5, 198.0, 203.5, 209.0, 214.5, 220.0, 225.5, 231.0, 236.5, 242.0, 247.5, 253.0, 258.5, 264.0, 269.5, 275.0, 280.5, 286.0, 291.5, 297.0, 302.5, 308.0, 313.5, 319.0, 324.5] }
it 'calculates values for 1 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 1, minute: i).angle_between_hands }
expect(subject).to eq(one_oclock_result)
end
it 'calculates values for 2 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 2, minute: i).angle_between_hands }
expect(subject).to eq(two_oclock_result)
end
it 'calculates values for 3 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 3, minute: i).angle_between_hands }
expect(subject).to eq(three_oclock_result)
end
it 'calculates values for 4 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 4, minute: i).angle_between_hands }
expect(subject).to eq(four_oclock_result)
end
it 'calculates values for 5 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 5, minute: i).angle_between_hands }
expect(subject).to eq(five_oclock_result)
end
it 'calculates values for 6 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 6, minute: i).angle_between_hands }
expect(subject).to eq(six_oclock_result)
end
it 'calculates values for 7 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 7, minute: i).angle_between_hands }
expect(subject).to eq(seven_oclock_result)
end
it 'calculates values for 8 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 8, minute: i).angle_between_hands }
expect(subject).to eq(eight_oclock_result)
end
it 'calculates values for 9 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 9, minute: i).angle_between_hands }
expect(subject).to eq(nine_oclock_result)
end
it 'calculates values for 10 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 10, minute: i).angle_between_hands }
expect(subject).to eq(ten_oclock_result)
end
it 'calculates values for 11 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 11, minute: i).angle_between_hands }
expect(subject).to eq(eleven_oclock_result)
end
it 'calculates values for 12 o\'clock' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 12, minute: i).angle_between_hands }
expect(subject).to eq(tweleve_oclock_result)
end
it 'calculates values for 13 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 13, minute: i).angle_between_hands }
expect(subject).to eq(one_oclock_result)
end
it 'calculates values for 14 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 14, minute: i).angle_between_hands }
expect(subject).to eq(two_oclock_result)
end
it 'calculates values for 15 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 15, minute: i).angle_between_hands }
expect(subject).to eq(three_oclock_result)
end
it 'calculates values for 16 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 16, minute: i).angle_between_hands }
expect(subject).to eq(four_oclock_result)
end
it 'calculates values for 17 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 17, minute: i).angle_between_hands }
expect(subject).to eq(five_oclock_result)
end
it 'calculates values for 18 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 18, minute: i).angle_between_hands }
expect(subject).to eq(six_oclock_result)
end
it 'calculates values for 19 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 19, minute: i).angle_between_hands }
expect(subject).to eq(seven_oclock_result)
end
it 'calculates values for 20 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 20, minute: i).angle_between_hands }
expect(subject).to eq(eight_oclock_result)
end
it 'calculates values for 21 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 21, minute: i).angle_between_hands }
expect(subject).to eq(nine_oclock_result)
end
it 'calculates values for 22 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 22, minute: i).angle_between_hands }
expect(subject).to eq(ten_oclock_result)
end
it 'calculates values for 23 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 23, minute: i).angle_between_hands }
expect(subject).to eq(eleven_oclock_result)
end
it 'calculates values for 00 hrs' do
subject = (0..59).to_a.map{ |i| Clock.new(hour: 00, minute: i).angle_between_hands }
expect(subject).to eq(tweleve_oclock_result)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment