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
122 lines
2.9 KiB
Markdown
122 lines
2.9 KiB
Markdown
---
|
||
id: 6a26df3e2988bcdded204897
|
||
title: "Challenge 361: Spoken Time"
|
||
challengeType: 29
|
||
dashedName: 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"` |
|
||
| 1–29 (excluding 15) | `"X minutes past Y"` |
|
||
| 30 | `"half past Y"` |
|
||
| 45 | `"quarter to Z"` |
|
||
| 31–59 (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"`.
|
||
|
||
```js
|
||
({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"`.
|
||
|
||
```js
|
||
({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"`.
|
||
|
||
```js
|
||
({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"`.
|
||
|
||
```js
|
||
({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"`.
|
||
|
||
```js
|
||
({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"`.
|
||
|
||
```js
|
||
({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"`.
|
||
|
||
```js
|
||
({test: () => { runPython(`
|
||
from unittest import TestCase
|
||
TestCase().assertEqual(get_spoken_time(117.5, 335), "5 minutes to 4")`)
|
||
}})
|
||
```
|
||
|
||
# --seed--
|
||
|
||
## --seed-contents--
|
||
|
||
```py
|
||
def get_spoken_time(hour_angle, minute_angle):
|
||
|
||
return hour_angle
|
||
```
|
||
|
||
# --solutions--
|
||
|
||
```py
|
||
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}"
|
||
```
|