views:

2997

answers:

29

Possible Duplicate:
Code Golf: Seven Segments

The task: Write the smallest possible program (least number of characters) that takes input in the hh:mm format and outputs this as a digital clock (seven-segment display).

Sample input: 19:27
Sample output:

     _     _   _
  | |_| .  _|   |
  |  _| . |_    |

Sample input: 11:11
Sample output:

 
  |   | .   |   |
  |   | .   |   |

The numbers should look like this:

     _   _       _   _   _   _   _   _
  |  _|  _| |_| |_  |_    | |_| |_| | |
  | |_   _|   |  _| |_|   | |_|  _| |_|

The colon is represented by a dot on the second and third line of output. Numbers must be separated by a column of spaces, the same goes with the colon. A special case is the first and last number - to make this harder, you are not allowed to have trailing spaces.

Any language is allowed. Please use the standard answer format as in the other code golf questions. And the prize? Fame ;)

Note: i'm not the author of this challenge. It was presented to me by a friend from a university where I studied. I do not claim that HE is the author of this, but he is the first person who told me about this.

Hint: a clever way of storing the numbers appearance could be the key to success.

Update: From comments below i decided to add one small constraint. Since the challenge is called "digital clock" it is now required to have fixed width numbers. So all of them must occupy 3 collumns and 3 rows. It should look as in a digital clock, so for example number one occuppies the right most column. I've edited the sample outputs.

+4  A: 

Perl, 349 chars

@d[48..59]=(' _ ',' ',' _ ','_ ','   ',' _ ',' _ ','_ ',' _ ',' _ ',' ');
@e[48..59]=('| |','|',' _|','_|','|_|','|_ ','|_ ',' |','|_|','|_|','.');
@f[48..59]=('|_|','|','|_ ','_|','  |',' _|','|_|',' |','|_|',' _|','.');
$_=<>;print join(' ',map$d[ord$_],split//,$_)."\n".
join(' ',map$e[ord$_],split//,$_)."\n".
join(' ',map$f[ord$_],split//,$_)."\n";

Added newlines for clarity.

ninjalj
Perl rules them all? ;) Lets see if anyone can find a better solution, but this one is indeed nice.
PeterK
Nice to see the digits in the source code.
Andreas Rejbrand
You could try using a delimiter instead some kind of array (Note: I'm not a perl programmer)
TheLQ
@Lord Quackstar: well, this was my first quick attempt. My second attempt is at http://stackoverflow.com/questions/3324301/code-golf-digital-clock/3325229#3325229 and when I managed to do it in 192 chars, there was already another Perl solution at 155 chars.$a=' _ | | | _||_||_ ..';@a=split//,$a;$_=<>;map{$s[$_].=$map{$_=~s/.//;print$_.$/}@s;
ninjalj
+2  A: 

530 Characters - VB.Net 2008 Console App

not including white-space :(

otherwise its 926 hahaha

Dim inp As String = "19:27"
Dim l0 As String() = {" _ ", " ", " _ ", " _ ", "   ", " _ ", " _ ", "_ ", " _ ", " _ ", " "}
Dim l1 As String() = {"| |", "|", " _|", " _|", "|_|", "|_ ", "|_ ", " |", "|_|", "|_|", "."}
Dim l2 As String() = {"|_|", "|", "|_ ", " _|", "  |", " _|", "|_|", " |", "|_|", "  |", "."}
Dim _l As New List(Of String())
_l.Add(l0)
_l.Add(l1)
_l.Add(l2)

Dim i As Byte, j As Int16
For i = 0 To 2
    Dim wInp As String = inp
    For j = 4 To 1 Step -1
        wInp = wInp.Insert(j, " ")
    Next

    For Each tCh As Char In inp
        If Integer.TryParse(tCh, 0) Then
            wInp = wInp.Replace(tCh, _l(i)(Val(tCh)))
        Else
            wInp = wInp.Replace(tCh, _l(i)(10))
        End If
    Next
    Console.Out.WriteLine(wInp)
Next

EDIT: I changed the '7' to be only two characters wide because it looked awkward having a gap of 2 spaces between that and the prior number.

It was an aesthetic choice on my behalf, and if you include the additional spaces the character count goes up to 533 without white-spaces and 929 with white spaces.

EDIT2: First code-golf submission. Horray for bloatware!

EDIT3: Noticed some unnecessary code and such. Edited as such and removed about 150 characters worth.

EDIT4: Shortened up variable names. Changed Integer to Byte to save on 3 characters and turned Integer to Int16 to save on 2. Also remembered that I can pass in '0' instead of 'Nothing' for TryParse to save 6 characters.

Jeffrey Kern
You could shave off a lot with short variable names.
PeterK
I was aiming for legibility. lemme see if I can edit this and make it unreadable
Jeffrey Kern
Shortened variable names and changed some data types. I don't think I should trim anymore -I'm a fan of being able to read what the code does haha, though that defeats the purpose of golf :P
Jeffrey Kern
If someone can translate this to C#, i think it would be much shorter! Dim inp As String = string inp
Ranhiru Cooray
+13  A: 

PowerShell, 135 chars

$i="$input"[0..9]
'☺ ☺☺ ☺☺☺☺☺◘','♠☻♥♥♦♣♣☻♦♦•','♦☻♣♥☻♥♦☻♦♥•'|%{$c=$_
""+($i|%{('   0 _ 0  |0 _|0|_|0|_ 0| |0.0 '-split0)[$c[$_-48]]})}

(Note: This uses ASCII control characters in the strings and thus cannot be represented nicely here. I've used the respective Unicode character for the glyphs. Take the code from here for trying it out.)

Perl/Python/Ruby lovers? Where are you? Come on, this is a shame that PowerShell is shorter than any solution in Ruby.

History

  • 2010-07-24 10:25 (294) Initial solution.
  • 2010-07-24 10:32 (265) First try at golfing. Rolled the three pipelines into a loop. Shortened extraction of the input characters.
  • 2010-07-24 10:37 (230) Shortened number storage quite a bit by splitting a string.
  • 2010-07-24 10:38 (224) Splitting at a number is even shorter.
  • 2010-07-24 10:41 (219) Putting a pipeline around the splitting saves a few characters as well.
  • 2010-07-24 10:49 (210) Started golfing the numbers a little bit more. Must ... find ... patterns ...
  • 2010-07-24 10:52 (200) Who the hell needs more than a single jagged array for the numbers anyway?
  • 2010-07-24 12:16 (196) Shortened the other source strings a bit as well.
  • 2010-07-24 13:30 (202) Requirements have changed.
  • 2010-07-25 08:50 (188) Totally re-engineered. Same idea as the VB or C++ solutions.
  • 2010-07-25 09:20 (160) Some more optimizations of that approach. All arrays inlined ;-)
  • 2010-07-25 09:25 (150) Used an array directly instead of first passing indexes through the pipeline.
  • 2010-07-25 13:51 (143) Packed the strings into a single one again.
  • 2010-07-25 14:31 (140) The joys of having binary-safe strings ... :-)
  • 2010-07-26 00:59 (135) Evaluating an array in a string context separates with a space by default (overridable with $OFS), so we don't need -join' ' which was way too long.

The 196 byte version commented

Joey
I cannot really say that I understand this code...
Andreas Rejbrand
@Andreas: I added a link to a commented version of the code.
Joey
C# has gotten within a few strokes; I think it's time to refactor the PowerShell version.
Gabe
Ah, much better! PS is now within striking distance of Perl and Python...
Gabe
@Gabe: Beating Perl and Python by now. And the code is getting increasingly ugly (and cannot be entered without a hex editor anymore) ;-)
Joey
Too bad i cannot upvote this more than once. Amazing!
PeterK
Sweet! But there is a Perl solution claiming 140 chars: http://stackoverflow.com/questions/3324301/code-golf-digital-clock/3328207#3328207
Gabe
@Gabe: Better now? ;-)
Joey
Gah, 4 different solutions with 135 bytes ... my thoughts are drifting to ever weirder solutions. I give up now.
Joey
PowerShell is scary...
poke
@poke: I like it ;-)
Joey
@Johannes Rössel: It sure is, but seeing this (and other) code is still scary :o
poke
@poke: Well, the very first revision shows readable code, if you like that better ;)
Joey
+3  A: 

Delphi - 449 426 372 354 characters

program a;{$APPTYPE CONSOLE}var o:array['1'..'9'] of string=('   ','  |',' ',' _ ',' _|','.','| |','|_ ','|_|');d:string='414414444437255988299692852592956';s,t,u:string;c,i:byte;begin for i:=1 to 5 do begin c:=ord(ParamStr(1)[i])-47;if i>1 then begin s:=s+' ';t:=t+' ';u:=u+' 'end;s:=s+o[d[c]];t:=t+o[d[c+11]];u:=u+o[d[c+22]]end;write(s,#10,t,#10,u)end.

Edit 1: Changed the data array to a single-dimensional array.

Edit 2: Instead of repeating the data strings, define only the possible strings and index into them.

Edit 3: Updated to meet new font for output, shaving off about 18 characters.

(Semi-)readable version:

program a;

{$APPTYPE CONSOLE}

var o:array['1'..'9'] of string=('   ','  |',' ',' _ ',' _|','.','| |','|_ ','|_|');
d:string='414414444437255988299692852592956';
s,t,u:string;
c,i:byte;

begin
  for i:=1 to 5 do begin
    c:=ord(ParamStr(1)[i])-47;
    if i>1 then begin s:=s+' '; t:=t+' '; u:=u+' 'end;
    s:=s+o[d[c]]; t:=t+o[d[c+11]]; u:=u+o[d[c+22]]
  end;
  write(s,#10,t,#10,u)
end.

Output:

C:\Users\Michael Madsen\Documents\RAD Studio\Projects>a 19:27
     _     _   _
  | |_| .  _|   |
  |  _| . |_    |
C:\Users\Michael Madsen\Documents\RAD Studio\Projects>a 11:11

  |   | .   |   |
  |   | .   |   |
Michael Madsen
Works! --------
Andreas Rejbrand
Delphi for code golf??
Camilo Martin
@Camilo Martin: at least noone has submitted Cobol or Intercal...
ninjalj
+24  A: 

VB.NET, 228 221 210 214 202 characters

(damn Console.Write is so anti-codegolf InputBox("") and MsgBox() are cheaper)

p="202202222284133655166761531361637     | _  _|| ||_ |_|."
i=InputBox("")
For l=0To 2
For x=0To Len(i)-1
k=Asc(i(x))-48
b=Val(p(k+l*11))
o+=Space(-(x>0))
o+=If(b=8," ",Mid(p,b*3+34,3))
Next
o+=vbLf
Next
MsgBox(o)

At least I beat Perl (and others too!) :}

Edit:

Explaination

Instead of using 3x3 = 9 characters for each digit, I have converted the possible strings for each character into an integer:

"   " -> 0
"  |" -> 1
" _ " -> 2
"| |" -> 4
" _|" -> 5
"|_|" -> 6

and

"." -> 7
" " -> 8 (top of colon only)

So I take the Ascii equivalent of each character from the input (: is conveniently placed right after 9), subtract 48 (gives 0 to 10) and then find the equivalent integer into my initial string (adding 11 * <current line>).

The rest is bit-testing mumbo jumbo.

Output:

alt text

Update:

  • Added 4 characters in order to be in accordance to the rules (thanks Nabb)
  • Removed trailing space (thanks Michael Madsen)
  • New method: now 100% compatible with the requirements (space-wise) and even less characters.
  • Corrected the colon symbol (: to .)
  • New screenshot (thanks Johannes Rössel)
Anax
WTF. I'm decent in VB but holy cow I dont get this code. What is P and how did u come to that solution?
Jeffrey Kern
It's.... magic!
Anax
@Jeffrey Kern: It has nothing to do with your knowledge of the programming language by itself. It is just a matter of understanding the logic of the current solution. (Which I don't either.)
Andreas Rejbrand
Could you produce sample IO? The code suggests whitespace between characters is being omitted.
Nabb
@Nabb: Corrected (+4 chars) and added sample output. Well spotted.
Anax
@Anax: If I'm not mistaken, your code violates the requirement not to have trailing spaces after the last character - it doesn't look like you only add that final space for the first 4 characters.
Michael Madsen
@Michael Madsen: Now 100% compatible with the rules.
Anax
anax: Not quite ... the colon should be a dot.
Joey
@Johannes Rösse: Well spotted, thanks!
Anax
You may want to update that screenshot too ;)
Joey
@Johannes Rössel: There you go :)
Anax
+3  A: 

C++, 295 bytes

including whitespace, tabs and windows crlf newlines.

#include <stdio.h>
char* d=" _     _  _     _  _  _  _  _    | |  | _| _||_||_ |_   ||_||_| . |_|  ||_  _|  | _||_|  ||_| _| . ";
int main(int a,char** s){
    for (int i=0,k;i<15;i++){
        k=(s[1][i%5]-48)*3+(i/5)*33;
        printf("%.3s",&d[k]);
        if (!((i+1)%5))printf("\n");
    }       
    return 0;
}
SigTerm
+7  A: 

Python 3, 176 170 174 164 chars

j=''.join
t=input()
for i in 0,3,6:print(j(c<':'and j([(' ','|_|'[x%3])[0x375fa9176b3538d93ca41ea>>x&1]for x in range(90)][int(c)*9+i:][:3])or'. '[i<1]for c in t))
Marco Mariani
I don't understand a single character of that, but it's beautiful :-O
Thomas
aarg, my hands kept posting the wrong version. basically the number is a bitmask of the leds (3 bits for each row). the '|_|' converts the bit to the led shape.
Marco Mariani
reverted: the input() must stay out of the loop, or it will be called for each line.
Marco Mariani
@Marco: my bad re input()! how about replacing `'. '[not i]` with `' ..'[i/3]`, 1 char less?
Nas Banov
no, because in python3, i/3 is a float. so it would be i//3, 0 less chars
Marco Mariani
@Marco: `[i>0]` then, for 2char savings?
Nas Banov
'. '[i<1], and I removed another silly repetition
Marco Mariani
+18  A: 

GolfScript - 98 chars

3,{:S;.{48-"9>99>99999CWVV[[B>[[N*D%*C+*D*(""}"{base}/31/S=3/=2+{"._ |"=}%}%){;).32=}do[][email protected]}/;;

Replace \5 with the appropriate character. Ensure that there is no newline after the input (or prefix the code with n- to remove any).
This uses fixed-width numbers. For variable-width, use:

"9z9k>99k99CcV[[BH[[N,v'*C+,D*("
  • (120) Initial solution of 120 chars. Commence golfing.
  • (114) Removed variables, removed extraneous newline at end.
  • (112) Optimized data unpacking.
  • (110) Changed 'blank' character to newline.
  • (107) Changed 'blank' character to an index in the array which doesn't exist.
  • (107) Removed extraneous space in 11:11, moved spacing between characters.
  • (104) Further optimized data unpacking.
  • (102) Removed extraneous 1/ (i.e. changed array lookup to string lookup).
  • (99) Made 'blank' characters before .'s implicit.
  • (98) Relocated and changed trailing space removal.
Nabb
Mind explaining what the heck "9z9k>99k99CcV[[BH[[N,v'*C+,D*(" is?
TheLQ
"Replace \5 with the appropriate character." Where's that?
Vincent
+17  A: 

Python 3, 202 176 170 167 characters

Now using the new fixed-width rules. It's not even very obfuscated. Note that : is conveniently after 9 in the ASCII table. With added line breaks and indentation:

i=input()
s=' _ '
t=s+'   '+s
for q in[t*2+s*4+' ',
         "| |  | _| _||_||_ |_   ||_||_|.",
         "|_|  ||_  _|  | _||_|  ||_| _|."]:
    print(' '.join(q[ord(x)*3-144:][:3]for x in i))

Using Python 3 saves four chars on raw_ and costs two in adding parentheses to print.

$ echo '19:27' | python3 clock.py 
     _     _   _ 
  | |_| .  _|   |
  |  _| . |_    |

I think I've reached the limit of this algorithm. To get it even shorter, we'll really need to get rid of those long strings.

Thomas
but is it code golf if it's readable? :)
Marco Mariani
I guess nobody bothers. I like this python piece the most.
Cheery
I didn't bother for readability either; but it just turned out pretty short anyway.
Thomas
@Marco: Readability and golfing are orthogonal to each other. They can coexist quite nicely. Also above code is formatted; readability suffers when viewing it in golfed form. Still, I sometimes hate that my language of choice essentially forces me to write readable golf code which could be shorter otherwise.
Joey
I was joking, it was a kind of praise :) I imagine from a readability vs compactness point of view, haskell has an advantage over python (for non-trivial programs). Must. Study. It.
Marco Mariani
+40  A: 

Python, 156 152 147 145 chars

s=raw_input()
for i in 0,1,2:print' '.join(c<':'and'    | |_ _ _|_|'[2*(0x2e9b426672b870b63b09194>>9*ord(c)+3*i-432&7):][:3]or' ..'[i]for c in s)

output for '12:34:56:78:90'

     _     _         _   _     _   _     _   _ 
  |  _| .  _| |_| . |_  |_  .   | |_| . |_| | |
  | |_  .  _|   | .  _| |_| .   | |_| .  _| |_|

How does it work:

The string ' | |_ _ _|_|' contains all the possible 3-symbol pieces needed to construct the digits - it just depends where you start looking for it. The magic number shifted by the digit's ascii code and line number (9*ord(c)+3*i-432&7) points at the right place in the template. Then [:3] cuts the string after 3 characters. The colon is handled as a special case in ' ..'[i]


Python, 199 174 167 165 154 bytes

i=raw_input()
for y in'05009000005','67113224338','37214134318':print' '.join(' _ , _|,|_ ,|_|,  |, ,| |,|,.,   '.split(',')[int(y[ord(x)-48])]for x in i)

Example:

$ echo 0123456789: | python script.py
 _     _   _       _   _   _   _   _   
| | |  _|  _| |_| |_  |_    | |_| |_| .
|_| | |_   _|   |  _| |_|   | |_|  _| .

How does it work:

The string ' _ , _|,|_ ,|_|, |, ,| |,|,., ' contains all needed horizontal parts, but stored separately. The number arrays are pointers to that string. For example 0 consists of the following parts:

0 -  _ 
6 - | |
3 - |_|
viraptor
cute and also works with days longer than 99 hours
Marco Mariani
http://dpaste.com/hold/221520/Looks like 161 to me.
Nick Presta
removed spaces, but I can't remove i - raw_input() can be read only once.
viraptor
Ah true. I didn't think about that. Good catch.
Nick Presta
Could you explain the code?
iceburn
145->144 with input() and print()
Marco Mariani
@iceburn - Added some simple descriptions - hope they're clear enough.
viraptor
@Marco: 145-2=143, perhaps? (Python3)
Nas Banov
it depends, should we count the '\n' in the last line? i feel silly :)
Marco Mariani
This is beautiful blasphemy
Jamie Wong
+8  A: 

Haskell, 248 199 characters

Line breaks and indentation added for clarity.

import Data.Char
main=interact$ \t->unlines
  [unwords
    [take 3$drop(ord x*3-144)d|x<-take 5 t]|
     d<-[" _     _  _     _  _  _  _  _  "
        ,"| |  | _| _||_||_ |_   ||_||_|."
        ,"|_|  ||_  _|  | _||_|  ||_| _|."]]

Now with the new fixed-width rules.

Thomas
+12  A: 

C++ 174 bytes

with unnecessary whitespace removed.

#include <stdio.h>
int main(int a,char**s)
{
    for(a=0;a<15;a++) printf("%.3s%s","    _   ||_  _|| ||_| . "+
            ((*("n\022cd2\\^Rvt?"+s[1][a%5]-48)>>(2-a/5)*3)&7)*3,(a+1)%5?"":"\n");
}

Or, more readably:

#include <stdio.h>
char* d="n\022cd2\\^Rvt?    _   ||_  _|| ||_| . ";
int main(int a,char** s){
    for (int i=0,k;i<15;i++){
        k=((d[s[1][i%5]-48]>>(2-i/5)*3)&7)*3+11;
        printf("%.3s",&d[k]);
        if (!((i+1)%5))printf("\n");
    }       
    return 0;
}

Explanation.

Solution is somewhat similar to this one, however it differs in details.

If you look carefully at a numbers in digital clock, that you'll notice that there is no such number that uses this element:

"|  "

Clock is divided in 3 rows, and each row has 8 possible states:

"   " //0x00
" _ " //0x01
"  |" //0x02
"|_ " //0x03
" _|" //0x04
"| |" //0x05
"|_|" //0x06
" . " //0x07

State for each row can be stored using 3 bits instead of 4 bits if you associated 1 bit for every element ("| ", " |", " _ ", " . "). Also top row is always either 0x00 or 0x01. Therefore, each clock number can be represented as octal number where each octal digit corresponds to a state of certain row. "zero" will be 0156, "one" will be 0022, and so on. After that I only had to encode numbers into ascii(when possible - see \022), and appended character representation of possible states to original array. The rest is arithmetical black magic.

It probably can be made even shorter, but I see no way to do that at the moment.


Sample io:

>digitalclock.exe 12:41
    _
  | _| . |_|  |
  ||_  .   |  |

>digitalclock.exe 12:03
    _     _  _
  | _| . | | _|
  ||_  . |_| _|

>digitalclock.exe 14:56
          _  _
  ||_| . |_ |_
  |  | .  _||_|

>digitalclock.exe 17:59
    _     _  _
  |  | . |_ |_|
  |  | .  _| _|

>digitalclock.exe 17:09
    _     _  _
  |  | . | ||_|
  |  | . |_| _|
SigTerm
Very clever solution! But you should probably edit your previous answer instead of posting another one if its the same language and similar idea.
PeterK
@PeterK: I've decided to keep both solutions, because they use slightly different approach, and the longer one is easier to understand. Also, I've rewritten the code...
SigTerm
There should be a space between two numbers.
KennyTM
+5  A: 

VB.Net, 97 94 characters

f=new Form
l=New Label
l.Font=New Font("DS-Digital",9)
l.Text=InputBox("")
f.Controls.Add(l)
f.Show

PS: You might need the DS-Digital fonts.

Anax
Funny answer, but not really in the spirit of code golf.
mattmc3
You should check other code golfs then ;)
Anax
Make that 9 pt for the font and you save three characters.
Joey
Cheater (15 chars)
TheLQ
+3  A: 

Perl, 247 chars

$n="}D>nGk{L\x7fo";@a=unpack "C*",$n;$_=<>;chop;@v=split//;sub f{$h=shift;join(' ',map $_ eq':'?'.':($a[$_]&$h?'|':' ').($a[$_]&$h*2?'_':' ').($a[$_]&$h*4?'|':' '),@v)."\n";}print join(' ',map $_ eq':'?' ':$a[$_]&8?' _ ':'   ',@v)."\n".f(1).f(16);
ninjalj
+7  A: 

Perl 202, 177, 167, 152 chars

the last newline is requirred

map{map{$o[$m++%3].=substr'     |  . _  _|| ||_ |_|',3*$_,3}split//,qw(257 011 346 344 071 364 367 311 377 374 022)[-48+ord$_]}<>=~/./g;$"=$/;print"@o
"

Perl 5.10 197, 173, 163, 149 chars

map{map{$o[$m++%3].=substr'     |  . _  _|| ||_ |_|',3*$_,3}split//,qw(257 011 346 344 071 364 367 311 377 374 022)[-48+ord$_]}<>=~/./g;$"=$/;say"@o"

With newlines :

map {
  map {
    $o[$m++%3] .= substr('     |  . _  _|| ||_ |_|', 3*$_, 3);
  } split//,qw(257 011 346 344 071 364 367 311 377 374 022)[-48 + ord($_)]
} <> =~ /./g;
$" = $/;
print "@o$/"

usage:

echo 12:34| perl digital.pl
M42
+3  A: 

C, 280 278 275 274 chars

char*n="|w$]m.k{%\x7fo",x[18],y[18],z[18],i,c,a,s;main(int u,char**v){u=95;s=32;
while(c<5){y[i]=(a=n[v[1][c++]-47])&2?*n:s;x[i]=s;z[i]=a&16?*n:s;y[++i]=z[i]=a?s
:46;x[i]=a&1?u:s;if(a&8)y[i]=u;if(a&64)z[i]=u;x[++i]=s;y[i]=a&4?*n:s;z[i++]=a&s?*
n:s;}printf("%s\n%s\n%s\n",x,y,z);}

newlines for readability. Note that the data contains a \x7f for readability, which can be stored as 1 byte.

Output

$ ./a.out 12:34; ./a.out 56:78
    _     _
  | _| .  _||_|
  ||_  .  _|  |
 _  _     _  _
|_ |_  .   ||_|
 _||_| .   ||_|
mvds
Nice one with the character constant. But I think you're supposed to read from stdin.
Thomas
There should be a space between two numbers.
KennyTM
+6  A: 

JavaScript, 262 255 210 characters

(including the 3 line breaks shown)

s='';a=prompt()
for(r in n=['23567890x:14','xx17x56x489x32x:x0','xx147x2x068x359x:']){for(e in a)for(i in t=n[r].split('x'))if(t[i].match(a[e]))s+=' _      ||_ |_| _|.  | |'.match(/.{3}/g)[i];s+='\n'}
alert(s)

works in firefox (not in Chrome for some reason).

If your alertbox doesn't have a monospaced font, then you need to document.write instead.

I tried all sorts of eval() and removing code, but this is the shortest I can get -- no eval() needed :-). 'n' contains string representations of arrays (split by 'x'), containing possible digits. The second string (now buried in the middle to save 5 bytes) contains clock display elements that match those digits.

I'm sure that even more common patterns can be factored out of the string by correlating the digits to ascii char codes

Variation on the theme:

Auto-updating HTML clock (shows current time) - 375 characters

<pre/><script type="text/javascript">
setInterval("s='';d=new Date();m=d.getMinutes();for(r in(n=['23567890x:14','xx17x56x489x32x:x0','xx147x2x068x359x:'])){for(e in(a=d.getHours()+':'+((m>9)?m:'0'+m)))for(i in(t=n[r].split(/x/)))if(t[i].match(a[e]))s+=' _      ||_ |_| _|.  | |'.match(/.{3}/g)[i];document.getElementsByTagName('pre')[0].innerHTML=s+='\\n'};",500)

(it's not the most efficient any more... I moved getElementsByTagName inside the loop because it allowed me to shave off 1 character... and I stopped using getElementById because this way I could use a self-closing html tag and save another 3 characters! Not to mention that it refreshes every 0.5 sec for a clock with no seconds display :-) But, it works, and is short -- and that's all that counts.)

Jhong
ooops, sorry, looks like I overwrote your changes. Feel free to revert.
Pumbaa80
All good -- it's almost the same with a few characters shaved off :-)
Jhong
It's down to 238 now anyway :-)
Jhong
Make that 233...
Jhong
OK... 225.. I think I'm done now.
Jhong
Remember back in the days when people had JS-powered clocks floating around on their websites around the mouse cursor? Back then I hadn't learned about Sine/Cosine yet, so the code was magical.
ItzWarty
Haha yes, it still is magic :-)... OK 213 now... I'll be happy when I get it to 199
Jhong
..... 210 .....
Jhong
+5  A: 

C, 232 228 characters

In this one, long is assumed to be at least 64 bits. Compiles with gcc with some warnings about implicitly declared functions.

char*a=" _|.",*q,v[6];long b[]={0x104104100104004,0x39a68061a6924822,
0x3926826920906826,0},*d=b,c;main(){for(scanf("%5s",v);*d;putchar(10)
,++d)for(q=v;*q;*++q?putchar(32):0)for(c=6;c>*q/58*4;c-=2)putchar(a[*
d>>(6**q-282-c)&3]);}

Readable version:

char *a = " _|.", *q, v[6];
long b[] = {0x104104100104004, 0x39a68061a6924822, 0x3926826920906826, 0}, *d = b, c;
main() {
    for (scanf("%5s", v); *d; putchar(10), ++d)
        for(q = v; *q; *++q ? putchar(32) : 0)
            for (c = 6; c > *q / 58 * 4; c -= 2)
                putchar(a[*d >> (6 * *q - 282 - c) & 3]);
}
Thomas
+4  A: 

C#/LINQ - 203 206 212 226 243 249 260 298 bytes

Minified (line-breaks for "readability")

using System.Linq;class M{static void
Main(string[]i){for(int
l=64;l>0;l/=8)System.Console.WriteLine(string.Join(" ",i[0].Select(c=>".  _   _|_|_  | |".Substring("|¶][¦klvdcÀ"[c-48]/l%8*2,c>57?1:3))));}}

Slightly more readable

using System.Linq;

class M
{
    static void Main(string[]i)
    {
        for (int l = 64; l > 0; l /= 8)
            System.Console.WriteLine(
                string.Join(" ",
                    i[0].Select(c=>
                    ".  _   _|_|_  | |"
                    .Substring(
                        "|¶][¦klvdcÀ"
                            [c - 48]
                            / l
                            % 8
                            * 2,
                        c > 57 ? 1 : 3)
                    )
                )
            );
    }
}

Note that accepting input via the command line saves 17 strokes over accepting it from stdin.

Bauer
Really good, but you can get this shorter by changing your Main() to Main(string[] i), by using a variable for your output and writing it at the end, and by rethinking your really long string of all the chars you'll be outputting. Hint - there's only 8 3-char string sequences needed to write every numeral and the : separator.
mattmc3
mattmc3: You're right that using stdin for input and rethinking the long string were good ideas, but I don't see how using a variable for output and writing it at the end would help. There's already only one `WriteLine`.
Gabe
+16  A: 

K, 120 characters

Using Kdb+'s K4:

r:0N 3#;i:-48+"i"$;.z.pi:{-1',/'" ",''+(" ",".",r"     | _  _|| ||_ |_|")(i r"468233457455283475478433488485011")i 5#x;}

Example:

$ echo 19:27 | q d.k
      _     _   _ 
   | |_| .  _|   |
   |  _| . |_    |

Bonus variant: absolutely straightforward, slightly longer (147 chars, with newlines trimmed), but (at least to my eyes) quite beautiful:

.z.pi:{-1',/'" ",''(0N 3#/:(" _     _  _     _  _  _  _  _  "
                            "| |  | _| _||_||_ |_   ||_||_|."
                            "|_|  ||_  _|  | _||_|  ||_| _|."))[;-48+"i"$5#x];}
earl
+1 for WTFness and you made me read the "K"-wikipedia article :)
tobsen
The prettiest of all!
Camilo Martin
+3  A: 

C++, 178 chars

#include<stdio.h>
int main(int i,char**p){for(i=0;i<60;i+=i%20-8?1:3)putchar(~i%20?"<!Zjchx)|lt"[p[0][i%20/4]-48]+3>>(i%4*5+i/20*3+7)%9&1?".|_| "[i%4+(i%20!=8)]:32:10);return 0;}

A simple loop:

for ( i = 0 to 59 ) print_character(f(i))

The string "<!Zjchx)|lt" contains the info for the seven-segment display. Each character encodes 7 bits for each digit, plus the semicolon. The semicolon happens to follow the digit 9 in ASCII order.

Tom Sirgedas
+2  A: 

VB.NET - 189 chars

Compiled with Option Explicit Off and Option Strict Off. 'a' is the argument variable, and doesn't have to be a valid time... it could be any sequence of numbers from 0-9 and the colon.

y = "    _  _||_||_   || | . "
z = "163055124122035142143155133132077"
o = ""
For j=0 To 2
For Each c In a
i = If(c=":"c,10,CStr(c))
o+=" "+y.Substring(CStr(z(i*3+j))*3,3)
Next
o+=vbLf
Next
MsgBox(o)

A few things to note - VB (in all its type un-safety wisdom) with Option Strict Off can flip types behind the scenes, but it didn't do the char->int conversions the way I wanted, so I had to CStr(). Also, to get around the sticky requirement that it can't have trailing spaces, it has starting spaces. And finally, I went with the convention the other VB.NET submissions had of not putting "Module M, Sub Main(), End Sub, End Module". So code-golf-wise, this solution doesn't beat any of the other languages, but it beats all the current VB.NET submissions.

mattmc3
Very good. Now, Instead of `Substring` use `Mid`
Anax
By the way, there's no input in your code.
Anax
Input variable is 'a' as per my comments.
mattmc3
You're also right about Mid saving me 5 or 6 more characters, but I would have had to look up how to use it again and since I've been happily Mid() free for nearly a decade, I wasn't sure I was willing to break the streak. Who knows what sorts of classic ASP nightmares I'd have tonight if I did that.
mattmc3
+4  A: 

I attempted to combine two approaches here around, but my unpacker got larger than the data.

Python, 186 bytes

i=input()
a=' |_.'
u=int('578aouoegk9ddv86r2nxu2mjiqkg',36)
for q in 144,111,78:print(' '.join((lambda c:a[c&3]+a[c/4&3]+a[c>>4&3])(u>>(u>>43>>(ord(x)*3-q)&7)*6)[:x>'9'or 3]for x in i))

At least it's quite scary.

Cheery
you can use `0x3e8a65aa9e456cd9304924120d8259450200` with the same effect, same length as `int('578aouoegk9ddv86r2nxu2mjiqkg',36)`
Nas Banov
What language is this in?
EricR
@EricR, python, ofcourse! :)
st0le
+1 for using base 36 "just because"
Marco Mariani
Gabe
nice proposal, makes it look even more horrible.
Cheery
and how about inlining the lambda? :) e.g. `f=lambda x:...; f(y)` can be inlined to `(lambda x:...)(y)`
Nas Banov
2 bytes dropped that way.
Cheery
+1  A: 

Ruby - 242 228 223 Bytes

_=[" _ ","   ","  |","| |"," _|","|_ ","|_|"];a=[36,122,45,44,162,54,56,32,66,64];x=y=z="";gets.chop.split(//).each{|c|if c==':';x+="  ";y+=" .";z+=" .";else;d=a[c.to_i];x+=_[d/100];y+=_[d/10%10];z+=_[d%10];end;};puts x,y,z

Here's the readable version...

_=[" _ ","   ","  |","| |"," _|","|_ ","|_|"]
a=[36,122,45,44,162,54,56,32,66,64]
x=y=z=""
gets.chop.split(//).each{|c|
if c==':'
    x+="  "
    y+=" ."
    z+=" ."
else
    d=a[c.to_i]
    x+=_[d/100]
    y+=_[d/10%10]
    z+=_[d%10]
end
}
puts x,y,z
st0le
+8  A: 

Perl, 143 (140) char

Just to show how similar this question is to this question (and to continue my homage to hobbs' code-golf solutions), I present this solution:

@s=unpack"C*",~"P\xdbLI\xc3a`[\@A";
$_=<>;for$s(6,3,0){print$&eq':'?$s<6?".":$"
:map$s[-48+ord$&]&1<<$_+$s?$_%2?"_":"|":$",0..2while/./g;print$/}

The astute reader will notice the similarity to this other code-golf solution. And I suspect the unastute reader will as well.

A slightly shorter and slightly less similar solution is

$_=<>;for$s(6,3,0){print$&eq':'?$s<6?".":$"
:map+(unpack"C*",~"P\xdbLI\xc3a`[\@A")
[-48+ord$&]&1<<$_+$s?$_%2?"_":"|":$",0..2while/./g;print$/}
mobrule
You beat the Python! But it's very close...
Thomas
+2  A: 

Scala 2.8 - 188 bytes (without whitespaces)

val (l, s) = (readLine, " |_.")
val t = for(i <- s; j <-s ; k <- s) yield ""+i+j+k
Seq(0x1084210042008L, 0x33390e3194a431L, 0x31390e5214e039L)
  .map(x => println(l
    .map(v => t((x >> 5*(v-48) & 31).toInt))
    .mkString))

The for instruction creates a sequence of every combinations of 3 characters using space, |, _, and . (there are 64 combinations).

The weird numbers are actually composed of 11 packets of 5 bits, each packet is a value of an index in the combination list. 11 is the number of input symbols (0 to 9 and .). 5 bits is the size required to store the 64 values used for indexing the combination list. Fortunately, 5x11 < 64, the size of the Long type I use for storing those weird numbers.

There is one weird number for each line to print (that is, 3).

barjak
+3  A: 

Ruby (181 characters)

puts ARGV[0].each_byte.map{|b|b==58?[' ','.','.']:[[7,0,7],[1,3,2],[4,6,5]].map{|p|p.map{|i|"w$]m.k{%\x7Fo"[b-48].ord[i]>0?i%3>0?"|":"_":" "}.join}}.transpose.map(&:join).join"\n"
gineer
+2  A: 

Common Lisp - 322 299 characters

(defun d (s)
  (labels ((m (s) (map 'list (lambda (x) (- (char-code x) 48)) s))
       (v (n x) (subseq (subseq " _ _|_|_   | | . " (elt (m x) n)) 0 3))
       (p (n) (v n "08008000008")) 
       (q (n) (v n ";922466944>")) 
       (r (n) (v n "4962924942>")))
    (let ((b (m s)))
      (format t "~{~a~}~%~{~a~}~%~{~a~}~%" (mapcar #'p b) (mapcar #'q b) (mapcar #'r b)))))

The line pattern uses overlapping triplets and is arranged to minimize the number of two-digit indices.

map 'list ... is marginally shorter than loop for c across ... collect and (subseq (subseq ... is marginally shorter than keeping the start index in a let to calculte the end index.

Paul Richter
+3  A: 

Perl - 191 characters

Just trying my hand. The data could certainly be compressed further, but at least it's pretty readable, as Perl solutions go. Newlines for presentation only. Like some other answers, actually handles any five-character string of digits and colons.

chop($i=<>);
$d="    _ | ||_|  | _||_  . 1011011111024553664337346545343570";
for(1..3){$_=$i;s/(\S)/S(-48+ord$1).' '/eg;s/\s*$/\n/;print}
sub S{substr$d,3*(substr$d,24+11*int($x++/5)+$_[0],1),3}

I wasn't sure whether the trailing-spaces restriction still applied, so it's possible to replace s/\s*$/\n/;print with print"$_\n" for a savings of five characters if trailing spaces are allowed. Easy usage:

echo '19:27' | perl clock.pl

Output:

     _       _   _
  | |_|  .   _|   |
  |  _|  .  |_    |
Jon Purdy