Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

This question already has an answer here:

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

share|improve this question

marked as duplicate by mniip, plannapus, Howard, Peter Taylor, ProgramFOX Feb 7 at 16:26

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

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

7 Answers 7

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.

share|improve this answer

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.

share|improve this answer
    
Nice, it seems working. Can you explain your calculations (or does it use some conclusions from older questions)? –  Arlaud Pierre Feb 7 at 12:56
    
I use my solution to a previous challenge. The "calculations" are used to determine which segments whould be "lit up" for a certain character. –  Rik Feb 7 at 13:13

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  _|.

share|improve this answer

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'))
share|improve this answer
1  
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) –  MT0 Feb 7 at 19:40

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.

share|improve this answer
    
At 14:58 it said "14:50", at 49 it said "14:51" and one minute later "15:00". –  Arlaud Pierre Feb 7 at 14:01
    
Yeah there is an issue with 8 and 9 encoding, I work on a fix :) –  Michael Feb 7 at 14:02
    
for whatever reason (haven't looked through the whole code), minutews are runded up I guess? –  Johannes H. Feb 7 at 14:02
2  
Sounds like some octal math worked its way in there. –  Ben Thul Feb 7 at 14:09

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.
share|improve this answer
    
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.) –  manatwork Feb 7 at 16:37
    
With a few more size optimizations, 240 characters: pastebin.com/7XQhXSpU –  manatwork Feb 7 at 17:30
    
Replace s[9]=' '+' ..'[h]+' ' with s[9]='%3s '%' ..'[h]. –  manatwork Feb 7 at 18:24

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.
share|improve this answer
1  
asc:array[0..9,0..2]of string…? –  manatwork Feb 7 at 12:31
    
Thanks, still fairly new to delphi, didnt know that was possible ^.^ –  Teun Pronk Feb 7 at 12:54
1  
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 –  manatwork Feb 7 at 14:28
    
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 :) –  Teun Pronk Feb 11 at 12:07

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