Print the time in a digital watch

6

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

Pierre Arlaud

Posted 2014-02-07T10:48:20.533

Reputation: 179

Question was closed 2014-02-07T16:26:17.840

2"The : is separated with the digits on both sides by 2 spaces." In your example it has 3 spaces on the left. – Boann – 2014-02-07T11:30:14.033

1@Boann Maybe 1 already has 1 space on each side? – Timtech – 2014-02-07T11:41:50.927

@Boann: no, the 1 digit has spaces included. – Pierre Arlaud – 2014-02-07T12:27:07.027

@mniip didn't see that one, but I believe the "glue" between getting the current time and printing the digits makes the golfing interesting. – Pierre Arlaud – 2014-02-07T12:28:16.267

@ArlaudPierre Having the segments of '1' in a different places actually eliminates some clever encoding strategies :( – Boann – 2014-02-07T12:31:49.473

@Boann Okay I've checked in fact there was a missing space. If you look at a digital clock, it usually has 7 segments, and 1 is represented by the two segments on the right so the empty segments on the left add a space (there are 2 spaces before the digit + 1 space for the empty | + 2 spaces for the empty __) – Pierre Arlaud – 2014-02-07T12:35:03.313

Answers

4

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.

Boann

Posted 2014-02-07T10:48:20.533

Reputation: 378

2

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.

Rik

Posted 2014-02-07T10:48:20.533

Reputation: 781

Nice, it seems working. Can you explain your calculations (or does it use some conclusions from older questions)? – Pierre Arlaud – 2014-02-07T12:56:50.210

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 – 2014-02-07T13:13:27.587

1

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

mniip

Posted 2014-02-07T10:48:20.533

Reputation: 9 396

1

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.

Michael M.

Posted 2014-02-07T10:48:20.533

Reputation: 12 173

At 14:58 it said "14:50", at 49 it said "14:51" and one minute later "15:00". – Pierre Arlaud – 2014-02-07T14:01:11.230

Yeah there is an issue with 8 and 9 encoding, I work on a fix :) – Michael M. – 2014-02-07T14:02:32.500

for whatever reason (haven't looked through the whole code), minutews are runded up I guess? – Johannes H. – 2014-02-07T14:02:52.290

2Sounds like some octal math worked its way in there. – Ben Thul – 2014-02-07T14:09:45.523

1

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'))

Florent

Posted 2014-02-07T10:48:20.533

Reputation: 2 557

1177 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 – 2014-02-07T19:40:17.143

0

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.

Teun Pronk

Posted 2014-02-07T10:48:20.533

Reputation: 2 599

1asc:array[0..9,0..2]of string…? – manatwork – 2014-02-07T12:31:34.187

Thanks, still fairly new to delphi, didnt know that was possible ^.^ – Teun Pronk – 2014-02-07T12:54:24.553

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: http://pastebin.com/uwRPGse1

– manatwork – 2014-02-07T14:28:24.443

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 – 2014-02-11T12:07:15.057

0

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.

Pablo

Posted 2014-02-07T10:48:20.533

Reputation: 121

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 – 2014-02-07T16:37:19.993

With a few more size optimizations, 240 characters: http://pastebin.com/7XQhXSpU

– manatwork – 2014-02-07T17:30:40.967

Replace s[9]=' '+' ..'[h]+' ' with s[9]='%3s '%' ..'[h]. – manatwork – 2014-02-07T18:24:42.433