# Challenge

Your task is to output the time (in 12 hour time) in ascii art.

All characters that will be used are as follows:

  ___    __   ___    ____    _  _     _____     __    ______
/ _ \  /_ | |__ \  |___ \  | || |   | ____|   / /   |____  |
| | | |  | |    ) |   __) | | || |_  | |__    / /_       / /
| | | |  | |   / /   |__ <  |__   _| |___ \  | '_ \     / /
| |_| |  | |  / /_   ___) |    | |    ___) | | (_) |   / /
\___/   |_| |____| |____/     |_|   |____/   \___/   /_/

___     ___
/ _ \   / _ \                                _
| (_) | | (_) |   __ _ _ __    _ __ _ __     (_)
> _ <   \__, |  / _ | '  \  | '_ \ '  \     _
| (_) |    / /   \__,_|_|_|_| | .__/_|_|_|   (_)
\___/    /_/                 |_|


(For each number/symbol individually, consult this gist).

You will receive input in an array of the form:

• [hours, minutes, 'am/pm']. For example, [4, 57, 'am'], with single quotes only used for am/pm
• or "hours-minutes-am/pm". For example, "4-56-am"
• or [hours, 'minutes', 'am/pm'] for languages that cannot handle leading zeroes on numbers. For example, [4, '07', 'am']

You may use either input method.

Output will be in the form 1 2 : 5 9 am, where there is one initial space, two spaces between each number (in the gist, each number already has one space on each side), one space between : (colon) and the neighbouring numbers, and one space between the last number and am/pm, with an optional leading and/or trailing newline. All spaces are between the right-most point of the symbol on the left and the left-most point of the symbol on the right.

Implicit output is allowed.

Lowest byte size wins.

The am/pm are to be aligned such that the bottom of the p in pm is aligned with the bottom of the rest of the output, that is, the undercore denoting the top of am/pm starts on the third line down (not counting a leading newline).

The colon is to be aligned such that it's first character (an underscore) starts on the second line down (not counting a leading newline).

For minutes < 10, output the minutes with a leading 0 (you should receive this in the input). For example, [8, 04, 'pm'] -> 8 : 0 4 pm.

You must not fetch the data for the numbers from a library or external resource. All data must be contained within the program.

For example, for the input [12, 47, 'am'], the output would be as follows:

  __    ___          _  _      ______
/_ |  |__ \    _   | || |    |____  |
| |     ) |  (_)  | || |_       / /   __ _ _ __
| |    / /    _   |__   _|     / /   / _ | '  \
| |   / /_   (_)     | |      / /    \__,_|_|_|_|
|_|  |____|          |_|     /_/


(If you see any edge cases that you can't decide what to do with, please post in comments and I will add them to examples).

• Possible duplicate of Render "Digital Clock Style" Numbers – Mego Feb 16 '16 at 7:28
• @Mego you reckon? That question simply says render (any) number as (very) basic ascii art. This question beefs up the ascii art, adds the am/pm and colon, and specifies input with an array with a mix of types. – user31556 Feb 16 '16 at 7:32
• Specifically: that question is clock-style numbers. This question is actual time, with all the right formatting. – user31556 Feb 16 '16 at 7:33
• The different format of the numbers and the addition of the colon and am/pm do little to differentiate the challenges imo. The main part of the challenge is still converting integers to ascii art. – Mego Feb 16 '16 at 7:34
• @Mego I don't think this is a duplicate. The other challenge has that ultra simple formatting (even compressable as binary). This one will probably get more kolmogorov-complexity-like answers. – PurkkaKoodari Feb 16 '16 at 8:50

# Perl, 592579540522 510 bytes

Under a sector!

($L,$C,$b)=unpack"W/aW/aB*",q!12346677889999 _|/\)( '<,>. PP¨ ¨@T @ôäð˜SÀ§€fÌUà¨Àäð'€GÖf3 X½fÍ5 s Î|½gËÖ—$¡))õ™˜À8Sô BÁªx~O àÔýåËþÏÃÆ~O‡ŸY¬Àf s
½À*õŸ/X8|½p>^€<¯å­kgúºÖ·ÓÊ¸°ªÀj® kª¸•p¸å\×   ­ô!;@c=map{$i<<=$_-$P if$_>$P;$P=$_;sprintf"%${l}b",$i++}$L=~/./g;while($b){$b=~s/^$c[$_]// and$g.=($C=~/./sg)[$_]for 0..$#c}$_=pop;s/-/:/;y/apm-/;</d;for$a(0..5){map{$o.=substr((split$/,$g)[$a],($x=-48+ord)*12,('6356766766099'=~/./g)[$x]+3)}/./g;$o.=$/}print$o  This program expects the time in the 2nd format ("12-34-am") as a commandline argument. Commented: ($L,$C,$b) = unpack "W/aW/aB*",             # extract code lengths, chars, and bitstream
q!12346677889999 _|/\)(
'<,>. PP¨
¨@T @ôäð˜SÀ§€fÌUà¨Àäð'€GÖf3 X½fÍ5 s Î|½gËÖ— $¡))õ™˜À8Sô BÁªx~O àÔýåËþÏÃÆ~O‡ŸY¬Àf s ½À*õŸ/X8|½p>^€<¯å­kgúºÖ·ÓÊ¸°ªÀj® kª¸•p¸å\× ­ô!; @c = map { # reconstruct huffman prefix codes$i <<= $_-$P if $_ >$P;                # increase code size
$P =$_;                                # keep track of previous code
sprintf "%${l}b",$i++                  # append code as bitstring
}
$L=~/./g; # canonical huffman prefix lengths while ($b ) {                              # decompress font
$b =~ s/^$c[$_]// # match and strip prefix code and$g .= ($C=~/./sg)[$_]           # append char for prefix code
for 0..$#c # iterate prefix codes in order } # luckily we can omit checking trailing bytes$_ = pop;                                   # get cmdline arg "12-34-am"
s/-/:/;                                     # ord(':')-ord('0')=10
y/apm-/;</d;                                # 'a'-> chr(11), 'p' -> chr(12), strip -,m
for $a (0..5) { # iterate 6 output lines map { # iterate each char in input$o .= substr(
( split $/,$g )[$a], # grab line$a
( $x=-48+ord ) * 12, #$x=glyph index, 12=glyph width
('6356766766099'=~/./g)[$x]+3 # glyph display width ) } /./g;$o .= $/ # append newline } print$o                                    # output


Note that due to character encoding issues, when you paste the above code in a file, the output may be somewhat malformed. So here's the golfed version, base-64 encoded. Copy it, and paste it into base64 -d > 510.pl:

KCRMLCRDLCRiKT11bnBhY2siVy9hVy9hQioiLHEhDjEyMzQ2Njc3ODg5OTk5DiBffC9cKSgKJzws
Pi5gFQBQAVACqAIgCqgBQBVUAqAFQAH05PAOmANTwBqngGbMBlVgHOAaqMDk8AcngEfWZmAzAA9Y
Ar1gZs0DNQBzoAHOBny9YGfL1g+XoAUkoSkp9ZmYDMAHOANT9A1Cwap4Bn5PABzgH9T9AeV/GBAB
y/7Pw8Z+Tx+Hn1mswGYAc6AKvWAMwCr1gZ8vWAc4Bny9YA5wPl6APK/lrWtn+rrWt9PKuAawBqrA
c3ByaW50ZiIlJHtsfWIiLCRpKyt9JEw9fi8uL2c7d2hpbGUoJGIpeyRiPX5zL14kY1skX10vLyBh
bmQkZy49KCRDPX4vLi9zZylbJF9dZm9yIDAuLiQjY30kXz1wb3A7cy8tLzovO3kvYXBtLS87PC9k
O2ZvciRhKDAuLjUpe21hcHskby49c3Vic3RyKChzcGxpdCQvLCRnKVskYV0sKCR4PS00OCtvcmQp
KjEyLCgnNjM1Njc2Njc2NjA5OSc9fi8uL2cpWyR4XSszKX0vLi9nOyRvLj0kL31wcmludCRv


Here's the font I'm using. I've spaced the glyphs 12 characters apart (the size of the am/pm) for easy indexing.

   ___        __          ___         ____        _  _        _____         __        ______       ___         ___
/ _ \      /_ |        |__ \       |___ \      | || |      | ____|       / /       |____  |     / _ \       / _ \      _
| | | |      | |           ) |        __) |     | || |_     | |__        / /_           / /     | (_) |     | (_) |    (_)          __ _ _ __   _ __ _ __
| | | |      | |          / /        |__ <      |__   _|    |___ \      | '_ \         / /       > _ <       \__, |     _          / _ | '  \ | '_ \ '  \
| |_| |      | |         / /_        ___) |        | |       ___) |     | (_) |       / /       | (_) |        / /     (_)         \__,_|_|_|_|| .__/_|_|_|
\___/       |_|        |____|      |____/         |_|      |____/       \___/       /_/         \___/        /_/                              |_|


This font is 592 bytes.
The previous approach used a few variations on RLE compression to reduce this to 353 bytes, at the cost of 78 bytes decompression code.
The Huffman coding compresses the font to 221 bytes at the cost of 154 bytes for the decompression algorithm.

• Darn it! I really want string compression for haskell.. – J Atkin Feb 24 '16 at 3:19

# Bash + GNU utilities + figlet, 134

Not sure if figlet is allowed or not, but it does seem to provide the right fonts - big for the digits and small for the : and {a,p}m:

f=figlet\ -f
b()(date +%$1|sed 's/./& /g'|$f big)
b -I|paste - <(echo "    ";$f small ": ") <(b M) <(echo;date +%P|$f small)|tr \\t \


The rest is just getting the right info from date and shuffling the formating around so it looks right:

  ___          _____    ___
/ _ \    _   | ____|  / _ \
| (_) |  (_)  | |__   | | | |   __ _ _ __
> _ <    _   |___ \  | | | |  / _ | '  \
| (_) |  (_)   ___) | | |_| |  \__,_|_|_|_|
\___/        |____/   \___/


Figlet may be installed on Ubuntu with sudo apt-get install figlet.

• oooh didn't think of this loophole. I'll edit the question to make sure that the character data is included in the program, but keep your submission and label it inactive - it's still a good one. – user31556 Feb 16 '16 at 19:02
• I did however use figlet to get the data for the numbers, so +1 for figuring that out :) – user31556 Feb 16 '16 at 20:52
• Just to make it clear: fonts cannot be loaded from external sources or from libraries. – user31556 Feb 17 '16 at 4:39

# C++, 938 Bytes

Revised version with some basic compression of input data: Test here

#include <stdio.h>
#include <time.h>
int main(){char e[]="!12!31!21!42!4!1!44!41!35!42!42!35^!!]!1^!}!}1!]!1}2!]!1}!}1!}!2}!3}!2^!^!2}3!1}!2^!!]!2^!!]!31!}!}!}!}!1}!}!3*!}!21*!}!}!}1!}!1}!}1!3^!^!6^!^!2}!)*!}!}!)*!}!21!!!1!3!1!!1!4)*}!}!}!}!1}!}!2^!^!2}1!=!1}1!2}!}2!]!1}!(!]!4^!^!4?!!=!2]1-!}!1^!a!}!(!1]!1}!(!]!(!1]!4!}!}}!}!1}!}!1^!^!22*!}!3}!}!32*!}!}!)*!}!2^!^!4}!)*!}!3^!^!2]1-}}}}!}!/1^}}}!2)*!]2^!2}}!}3}!}3^!4}}!2}3^!2]2^!2^^!6]2^!3^^!16}}!14",l[]="8578988998>?3",f,*q=f,*p=e,c,r;time_t z;time(&z);tm*u=localtime(&z);while(*p){if(*p>47&&*p<58){r=*p++-48;if(*p>47&&*p<58)r=r*10+*p++-48;while(r--)*q++=c;}else{*q++=c=*p++==94?48:p[-1];}}c=u->tm_hour;sprintf(e,"%02d<%02d%c",c%12,u->tm_min,':'+c/12);for(int s,n,o,r=0;r<6;r++){for(q=e;*q;q++){o=r*111;for(n=0; n<*q-48;n++)o+=l[n]-48;s=l[n]-48;for(n=o;n<o+s;n++)putchar(f[n]-1);}putchar('\n');}return 0;}

• The headers for this submission don't have all that much influence on the byte size when compared to the data required, so this could actually have a fair chance at winning. – user31556 Feb 16 '16 at 20:54

Yay, under 700 bytes!!

t=transpose
i=intercalate
l=lines
u=unlines
s=show
c(h,m,a)=u$t$l(i(r"!!\n!!\n")(map d(s h++':':(if m<10 then '0':s m else s m)))++r"!!"++(d$a!!0)) e s z n=i s$splitOn z n
r=e"   ""!"
d 'a'=b 10
d 'p'=b 11
d ':'=b 12

# JavaScript (ES6), 994 985 bytes

Terrible attempt with raw data not compressed at all, and a very tacky method for outputting.

But hey... it's only my second codegolf answer!

d="   ___   !  / _ \\  ! | | | | ! | | | | ! | |_| | !  \\___/  0  __  ! /_ | !  | | !  | | !  | | !  |_| 0  ___   ! |__ \\  !    ) | !   / /  !  / /_  ! |____| 0  ____   ! |___ \\  !   __) | !  |__ <  !  ___) | ! |____/  0  _  _    ! | || |   ! | || |_  ! |__   _| !    | |   !    |_|   0  _____  ! | ____| ! | |__   ! |___ \\  !  ___) | ! |____/  0    __   !   / /   !  / /_   ! |  _ \\  ! | (_) | !  \\___/  0  ______  ! |____  | !     / /  !    / /   !   / /    !  /_/     0   ___   !  / _ \\  ! | (_) | !  > _ <  ! | (_) | !  \\___/  0   ___   !  / _ \\  ! | (_) | !  \\__, | !    / /  !   /_/   0   ! _ !(_)! _ !(_)!   0!! __ _ _ __ !/ _ | '  \\!\\__,_|_|_|_|!0!! _ __ _ __ !| '_ \\ '  \\!| .__/_|_|_|!|_|".split(0);
f=a=>{t="toString",s="split",h=a[t]()[s](""),m=a[s](""),p=a=='am'?11:12,g=h.length>1?1:0,r="";for(i=0;i<6;i++){r+=d[h][s]('!')[i];r+=(g&&1)?d[h][s]('!')[i]:"";r+=d[s]('!')[i]+d[m][s]('!')[i]+d[m][s]('!')[i]+d[p][s]('!')[i]+"\n"}return r}


Old submission (994 bytes):

d=["   ___   !  / _ \\  ! | | | | ! | | | | ! | |_| | !  \\___/  ","  __  ! /_ | !  | | !  | | !  | | !  |_| ","  ___   ! |__ \\  !    ) | !   / /  !  / /_  ! |____| ","  ____   ! |___ \\  !   __) | !  |__ <  !  ___) | ! |____/  ","  _  _    ! | || |   ! | || |_  ! |__   _| !    | |   !    |_|   ","  _____  ! | ____| ! | |__   ! |___ \\  !  ___) | ! |____/  ","    __   !   / /   !  / /_   ! |  _ \\  ! | (_) | !  \\___/  ","  ______  ! |____  | !     / /  !    / /   !   / /    !  /_/     ","   ___   !  / _ \\  ! | (_) | !  > _ <  ! | (_) | !  \\___/  ","   ___   !  / _ \\  ! | (_) | !  \\__, | !    / /  !   /_/   ","   ! _ !(_)! _ !(_)!   ","!! __ _ _ __ !/ _ | '  \\!\\__,_|_|_|_|!","!! _ __ _ __ !| '_ \\ '  \\!| .__/_|_|_|!|_|"];
f=a=>{
t="toString",s="split",h=a[t]()[s](""),m=a[s],p=(a=='am')?11:12,g=(h.length>1)?1:0,r="";
for(i=0;i<6;i++){
r+=d[h].s('!')[i];
r+=g&&1?d[h].s('!')[i]:"";
r+=d.s('!')[i]+d[m].s('!')[i]+d[m].s('!')[i]+d[p].s('!')[i]+"\n"
}
return r
}


Split into lines to make it easier to read.

Basically:

var f = function (a) {
hours = a.toString().split(""), // convert hours to a string then array to
// handle single and and double numbers
minutes = a.split(""), // ditto with minutes
period = a == "am" ? 11 : 12, // if it is am, get data, if pm, get data
g = hours.length > 1 ? 1 : 0, // if hours > 9, then g is true
r = ""; // the string that will be returned
for (i = 0; i < 6; i++) {
r += data[hours].split("!")[i]; // add the first digit of hours to r
r += g && 1 ? data[hours].split("!")[i] : ""; // if g is true, add the second
//digit of hours to r
r += data.split("!")[i] + // colon
data[minutes].split("!")[i] + // first digit of minutes
data[minutes].split("!")[i] + // second digit of minutes
data[period].split("!")[i] + // am/pm
"\n"; // and finally linebreak.
} // entire loop repeated six times, each iteration adds one line to the string
return r; // return the string
};


## Python 3, 1085 1072 bytes

### Golfed

def f(h,c="",n=["   ___   @  / _ \  @ | | | | @ | | | | @ | |_| | @  \___/  ","  __  @ /_ | @  | | @  | | @  | | @  |_| ","  ___   @ |__ \  @    ) | @   / /  @  / /_  @ |____| ","  ____   @ |___ \  @   __) | @  |__ <  @  ___) | @ |____/  ","  _  _    @ | || |   @ | || |_  @ |__   _| @    | |   @    |_|   ","  _____  @ | ____| @ | |__   @ |___ \  @  ___) | @ |____/  ","    __   @   / /   @  / /_   @ |  _ \  @ | (_) | @  \___/  ","  ______  @ |____  | @     / /  @    / /   @   / /    @  /_/     ","   ___   @  / _ \  @ | (_) | @  > _ <  @ | (_) | @  \___/  ","   ___   @  / _ \  @ | (_) | @  \__, | @    / /  @   /_/   ","   @ _ @(_)@ _ @(_)@   ","            @            @ __ _ _ __ @/ _ | '  \@\__,_|_|_|_|@            ","            @            @ _ __ _ __ @| '_ \ '  \@| .__/_|_|_|@|_|"]):
for i in range(6):
for j in range(3):
if j<2:
x=int(h[j]);d=x//10;u=x%10
if d>0 or j>0:c+=n[d].split("@")[i]
c+=n[u].split("@")[i]
if j==0:c+=" "+n.split("@")[i]+" "
else:y=11 if h[j]=="am" else 12;c+=" "+n[y].split("@")[i]
c+="\n"
return c


### Ungolfed

import os
from time import ctime

def asciiClock(hour):
num = ["   ___   @  / _ \  @ | | | | @ | | | | @ | |_| | @  \___/  @","  __  @ /_ | @  | | @  | | @  | | @  |_| @",
"  ___   @ |__ \  @    ) | @   / /  @  / /_  @ |____| @","  ____   @ |___ \  @   __) | @  |__ <  @  ___) | @ |____/  @",
"  _  _    @ | || |   @ | || |_  @ |__   _| @    | |   @    |_|   @","  _____  @ | ____| @ | |__   @ |___ \  @  ___) | @ |____/  @",
"    __   @   / /   @  / /_   @ |  _ \  @ | (_) | @  \___/  @","  ______  @ |____  | @     / /  @    / /   @   / /    @  /_/     @",
"   ___   @  / _ \  @ | (_) | @  > _ <  @ | (_) | @  \___/  @","   ___   @  / _ \  @ | (_) | @  \__, | @    / /  @   /_/   @",
"   @ _ @(_)@ _ @(_)@   @","            @            @ __ _ _ __ @/ _ | '  \@\__,_|_|_|_|@            @",
"            @            @ _ __ _ __ @| '_ \ '  \@| .__/_|_|_|@|_|@"]
clock = ""
for i in range(6):
for j in range(3):
if j < 2:
x = int(hour[j])
d = x // 10
u = x % 10
if d > 0 or j > 0:
clock += num[d].split("@")[i]
clock += num[u].split("@")[i]
if j == 0:
clock += " " + num.split("@")[i] + " "
else:
y = 11 if hour[j] == "am" else 12
clock += " " + num[y].split("@")[i]
clock += "\n"
return clock

previousMinute = -1
while True:
hour = ctime().split().split(":")
h = int(hour)
m = hour
x = "am" if h < 12 else "pm"
if h > 12:
h -= 12
if  previousMinute != m:
os.system("clear") # if using Windows change to "cls"
print(asciiClock([h, m, x]))
previousMinute = m
`