6
\$\begingroup\$

Write a program that prints the current time in a digital watch.

Rules:

  • The program must use the local timezone.
  • Time is expressed between 00:00 to 23:59 (with only hours and minutes).
  • The program must follow the output rules.
  • The smallest program wins.

Output (see example):

  • Each digit is represented by 4×3 matrix of the characters (space), | (pipe) and _ (underscore).
  • There are two spaces between two digits.
  • The : (column) is represented with a 1x3 matrix [,.,.] and is separated with the digits on both sides by 2 spaces.
  • A newline at the end of the output is tolerated.

List of digits:

 __           __    __          __    __    __    __    __
|  |     |    __|   __|  |__|  |__   |__      |  |__|  |__|
|__|     |   |__    __|     |   __|  |__|     |  |__|   __| 

Example output: (for 21:08)

 __             __    __
 __|     |  .  |  |  |__|
|__      |  .  |__|  |__|

Go!

EDIT: corrected the spaces for : and 1

\$\endgroup\$
6
  • 2
    \$\begingroup\$ "The : is separated with the digits on both sides by 2 spaces." In your example it has 3 spaces on the left. \$\endgroup\$
    – Boann
    Feb 7, 2014 at 11:30
  • 1
    \$\begingroup\$ @Boann Maybe 1 already has 1 space on each side? \$\endgroup\$
    – Timtech
    Feb 7, 2014 at 11:41
  • \$\begingroup\$ @Boann: no, the 1 digit has spaces included. \$\endgroup\$ Feb 7, 2014 at 12:27
  • \$\begingroup\$ @mniip didn't see that one, but I believe the "glue" between getting the current time and printing the digits makes the golfing interesting. \$\endgroup\$ Feb 7, 2014 at 12:28
  • \$\begingroup\$ @ArlaudPierre Having the segments of '1' in a different places actually eliminates some clever encoding strategies :( \$\endgroup\$
    – Boann
    Feb 7, 2014 at 12:31

7 Answers 7

4
\$\begingroup\$

PHP, 229 174

<?php $s=" |.. w\$km<]_d\x7F}";for($r=3;$r--;print'
')foreach(str_split(date('H:i'))as$c)echo$c>'9'?$s[$r+2]:$s[($d=ord($s[$c+5])>>$r*3)/2&1].($d&1?@__:'  ').$s[$d/4&1],'  ';

$s is a lookup table that encodes several things. The first two characters are the vertical segments, when off or on. The next three characters are the characters of the colon on each of the three rows. The character codes of the remaining characters encode in binary the state of the segments of each digit.


Old version, 229 chars:

<?php foreach([strtr(decbin(735),['    ',' __ ']).' ','|  |   | __| __||__||__ |__    ||__||__|.','|__|   ||__  __|   | __||__|   ||__| __|.']as$r){foreach(str_split(date('H:i'))as$c)echo substr($r,ord($c)-48<<2,4).'  ';echo'
';}

Useful fact: the ASCII code of : is one greater than the ASCII code of 9, so 0123456789: are contiguous.

\$\endgroup\$
2
\$\begingroup\$

C# (407 418)

namespace System{using z=String;using w=Console;class P{static void Main(){var t=DateTime.Now.ToString("HH:mm");int k=0;z b="17",d=b+23,e=b+3459,f="56",g=e+2680;Action<z,z,z>q=(l,m,r)=>{foreach(var c in t){if(c==':')w.Write(k++>0?".":" ");else{h(c,l);h(c,m,"_");h(c,m,"_");h(c,r);}w.Write("  ");}w.Write("\n");};q(g,"14",g);q(d,b+0,f);q(e,b+4,"2");}static void h(char x,z m,z y="|"){w.Write(m.Contains(""+x)?" ":y);}}}

Edit: digits are now 4x3 instead of 3x3. this adds 11 characters.

\$\endgroup\$
2
  • \$\begingroup\$ Nice, it seems working. Can you explain your calculations (or does it use some conclusions from older questions)? \$\endgroup\$ Feb 7, 2014 at 12:56
  • \$\begingroup\$ I use my solution to a previous challenge. The "calculations" are used to determine which segments whould be "lit up" for a certain character. \$\endgroup\$
    – Rik
    Feb 7, 2014 at 13:13
1
\$\begingroup\$

Perl - 289 291 302

use POSIX;$_=$p=(strftime"%H:%02M\n",localtime)=~s;.;$&  ;rg;s;\S;$&eq':'?'a':$&-1&&$&-4?'abba':'aaaa';eg;$_.=$p;s;\d|:;(caacaaacabbcabbccbbccbbacbbaaaaccbbccbbcd=~/.{0,4}/g)[-48+ord$&];eg;$_.=$p;s;\d|:;(cbbcaaaccbbaabbcaaacabbccbbcaaaccbbcabbcd=~/.{0,4}/g)[-48+ord$&];eg;y;a-d; _|.;;print
  • strftime"%H:%02M\n",localtime - obtain local time in H:MM format

  • s;.;$& ;rg - intersperse with double spaces
    the time is saved in $p for later usage

  • s;\S;$&eq':'?'a':$&==1||$&==4?'aaaa':'abba';eg - replace : with a, 1 and 4 with aaaa and other digits with abba (later a will turn into , b - into _, c - |, d - .)
    $_.=$p append $p (spaced time)

  • s;\d|:;(caacaaacabbcabbccbbccbbacbbaaaaccbbccbbcd=~/.{0,4}/g)[-48+ord$&];eg

    • /.{0,4}/g - turn the preceding string into an array of 4-char strings
    • -48+ord$& - turn char code into an index, 0 becomes 0, 1 becomes 1, : becomes 10
  • then append $p again and run a similar substitution

  • y;a-d; _|.; - replace abcd with  _|.

\$\endgroup\$
1
\$\begingroup\$

JavaScript, 192

Disclaimer: This one is a JavaScript port of @Boann's answer.

for(o='',D=(o+(new Date)).substr(16,5),s=' |.. w$km<]_d\x7F}',r=3;r--;o+='\n')for(i=0;c=D[i++];o+=c>'9'?s[r+2]:(s[(d=(s[+c+5]).charCodeAt(0)>>r*3)/2&1]+(d&1?'__':'  ')+s[d/4&1])+'  ');alert(o)

JavaScript (ES6), 256

for(t=[v='',v,v],d=(v+(new Date)).substr(16,5),i=0;c=d[i++];)for(j=3;j--;t[j]+='0    00    00000 +|22  1 1|1|__ |__  2|1|1.+|12 |__  1 2 1|1 2|1 1.'.replace(/\d/g,e=>!+e?' __ ':e^2?'__|':'  |').split('+')[j].substr(+c==c?c*4:40,4)+'  ');alert(t.join('\n'))

Ungolfed:

for(
  // Create an array containing 3 empty strings.
  t=[v='',v,v],
  // Convert current date to a string and extract the time part.
  d=(v+(new Date)).substr(16,5),
  i=0;
  // Read current time digit.
  // Break the loop when the end of string is reached.
  c=d[i++];
)
  for(
    // Iterate 3 times in order to fill each line.
    j=3; j--;
    // Append current character.
    t[j]+='0    00    00000 +|22  1 1|1|__ |__  2|1|1.+|12 |__  1 2 1|1 2|1 1.'.replace(
      // Unpack the above string.
      // Convert each digit into a substring as follow:
      /\d/g,e=>
        // 0: Convert current digit into a number and negate it.
        //    Must be done because !'0' equals false.
        !+e?' __ '
        // 1: Convert current digit into a number and check if different than 2.
        //    Since we have handled the 0, we just read a 1.
        :e^2?'__|'
        // 2: Last case.
        :'  |'
    // Split the unpacked string in 3 lines.
    ).split('+')[j]
      // Get the 4 characters representing the current digit.
      .substr(
        // Convert current digit into a number and compare it with itseft.
        // The comparison fails if the digit convertion results in NaN (:).
        +c==c?c*4:40,4
      // Add 2 spaces between each digits
      )+'  '
  );

// Join lines.
// Output ASCII time.
console.log(t.join('\n'))
\$\endgroup\$
1
  • 1
    \$\begingroup\$ 177 Characters: o='';D=o+Date();s=' |.. w$km<]_d\x7F}';for(r=3;r--;o+='\n')for(i=16;i<21;)o+=(c=D[i++])>'9'?s[r+2]:(s[(d=s[+c+5].charCodeAt(0)>>r*3)/2&1]+(d&1?'__':e=' ')+s[d/4&1])+e;alert(o) \$\endgroup\$
    – MT0
    Feb 7, 2014 at 19:40
1
\$\begingroup\$

Javascript (444, 436, 417, 402)

s="\n";q=[];[0x6606,0x66666,0xfee89,0xff877,0x8e78f,0xef8fe].forEach(function(n){for(i=0;i<20;++i)q.push(1&(n>>i))});function f(j){s+=q[j]?'|':' ';s+=q[j+1]?'_':' ';s+=q[j+2]?'_':' ';s+=q[j+3]?'|':' '}function g(n,l){f(4*Math.floor(n/10)+40*l);s+="  ";f(4*(n%10)+40*l)}d=new Date;h=d.getHours();m=d.getMinutes();p="  .  ";g(h,0);s+="     ";g(m,0);s+="\n";g(h,1);s+=p;g(m,1);s+="\n";g(h,2);s+=p;g(m,2);s

How it works :
Each line of a number is encoded with 4 bits, 0 is a space, 1 is _ (for 2nd and 3rd character) or | (for 1st and last character).
For example, 5 is 0110, 0001, 0111.
The goal is to create an array of 120 booleans (10 numbers * 3 lines * 4 bits) containing all the numbers.

\$\endgroup\$
4
  • \$\begingroup\$ At 14:58 it said "14:50", at 49 it said "14:51" and one minute later "15:00". \$\endgroup\$ Feb 7, 2014 at 14:01
  • \$\begingroup\$ Yeah there is an issue with 8 and 9 encoding, I work on a fix :) \$\endgroup\$
    – Michael M.
    Feb 7, 2014 at 14:02
  • \$\begingroup\$ for whatever reason (haven't looked through the whole code), minutews are runded up I guess? \$\endgroup\$ Feb 7, 2014 at 14:02
  • 2
    \$\begingroup\$ Sounds like some octal math worked its way in there. \$\endgroup\$
    – Ben Thul
    Feb 7, 2014 at 14:09
0
\$\begingroup\$

Ruby (239 335)

0.upto(2){|h|s=(0..3).map{|i|'041655023022615032031055011012'.gsub(/./){[' __ ','|__|',' __|','|__ ','|  |','   |',' '*4][$&.to_i]}.scan(/.{12}/)[Time.new.strftime('%H%M').split('')[i].to_i][h*4..h*4+3]}*' ';s[9]='  '+' ..'[h]+'  ';puts s}

Edit: Shorted with @manatwork syntax

The idea is pretty straightforward: make the array with the numbers and substrings (with []) to print each line of the number. I know is far from perfect, I'm new in Ruby and there is probably a way to make a loop in the printing that takes less chars.
\$\endgroup\$
3
  • \$\begingroup\$ Instead of putting the time in variable t then distributing to 4 variables with 4 separate assignments, you can do it without variable t using a single parallel assignment: m,n,l,k=Time.new.strftime('%H%M').split('').map{|i|i.to_i}. (Just matter of syntax, not checked how good idea is the use of those 4 variables.) \$\endgroup\$
    – manatwork
    Feb 7, 2014 at 16:37
  • \$\begingroup\$ With a few more size optimizations, 240 characters: pastebin.com/7XQhXSpU \$\endgroup\$
    – manatwork
    Feb 7, 2014 at 17:30
  • \$\begingroup\$ Replace s[9]=' '+' ..'[h]+' ' with s[9]='%3s '%' ..'[h]. \$\endgroup\$
    – manatwork
    Feb 7, 2014 at 18:24
0
\$\begingroup\$

Delphi XE3 (504 495)

Waay to much, but still fun to do :)
Thanks Manatwork for the tip on multidimensional arrays.

const asc:array[0..9,0..2]of string=((' __ ','|  |','|__|'),('    ','   |','   |'),(' __ ',' __|','|__ '),(' __ ',' __|',' __|'),('    ','|__|','   |'),(' __ ','|__ ',' __|'),(' __ ','|__ ','|__|'),(' __ ','   |','   |'),(' __ ','|__|','|__|'),(' __ ','|__|',' __|'));var s,l:string;x,i:int16;begin s:=FormatDateTime('hhnn',now);for I:=0to 2do begin l:='';for x:=1to length(s)do begin l:=l+asc[StrToInt(s[x])][i];if x=2 then if i>0then l:=l+'  .  'else l:=l+'     'end;writeln(l);end;readln;end.

With indent

const
asc: array[0..9,0..2] of string = (
  (' __ ','|  |','|__|'),
  ('    ','   |','   |'),
  (' __ ',' __|','|__ '),
  (' __ ',' __|',' __|'),
  ('    ','|__|','   |'),
  (' __ ','|__ ',' __|'),
  (' __ ','|__ ','|__|'),
  (' __ ','   |','   |'),
  (' __ ','|__|','|__|'),
  (' __ ','|__|',' __|'));
var
s,l:string;
x,i:int16;
begin
    s:=FormatDateTime('hhnn',now);
    for I := 0 to 2 do
    begin
      l:='';
      for x := 1 to length(s) do
      begin
        l := l + asc[StrToInt(s[x])][i];
        if x=2 then
          if i>0then
            l:=l+'  .  '
          else l:=l+'     '
      end;
      writeln(l);
    end;
    readln
end.
\$\endgroup\$
4
  • 1
    \$\begingroup\$ asc:array[0..9,0..2]of string…? \$\endgroup\$
    – manatwork
    Feb 7, 2014 at 12:31
  • \$\begingroup\$ Thanks, still fairly new to delphi, didnt know that was possible ^.^ \$\endgroup\$
    – Teun Pronk
    Feb 7, 2014 at 12:54
  • 1
    \$\begingroup\$ Took a closer look and I observed some problems. Well, at least in Delphi 2007 these are problems: 1) needs compilation directive to be able to use standard output; 2) the use of SysUtils must be declared; 3) No int16 data type – please specify your Delphi version. But there are some minor tricks to reduce the code size: 1) the array contains just a few distinct strings repeated many times, so better declare them separately; 2) due to the fixed “hhmnn” format string s's length will be always 4, so no need for the Length function; and a few minor tweaks. 415 char: pastebin.com/uwRPGse1 \$\endgroup\$
    – manatwork
    Feb 7, 2014 at 14:28
  • \$\begingroup\$ Thanks, this is very helpful. I wont change it though because its barely my code anymore, but im sure I can use this for other questions too. So thanks a bunch :) \$\endgroup\$
    – Teun Pronk
    Feb 11, 2014 at 12:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.