Print a word clock
TI-Basic, 335 334 bytes
Pretty much perfect, since the TI-84 calcs have 8x16 letter displays, and this is 8x15. Date is taken as input in order to support calcs earlier than TI-84, which do not have internal clocks. With no arguments, Input
gets input by default into X
and Y
, similar to Prompt X,Y
. So make X
be hours (anything >=0
will work correctly) and have Y
be minutes.
Input
ClrHome
int(Y/5-5.6
Output(1,1,"IT IS
If Ans=~6
Output(8,8,"O'CLOCK
If 2=abs(3-abs(Ans
Output(3,1,"FIVE
If 4=abs(Ans
Output(1,12,"TEN
If 3=abs(Ans
Output(2,1,"QUARTER
If 2=abs(Ans
Output(2,8,"TWENTY
If sum(abs(Ans)={1,2,4,5
Output(3,5,"MINUTES
If not(Ans
Output(1,7,"HALF
If Ans<1 and Ans+6
Output(4,1,"PAST
If Ans>0
Output(3,14,"TO
12fPart(12(^~1)(X+(Y>32->A
If not(Ans
12->A
{21,6,10,25,30,41,45,51,61,66,70,81
.05Ans(A
Output(int(4+Ans),20fPart(Ans),sub("ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE TEN ELEVENTWELVE",6A-5,6
Note 1: For TI-84+ you can replace Input
with something like getTime:Ans(1->X:getTime:Ans(2->Y
. Also, int(Y/5-5.6
is equivalent to round(Y/5,0)-6
. And no, in this case int(
could not be interchanged with iPart(
.
Note 2: This prints the input just fine, but for asethetic reasons you probably want Pause
at the end of the program to avoid the Done
message upon program termination.
Edit: Byte count lowered because tokenized (see note on previous revision), also a bug is fixed thanks to @Neil. Third, fixed a bug I found myself which would have costed 2 bytes but the optimization actually saved 1 byte overall, and I also realized that I am getting input so I don't need to call getTime
(duh?). Last, for anyone who wants to confirm this byte count, the only two byte token is sub(
.
PHP, 387 384 353 352 342 323 310 306 298 293 291 bytes
Thanks @Christoph for golfing along with his excellent findings!
At least 45 bytes are on his account; 16 or more inspired by him.
A Marvel Team Up!
IT IS <?foreach([HALF,TEN,QUARTER,TWENTY,FIVE,MINUTES,TO,PAST,TWO,THREE,ONE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN,ELEVEN,TWELVE,"O'CLOCK"]as$w)echo strstr([w,ghj,dhj,ej,fhj,fghj,cj,fghi,fhi,ei,dhi,ghi][$m=date(i)/5+.5].mklnopqrstuvm[date(h)-($m<7)],99+$i)?$w:$w^$w^" ","
"[$i++%3^$i<3];
loops through the data and checks if the current index is in a generated string that contains the indexes of the words to light up (mapped to letters); appends linebreak or space depending on the index.
May yield notices if you dont´t use the default value for error_reporting
(22519).
Test it online.
breakdown
IT IS <?
foreach([HALF,TEN,QUARTER,TWENTY,FIVE,MINUTES,TO,PAST, // loop through words
TWO,THREE,ONE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN,ELEVEN,TWELVE,"O'CLOCK"]as$w)
echo strstr( // search word index in ...
[w,ghj,dhj,ej,fhj,fghj,cj,fghi,fhi,ei,dhi,ghi][$m=date(i)/5+.5] // minutes & co
.mklnopqrstuvm[date(h)-($m<7)] // hours (-1 if minutes<33)
,99+$i // (map 0..20 to c..w)
)?$w:$w^$w^" ", // if found, print string, else print spaces
"\n "[$i++%3^$i<3]; // if $i in [3,5,8,...], print newline, else space
Golfs:
$x/5+.5|0
is two bytes shorter thanround($x/5)
.- Two calls of
date(h)
are one byte shorter than assigning thedate
result to a variable. - Using a single assigment golfed away the variable that the light-up indexes were stored in.
- A string for the light-up indexes instead of an array saved around 30 bytes.
$w<A
is three bytes shorter than$w=="\n"
- make sure that no space is after a delimiter!abs
saved 8 bytes on the minutes word.- Thanks @Christoph: Moving from numbers to letters for the map rendered the separators obsolete and allowed one more string instead of array; saved 23+8 bytes.
Using underscore as the first index allowed to include it into the "it is" alternatives; and it rendered the quotation for the hours obsolete. - Duplicating the
1
value in the hours map rendered the modulo obsolete and that with additional golfing saved 10 bytes. Inspired by @Christoph. - Calculating the linebreaks and spaces instead of hardcoding them shaved off 19 bytes.
- Bit logic on strings saves 7 bytes:
str_pad("",strlen($w))
->$w^$w^" "
. (Christoph) - If
strtr
´s second parameter is no string, it will be interpreted as an ascii code. saves 5 bytes.
JavaScript (ES6), 291 303 295 bytes
Takes input as two integers with currying syntax (h)(m)
h=>m=>console.log(`IT IS HALF TEN
QUARTER TWENTY
FIVE MINUTES TO
PAST TWO THREE
ONE FOUR FIVE
SIX SEVEN EIGHT
NINE TEN ELEVEN
TWELVE O'CLOCK`.replace(/\S+/g,w=>(k/=2)&1?w:w.replace(/./g,' '),k=[x=1<<19,88,81,66,84,92,64.5,60,52,34,49,56,x,h=(m<33?h+11:h)%12][m/5+.4|0]*16|6|2048<<(h?h-(h<3):2)))
How it works
The whole clock can be seen as 23 LEDs that are either ON or OFF. So, the clock state is a 23-bit integer.
Bit | Word Bit | Word
----+-------- ----+--------
00 | IT 12 | ONE
01 | IS 13 | FOUR
02 | HALF 14 | FIVE
03 | TEN 15 | SIX
04 | QUARTER 16 | SEVEN
05 | TWENTY 17 | EIGHT
06 | FIVE 18 | NINE
07 | MINUTES 19 | TEN
08 | TO 20 | ELEVEN
09 | PAST 21 | TWELVE
10 | TWO 22 | O'CLOCK
11 | THREE
The minutes logic that we need to implement to enable the right words is not as simple as one might think at first glance. A magic-golfing formula may exist but I went the easy way and decided to just hardcode each possible configuration:
Minutes | Words | Enabled bits | Value | Value / 8
--------+--------------------------+--------------+---------+----------
00 | O'CLOCK | 22 | 4194304 | 524288
05 | FIVE MINUTES PAST | 6, 7, 9 | 704 | 88
10 | TEN MINUTES PAST | 3, 7, 9 | 648 | 81
15 | QUARTER PAST | 4, 9 | 528 | 66
20 | TWENTY MINUTES PAST | 5, 7, 9 | 672 | 84
25 | TWENTY FIVE MINUTES PAST | 5, 6, 7, 9 | 736 | 92
30 | HALF PAST | 2, 9 | 516 | 64.5
35 | TWENTY FIVE MINUTES TO | 5, 6, 7, 8 | 480 | 60
40 | TWENTY MINUTES TO | 5, 7, 8 | 416 | 52
45 | QUARTER TO | 4, 8 | 272 | 34
50 | TEN MINUTES TO | 3, 7, 8 | 392 | 49
55 | FIVE MINUTES TO | 6, 7, 8 | 448 | 56
Test cases
let f =
h=>m=>console.log(`IT IS HALF TEN
QUARTER TWENTY
FIVE MINUTES TO
PAST TWO THREE
ONE FOUR FIVE
SIX SEVEN EIGHT
NINE TEN ELEVEN
TWELVE O'CLOCK`.replace(/\S+/g,w=>(k/=2)&1?w:w.replace(/./g,' '),k=[x=1<<19,88,81,66,84,92,64.5,60,52,34,49,56,x,h=(m<33?h+11:h)%12][m/5+.4|0]*16|6|2048<<(h?h-(h<3):2)))
;
[[13,15],[13,58],[14,30],[15,35],[10,0],[12,0]].map(([h, m]) => {
console.log('h = ' + h, 'm = ' + m);
f(h)(m);
});