9
\$\begingroup\$

I made this because, although we have a bunch of other questions involving smiley faces, there is nothing for just printing an ASCII smiley face with as little code as possible.

Anyway, print this exactly (Trailing spaces allowed):

        **********
    ******************
  **********************
 *******  ******  *******
 ************************
**************************
**************************
*****   **********   *****
 *****   ********   *****
 ******            ******
  **********************
    ******************
        **********

This is code-golf, so fewest bytes wins. Yes, you have to use asterisks.

\$\endgroup\$
4

20 Answers 20

5
\$\begingroup\$

Python 3, 97 bytes

The string has a leading and trailing unprintable with value 5.

for c in"wç¿ğŗŗĵý6çw":c=ord(c);s=c%8*'*'+c//8%7*' '+c//56*'*';print(f'{s+s[::-1]:^26}')

Try it online!

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

APL+WIN, 57 bytes

m,⌽m←13 13⍴(¯17+⎕av⍳'hedibkagbca⊢ceaecdafhkdihe')/26⍴' *'

String used to index into atomic vector has been adjusted to allow for differences between APL+WIN and Dyalog

Try it online! Thanks to Dyalog Classic

\$\endgroup\$
4
\$\begingroup\$

Java (JDK), 153 bytes

v->{var s=0;for(var c:"HJ!DR!BV!AGBFBG!AX!@Z!@Z!@ECJCE!AECICE!AFLF!BV!DR!HJ".getBytes())System.out.print("\n* ".split("")[c/64+(s^=c/64)].repeat(c%32));}

Try it online!

Explanation

The idea is to have toggle, s, which will tell us when to print spaces or stars. The number of those spaces or spaces is defined by each character used in the long string. Any letter is their corresponding number (A=1, B=2, ...), @ actually is zero, and ! also means 1, but it's in a lower range than A to know when to go to the next line.

We can see the smiley as a sequence of [0,26] spaces followed by stars [1,26], possibly repeated. This makes sure that if we provide 2 chars, the first char represent the spaces and the second char represent the stars. This toggling is done using s^=1.

But it happens that I have to insert new lines in that sequence. A new character would then mess up with that s^=1, so I changed that to s^=c/64, meaning that only letters and @ actually trigger the toggle, while ! result in s^=0 which is a no-op.

s c s^(c/64) c/64+(s^(c/64)) Result
0 ! 0 0 \n
0 [@-Z] 1 2 (space)
1 ! 1 1 Never occurs
1 [@-Z] 0 1 *

After the character is selected (but kept as a string, not as a character), it is repeated c%32 times. It is to note that '!' % 32 = 33 % 32 = 1 and '@' % 32 = 64 % 32 = 0. Java's .repeat(0) will indeed result in the empty string ("").

\$\endgroup\$
3
\$\begingroup\$

05AB1E, 72 68 42 bytes

•A9lΘRfÓβèε¢|Ïí"·тjêøè§Äα9₃ê˜ì•… *
ÅвJº.c

-26 bytes by adding a mirror (inspired by @Neil's Charcoal answer).

Try it online.

Explanation:

•A9lΘRfÓβèε¢|Ïí"·тjêøè§Äα9₃ê˜ì•
              "# Push compressed integer 61833926632893543016875916488121666051545681457434856388592933517828315
  … *\n        # Push string " *\n"
       Åв      # Convert the integer to base-" *\n" (which means to convert it to base-3,
               # and index them into the 3-char string)
         J     # Join all characters together to a string
          º    # Mirror each line
           .c  # And centralize all lines
               # (after which the result is output implicitly)

This is the result without the mirror and centralize. The code for this is generated with this 05AB1E ASCII-art tip.
See this 05AB1E tip of mine (section How to compress large integers?) to understand why •A9lΘRfÓβèε¢|Ïí"·тjêøè§Äα9₃ê˜ì• is 61833926632893543016875916488121666051545681457434856388592933517828315.

\$\endgroup\$
3
\$\begingroup\$

PHP, (all versions) 119 106 104 71 bytes

<?=gzinflate("SP€ -8àåBå#‹cŠBe ,˜ ¸J„]¸dˆ’Cq#Œ³I]JK À‰Ûg8Ã=Ü");

WARNING: this code contains many non-printable chars and a function that is disabled in most online code testers. It is either impossible to enter the correct code on the page or run the function. Here is the php file I uploaded to gitHub so that you can test:

Try it OFFline!

For info, it was generated by PHP's file_put_contents with the direct result of gzdeflate, no other manipulation required, the file is not manually edited with an Hex program, the only modification is deleting the last null byte of the generated zip string in notepad.

Thanks to @hanshenrik for the help trying to share this shortest version!

Longer version that can be tested online:

PHP, (version < 8.0) 104 bytes

<?=gzinflate(base64_decode(U1CAAC044OVC5SOLY4pCZaAsmAq4SoQUFl24ZIiSQ3EjjAOzDkkSXUpLAQnAHYnbZzjDAj3cAA));

Online PHP function(s)

Simply encoded with gz, which is not available in TIO so I provided another site's link. (inspired by this answer after following @Neil's link "In Honor of Adam West")

EDIT: zip shortened by removing trailing spaces + finally it's only alphanumeric chars so I could remove the quotes (the warning would not show in the output in TIO like it does with Online PHP functions)

\$\endgroup\$
8
  • \$\begingroup\$ it's possible to skip base64_decode and the base64 and insert the gzip binary directly in the source code using var_export() and HxD Hex Editor, but it's not possible using VSCode; here is the base64 of a version of your code in only 83 bytes, but warning, this code is NOT VSCode-compatible, but it is php-compatible: PD89Z3ppbmZsYXRlKCdTUIAnLiJcMCIuJy044OVC5SOLY4pCZaAsmAq4SoQUFl24ZIiSQ3EjjAOzDkkSXUpLAQnAHYnbZzjDAj3cJy4iXDAiKTs= \$\endgroup\$ – hanshenrik Feb 2 at 19:56
  • \$\begingroup\$ shaved off a few more bytes (more efficient NULL-encoding), now it's 72 bytes: PD89Z3ppbmZsYXRlKCdTUIAALTjg5ULlI4tjikJloCyYCrhKhBQWXbhkiJJDcSOMA7MOSRJdSksBCcAdidtnOMMCPdwAJyk7 \$\endgroup\$ – hanshenrik Feb 2 at 20:08
  • \$\begingroup\$ (and i think its possible to shave off a few more bytes from the 72 solution with more efficient encoding of \\ but i haven't tried, not all \ needs to be escaped, just some of them =/ ) \$\endgroup\$ – hanshenrik Feb 2 at 20:24
  • \$\begingroup\$ I get <br /> <b>Fatal error</b>: Uncaught Error: Undefined constant &quot;U1CAAC044OVC5SOLY4pCZaAsmAq4SoQUFl24ZIiSQ3EjjAOzDkkSXUpLAQnAHYnbZzjDAj3cAA&quot; in [...][...]:1 Stack trace: #0 {main} thrown in <b>[...][...]</b> on line <b>1</b><br /> when I run it. +2 bytes - I think the string needs quotes. \$\endgroup\$ – A username Feb 3 at 4:07
  • \$\begingroup\$ @Ausername you have to run it on PHP version < 8.0, it used to throw a notice, then a warning from 7.2, and only became a fatal error with 8.0. I'll add the precision \$\endgroup\$ – Kaddath Feb 3 at 8:06
2
\$\begingroup\$

Charcoal, 36 bytes

⭆”←&∨n?Þ\`W!π↖δ℅If#≕W⧴@b⪪¹λ”∨×Σι*ι‖M←

Try it online! Link is to verbose version of code. Explanation:

⭆”...”

Map over partially RLE-encoded string.

∨×Σι*ι

Replace non-zero digits with their count of *s.

‖M←

Reflect the result.

Out of interest, I tried porting my answer to In Honor of Adam West but that weighed in at a massive 39 bytes (although it was still my second best approach).

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

05AB1E, 33 bytes

Very similar to my Python answer, this encodes the half of every line as a 3-digit base 8 integer.

•Uмö€æ¤š∊η ø‘Kó•468вε8в„* Þ×J}º.c

Try it online!

Commented:

•Uмö€æ¤š∊η ø‘Kó•468в # compressed integer list
                     # [5,135,263,467,327,391,391,349,348,432,263,135,5] (base 10)
                     # [5,207,407,723,507,607,607,535,534,660,407,207,5] (base 8)

ε         }          # map over the integers; example: 467
 8в                  # convert to base 8               [7, 2, 3]
   …*                # push the string "* "
       Þ             # create a infinite list by cycling the characters
        ×            # for each each base-8 digit, repeat the character at the same index this many times
                     #                                 ['*******', '  ', '***']
         J           # join into a single string       '*******  ***'

º                    # mirror every line
 .c                  # centralize and join by newlines
\$\endgroup\$
1
  • 1
    \$\begingroup\$ •Uмö€æ¤š∊η ø‘Kó•468в can be •γÂÂàª[O‘ôγ̹‚5•₄;в for -1. And you've made a typo in your explanation: the should be . Nice approach btw! \$\endgroup\$ – Kevin Cruijssen Feb 2 at 20:30
2
\$\begingroup\$

Perl 5, 93 bytes

say'IK
ES
CW
BHCGCH
BY
A[
A[
AFDKDF
BFDIDF
BGMG
CW
ES
IK'=~s/./('*',$")[--$|]x(-65+ord$&)/ger

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Nice solution! If you use numbers for the number of spaces and A-Z for the number of asterisks you can save a few bytes more: Try it online! \$\endgroup\$ – Dom Hastings Feb 3 at 12:49
2
\$\begingroup\$

JavaScript (ES6), 108 bytes

_=>`8a
4i
2m
172627
1o
0q
0q
053a35
153835
16c6
2m
4i
8a`.replace(/./g,c=>"* "[_^=1].repeat(parseInt(c,36)))

Try it online!


JavaScript (ES6),  112  109 bytes

Returns an array of strings.

_=>[p=1020,960,768,515,512,0,0,28,526,519.9,768,960,p].map(n=>(g=(k,c="* "[n*8>>k&1])=>~k?c+g(k-1)+c:'')(12))

Try it online!

How?

Each value in the array represents the inverted 13-bit value of the left side of the smiley, divided by 8. Dividing by 8 saves 7 bytes overall, although there's a non-integer value in there (519.875, which can be rounded to 519.9).

........***** -> 1111111100000 -> 8160 / 8 = 1020
....********* -> 1111000000000 -> 7680 / 8 = 960
..*********** -> 1100000000000 -> 6144 / 8 = 768
.*******..*** -> 1000000011000 -> 4120 / 8 = 515
.************ -> 1000000000000 -> 4096 / 8 = 512
************* -> 0000000000000 ->    0 / 8 = 0
************* -> 0000000000000 ->    0 / 8 = 0
*****...***** -> 0000011100000 ->  224 / 8 = 28
.*****...**** -> 1000001110000 -> 4208 / 8 = 526
.******...... -> 1000000111111 -> 4159 / 8 = 519.875
..*********** -> 1100000000000 -> 6144 / 8 = 768
....********* -> 1111000000000 -> 7680 / 8 = 960
........***** -> 1111111100000 -> 8160 / 8 = 1020

So, we extract the kth 'pixel' stored in the bitmask n with:

n * 8 >> k & 1
\$\endgroup\$
3
  • \$\begingroup\$ Sir, would you mind explaining this part [n*8>>k&1])=>~k? \$\endgroup\$ – snr Feb 4 at 10:04
  • 1
    \$\begingroup\$ @snr I've added an explanation. Given the operator precedence, n*8>>k&1 should be read as ((n*8)>>k)&1 and means least significant bit of n * 8 right-shifted by k positions. \$\endgroup\$ – Arnauld Feb 4 at 10:34
  • \$\begingroup\$ I'm captivated by your solutions. Actually, you are why I've started learning Javascript . \$\endgroup\$ – snr Feb 4 at 10:57
1
\$\begingroup\$

Retina 0.8.2, 82 bytes


i10¶e18¶c22¶b7c6c7¶b24¶26¶26¶5d10d5¶b5d8d5¶b6jd6¶c22¶e18¶i10
\d+
$**
T`l`d
\d
$* 

Try it online! Explanation: Uses run-length encoding, where numbers encode *s and letters b-j encode spaces (so for the 12 spaces of the mouth I need two letters).


i10¶e18¶c22¶b7c6c7¶b24¶26¶26¶5d10d5¶b5d8d5¶b6jd6¶c22¶e18¶i10

Insert the run-length encoded text.

\d+
$**

Decode integers to runs of *s.

T`l`d

Replace letters b-j with digits 1-9.

\d
$* 

Decode digits to runs of spaces.

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

Bubblegum, 49 bytes

Obligatory bubblegum entry. Generated with zopfli --i1000 --deflate -c smiley.txt | xxd.

00000000: 5380 022d 38e0 42e6 a208 8369 4c09 9838  S..-8.B....iL..8
00000010: 4401 8246 c860 ea01 6272 a560 ae83 71a0  D..F.`..br.`..q.
00000020: 56c1 b898 3230 3e02 60f5 11e1 10c0 0c2b  V...20>.`......+
00000030: 00                                       .

Try it online!

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

Jelly, 35 33 bytes

“ ṄUçɓĠḷƑżØS`’b12o43µ⁾ *ṁxs13m€0Y

Try it online!

Explanation

“ ṄUçɓĠḷƑżØS`’b12o43µ⁾ *ṁxs13m€0Y   Main monadic link
“ ṄUçɓĠḷƑżØS`’                      8060783762011200773438708597
              b12                   Convert to base 12 => [8,5,4,9,2,11,1,7,2,3,1,0,3,5,1,5,3,4,1,6,8,11,4,9,8,5]
                 o43                Logical OR with 43 => [8,5,4,9,2,11,1,7,2,3,1,43,3,5,1,5,3,4,1,6,8,11,4,9,8,5]
                    µ               Use as argument to new monadic chain
                     ⁾ *ṁ           Repeat " *" to have the same length
                         x          Repeat each character as many times as the corresponding number
                          s13       Split into chunks of 13
                             m€0    Mirror each
                                Y   Join with newlines
\$\endgroup\$
1
\$\begingroup\$

Perl 5 -M5.10.0, 73 bytes

$_=unpack"B*","......w......|{.......";y/01/ */,say$_.reverse for/.{13}/g

Try it online!

Explanation

This solution consists of mostly unprintable characters which are a packed binary string containing a representation of the left-half of the image as 0s and 1s which is unpacked into $_, then y/// (tr///) changes all the 0s to s and the 1s to *s, before the /.{13}/g (m//) matches each stretch of 13 chars passing them to say ($_), along with the reverse of $_, to print the result on individual lines.

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

Japt -R, 66 55 52 bytes

-11 bytes thanks to AZTECCO

"ǿ߿࿧࿿῿῿἟ྏ࿀߿ǿ"¬®c s" *" ê1Ãû

Test it

Explanation

"..."              // String with characters at codepoints:
                   //   31   ('        *****' as binary string where ' ' -> 0, '*' -> 1)
                   //   511  ('    *********' as binary string where ' ' -> 0, '*' -> 1)
                   //   2047 ('  ***********' as binary string where ' ' -> 0, '*' -> 1)
                   //   4071 (' *******  ***' as binary string where ' ' -> 0, '*' -> 1)
                   //   4095 (' ************' as binary string where ' ' -> 0, '*' -> 1)
                   //   8191 ('*************' as binary string where ' ' -> 0, '*' -> 1)
                   //   8191 ('*************' as binary string where ' ' -> 0, '*' -> 1)
                   //   7967 ('*****   *****' as binary string where ' ' -> 0, '*' -> 1)
                   //   3983 (' *****   ****' as binary string where ' ' -> 0, '*' -> 1)
                   //   4032 (' ******      ' as binary string where ' ' -> 0, '*' -> 1)
                   //   2047 ('  ***********' as binary string where ' ' -> 0, '*' -> 1)
                   //   511  ('    *********' as binary string where ' ' -> 0, '*' -> 1)
                   //   31   ('        *****' as binary string where ' ' -> 0, '*' -> 1)
     ¬             // Convert the string to an array
      ®            // map array with func:
       c           //   convert char to codepoint
         s" *"     //   convert codepoint to a binary string with chars "* "
              ê1   //   concatenate reverse of the binary string to itself
                 û // centre-pad result of map

The -R flag then concatenates the resulting array with newlines
\$\endgroup\$
4
  • \$\begingroup\$ 55 \$\endgroup\$ – AZTECCO Feb 3 at 21:59
  • \$\begingroup\$ Nice! I thought it could be still golfed but didn't figured out , btw ê1 can be just ê \$\endgroup\$ – AZTECCO Feb 4 at 6:58
  • \$\begingroup\$ @AZTECCO ê palindromes the string so if length is odd the last char is not added again (e.g. abc -> abcba and not abccba), which causes a * to be removed from all lines \$\endgroup\$ – Mukundan314 Feb 4 at 7:24
  • \$\begingroup\$ Oh! Sorry.. Didn't noticed \$\endgroup\$ – AZTECCO Feb 4 at 9:21
1
\$\begingroup\$

Vyxal j, 50 bytes

»
«0QÞ*⌊B⊍E⟨}¹ǍaȦM.¥⁺⊍Ṅ₂ṖA«[¥ȯ⇩»3τ` *
`viṅøṀ`
`€øĊ

Try it Online!

All hail new vertical mirror!!

\$\endgroup\$
0
\$\begingroup\$

Julia, 102 bytes

println.(split(join(collect(" *"^18).^(b"HJKRFVCGBFBGBXAyCJCEAECHCEBFLFCVFRLJ".-64)),r"(?<=\G.{25})"))

Try it online!

the string stores the amount of consecutive ' ' and '*'. We than split the string in 26-character chunks and print with line breaks

\$\endgroup\$
0
\$\begingroup\$

C (gcc), 145 bytes116 Bytes

Thanks to ASCII-only, who managed to shave 29 bytes off.

c;f(i){for(i=0;c="+m'u%y$*%)%j${#}#}#(&-&h$(&+&h$)/i%y'u+-"[i++];c&64&&puts(""))while(--c%64>34)putchar(i&1?32:42);}

Try it online!

I had to start the encoding at 35, since 34 is " which requires an additional \ as escape character and thus would increase the total character count. Each character in the string +m'u%y$*%)%j${#}#}#(&-&h$(&+&h$)/i%y minus 35 represents the number of spaces and asteriks, in an alternating pattern. This achieves a compression rate of almost 8 (318/40).

Ungolfed:

char*s="+m'u%y$*%)%j${#}#}#(&-&h$(&+&h$)/i%y'u+-";
void f()
{
    for( int i=0; i < 40; ++i)
    {
        for(int j=35; j < (s[i]&63); ++j )
        {
            if( i&1 )
            {
                printf("*");
            }
            else
            {
                printf(" ");
            }
        }
        if( s[i] & 64 )
        {
            printf("\n");
        }
   }
}
\$\endgroup\$
3
  • \$\begingroup\$ Can be squeezed down a bit: 122 bytes \$\endgroup\$ – gastropner Feb 3 at 4:13
  • \$\begingroup\$ 116? \$\endgroup\$ – ASCII-only Feb 3 at 4:46
  • \$\begingroup\$ Suggest printf(L"* "+i%2) instead of putchar(i&1?32:42) \$\endgroup\$ – ceilingcat Feb 15 at 4:57
0
\$\begingroup\$

Pyth, 57 bytes

jm.[26+_K++*\*%/J|Cd390 8 8*\ /J64*\*%J8K\ ",5Ÿ6>>íå5,

Try it online!

\$\endgroup\$
0
\$\begingroup\$

x86-16 machine code, 101 96 bytes

Saved 5 bytes thanks to @peterferrie.

0BEC:0100  BE 44 01 31 DB AD 91 E3-22 51 E8 20 00 59 C1 E9   .D.1...."Q. .Y..
0BEC:0110  03 80 36 2E 01 08 E8 14-00 80 36 2E 01 08 83 FB   ..6.......6.....
0BEC:0120  0C 74 05 B8 0A 00 CD 29-43 EB DA CD 20 D1 E1 19   .t.....)C... ...
0BEC:0130  C0 24 0A 0C 20 83 FB 09-75 03 83 F0 0A CD 29 85   .$.. ...u.....).
0BEC:0140  C9 75 EA C3 F8 00 F8 0F-F8 3F 38 7F F8 7F F8 FF   .u.......?8.....
0BEC:0150  F8 FF F8 F8 78 7C F8 81-F8 3F F8 0F F8 00 00 00   ....x|...?......

Standalone executable.

Instruction listing (nasm syntax):

org 100h

    mov si, face
    xor bx, bx
lop:    lodsw
    xchg cx, ax
    jcxz ed
    push cx
    call loop
    pop cx
    shr cx, 3
    xor byte [loop+1], 8
    call loop
    xor byte [loop+1], 8
    cmp bx, 12
    je sk
    mov ax, 0Ah
    int 29h
sk: inc bx
    jmp lop
ed:
    int 20h

loop:   shl cx, 1
    sbb ax, ax
    and al, 0ah
    or al, ' '
    cmp bx, 9
    jne yy
    xor ax, 10
yy: int 29h
    test cx, cx
    jnz loop
    ret

face:   dw 00f8h, 0ff8h, 3ff8h, 7f38h, 7ff8h, 65528, 65528, 63736, \
        7c78h, 33272, 3ff8h, 0ff8h, 00f8h, 0000h

Example run

C:\test>smile.com
        **********
    ******************
  **********************
 *******  ******  *******
 ************************
**************************
**************************
*****   **********   *****
 *****   ********   *****
 ******            ******
  **********************
    ******************
        **********
\$\endgroup\$
1
  • \$\begingroup\$ "mov cx, ax" can be "xchg cx, ax". The "jnc" part block can be "sbb ax, ax / and al, 0ah / or al, ' '" \$\endgroup\$ – peter ferrie Feb 4 at 22:11
0
\$\begingroup\$

C (gcc), 175 168 bytes

-7 bytes thanks to ceilingcat

*s;i;p(x,y){for(i=x-printf("%*s",x-97,"");i++<y;printf("*"));s++;}f(){for(s=L"ikjesjcwjbhcgchjbyja{ja{jafdkdfjbfdidfjbgmgjcwjesjikA";*s-'j'?p(*s,s[1]):puts(""),*s++;);}

Try it online!

Explanation before some golfing:

char*s="ikjesjcwjbhcgchjbyja{ja{jafdkdfjbfdidfjbgmgjcwjesjik";

This string encodes the number of consecutive spaces and asterisks along with the newlines position.

p(x,y){for(i=97;i++<x;printf(" "));for(i=97;i++<y;printf("*"));s++;}

This function takes as arguments the ASCII value of two characters and use the first one to print whitespace and the second to print asterisks.

f(){*s-'j'?p(*s,s[1]):puts("");*s++&&f();};

Here we check whether the current character is a 'j', which has been chosen to encode a newline.

\$\endgroup\$
3
  • \$\begingroup\$ @ceilingcat wow thank you for showing me these tricks! \$\endgroup\$ – Sheik Yerbouti Feb 11 at 10:13
  • \$\begingroup\$ If you switch the string to uppercase then you can compare with 84 instead of 'j' \$\endgroup\$ – ceilingcat Feb 11 at 17:09
  • \$\begingroup\$ @ceilingcat you are right! This would save another byte. \$\endgroup\$ – Sheik Yerbouti Feb 11 at 20:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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