Files
wehub-resource-sync dde272c4b8
i18n - Build Validation / Validate i18n Builds (24) (push) Has been cancelled
CI - Node.js / Lint (24) (push) Has been cancelled
CI - Node.js / Build (24) (push) Has been cancelled
CI - Node.js / Test (24) (push) Has been cancelled
CI - Node.js / Test - Upcoming Changes (24) (push) Has been cancelled
CI - Node.js / Test - i18n (italian, 24) (push) Has been cancelled
CI - Node.js / Test - i18n (portuguese, 24) (push) Has been cancelled
CD - Docker - GHCR Images / Build and Push Images (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 11:55:53 +08:00

2.9 KiB
Raw Permalink Blame History

id, title, challengeType, dashedName
id title challengeType dashedName
6a26df3e2988bcdded204897 Challenge 361: Spoken Time 29 challenge-361

--description--

Given the angles for the hour and minute hands of an analog clock in degrees (clockwise from 12), return the time in spoken English.

Convert the minute hand angle to minutes (360° = 60 minutes), then use the following rules:

Minutes Spoken
0 "Y o'clock"
15 "quarter past Y"
129 (excluding 15) "X minutes past Y"
30 "half past Y"
45 "quarter to Z"
3159 (excluding 45) "X minutes to Z" (where X is 60 - minutes)

Where Y is the current hour and Z is the next hour, both derived from the hour hand angle (360° = 12 hours).

Note: Hand angles may not land exactly on a number, consider rounding them somehow.

--hints--

get_spoken_time(90, 0) should return "3 o'clock".

({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_spoken_time(90, 0), "3 o'clock")`)
}})

get_spoken_time(160, 120) should return "20 minutes past 5".

({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_spoken_time(160, 120), "20 minutes past 5")`)
}})

get_spoken_time(255, 180) should return "half past 8".

({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_spoken_time(255, 180), "half past 8")`)
}})

get_spoken_time(67.5, 92) should return "quarter past 2".

({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_spoken_time(67.5, 92), "quarter past 2")`)
}})

get_spoken_time(200, 240) should return "20 minutes to 7".

({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_spoken_time(200, 240), "20 minutes to 7")`)
}})

get_spoken_time(322.5, 273) should return "quarter to 11".

({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_spoken_time(322.5, 273), "quarter to 11")`)
}})

get_spoken_time(117.5, 335) should return "5 minutes to 4".

({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_spoken_time(117.5, 335), "5 minutes to 4")`)
}})

--seed--

--seed-contents--

def get_spoken_time(hour_angle, minute_angle):

    return hour_angle

--solutions--

def get_spoken_time(hour_angle, minute_angle):
    minutes = int(minute_angle / 6)
    hour = int(hour_angle / 30) or 12
    next_hour = (hour % 12) + 1

    if minutes == 0:
        return f"{hour} o'clock"
    if minutes == 15:
        return f"quarter past {hour}"
    if minutes == 30:
        return f"half past {hour}"
    if minutes == 45:
        return f"quarter to {next_hour}"
    if minutes < 30:
        return f"{minutes} minutes past {hour}"
    return f"{60 - minutes} minutes to {next_hour}"