| Bytes | Lang | Time | Link |
|---|---|---|---|
| 229 | C gcc | 250805T071531Z | CaydendW |
| 7568 | MATL | 250627T203334Z | Luis Men |
| 236 | C gcc | 250630T165023Z | jdt |
| 086 | Uiua | 250704T223722Z | ErikDaPa |
| nan | CP1610 machine code | 250627T172433Z | Arnauld |
| 227 | PowerShell Core 7.4+ | 250628T000031Z | user3141 |
| 322 | Java on Windows | 250630T115258Z | Kevin Cr |
| nan | Commodore 64 Assembler | 250630T111126Z | Jani Joe |
| 246 | JS | 250629T131050Z | b00t |
| 432 | HTML + CSS + JS | 250629T082636Z | M. Zhang |
| 293 | ZX Spectrum Basic | 250627T213317Z | Neil |
| 1024 | HTML + CSS + JS | 250627T173537Z | A.L |
C (gcc), 229 bytes
Contains unprintable characters:
*a=L"ð0@@!!!!!!\"DÂC0ð";*b=L"ð0@@!!!!!!\"DÂC0ð";*c;main(i){puts("\e[2J\e[H");for (i=0;i<256;++i%16||puts(""))putchar(a[i/8]&1<<(i%8)?42:32);c=a;a=b;b=c;usleep(1<<19);main();}
Stores the smiley faces in unprintable characters as a bitmap. Other things to possible optimise include: Reuse common parts of the strings and make the swapping better.
I'd add a TIO link but TIO doesn't like the infinite loop.
od dump of the program:
0000000 060452 046075 141442 007660 030014 040002 040002 141041
0000020 020600 100302 141041 020600 117702 141041 020600 100302
0000040 141001 000600 100302 021134 141504 041602 030014 130303
0000060 021017 025073 036542 021114 130303 006017 001060 001100
0000100 020500 102302 141041 020604 102302 141041 020604 102302
0000120 141041 000604 100302 141001 056200 042042 101303 006103
0000140 141460 007660 035442 061452 066473 064541 024156 024551
0000160 070173 072165 024163 056042 055545 045062 062534 044133
0000200 024442 063073 071157 024040 036551 035460 036151 032462
0000220 035466 025453 022551 033061 076174 072560 071564 021050
0000240 024442 070051 072165 064143 071141 060450 064533 034057
0000260 023135 036061 024074 022551 024470 032077 035062 031063
0000300 035451 036543 035541 036541 035542 036542 035543 071565
0000320 062554 070145 030450 036074 034461 035451 060555 067151
0000340 024450 076473 000012
0000345
MATL, 75 68 bytes
`TF'#c8Dw;Lv/P/7KMbi('F8:ZaY"8etPv!F85:90(!@o?tP*}F5:'x'+(]!1YG.5Y.T
You can try it at MATL online!, but it's slow. Here's an animated GIF from the offline compiler showing the actual speed:
C (gcc), 295 272 237 236 bytes
-23 bytes thanks to @Kevin Cruijssen!
-36 bytes thanks to @ceilingcat!
a[]: An array of 16 integers representing two 16×16 monochrome images.
- The first 8 values are Image 1.
- The next 8 values are Image 2.
f(b): A recursive function that:
Clears the screen using ANSI escape codes:
\033[H\033[2JIterates
ifrom 255 to 0 (32*8bits total).Uses
i/32 + b*8to select the appropriate image data (b=0or1).Uses
1 << i%32to mask out the bit at positioni % 32.Prints
'#'if the bit is set, otherwise a space.Outputs a newline after every 16 characters
i%16 || puts("").Waits about 0.5 seconds:
usleep(2<<18)= 524288 microseconds.Recursively calls
f(!b)to toggle between the two images.
Uiua, 86 bytes
&gifs2⊟∩⌟⬚0+∩⌝↘4_10⍉¤⊂1⟜(7_8¤)⋯31⬚0+⌝↘4_5⋯[.....1 .0 33 30]⊂⟜⇌≡(⊂⟜⇌)⋯[⊸×20⊸×6.˙+....1]
Explanation:
&gifs2⊟∩⌟⬚0+∩⌝↘4_10⍉¤⊂1⟜(7_8¤)⋯31⬚0+⌝↘4_5⋯[.....1 .0 33 30]⊂⟜⇌≡(⊂⟜⇌)⋯[⊸×20⊸×6.˙+....1]
⊂⟜⇌≡(⊂⟜⇌)⋯[⊸×20⊸×6.˙+....1] => create bitmap of the head outline using its top-left quadrant
(use of symmetry)
⬚0+⌝↘4_5⋯[.....1 .0 33 30] => bitmap for the non-blinking eye and mouth
∩⌝↘4_10⍉¤⊂1⟜(7_8¤)⋯31 => bitmap for the blinking eye (two frames)
⊟∩⌟⬚0+ => combine all the components together for each frame
&gifs2 => finally generate gif (2 frames/sec)
CP-1610 machine code, 89 DECLEs1=111.25 bytes
1. CP-1610 instructions are encoded with 10-bit values (0x000 to 0x3FF), known as DECLEs. Although the Intellivision is also able to work on 16-bit data, programs were really stored in 10-bit ROM back then.
This is a full program mapped at $4800-$4858. To get the correct delay of 500ms, this should be run on a 60Hz (NTSC) Intellivision.
We could save 1 DECLE by just incrementing the counter and testing bit #5. The frame change would occur every 32 frames (533.33ms).
Source code
ROMW 10 ; use 10-bit ROM
ORG $4800 ; map our program at $4800
BT EQU $0200 ; BACKTAB address
RTN EQU $1014 ; return address of the ISR
CLEAR EQU $1738 ; clear routine of the EXEC
GRAM EQU $3800 ; GRAM address
;; --------------------------------------------------------- ;;
;; main code ;;
;; --------------------------------------------------------- ;;
4800 2B8 00A MVII #isr AND $FF, R0 ; set up the interrupt service routine
4802 240 100 MVO R0, $100
4804 2B8 048 MVII #isr SHR 8, R0
4806 240 101 MVO R0, $101
4808 002 EIS ; enable interrupts
4809 017 DECR R7 ; spin forever
;; --------------------------------------------------------- ;;
;; ISR ;;
;; --------------------------------------------------------- ;;
;; NB: called with R1 = $4800 (because of the way the EXEC ;;
;; jumps to the entry point) ;;
;; --------------------------------------------------------- ;;
isr PROC
480A 2B8 034 MVII #52, R0 ; clear the STIC registers
480C 1E4 CLRR R4
480D 004 114 338 CALL CLEAR
4810 0FC ADDR R7, R4 ; we now have R4 = 52, which is the
; distance from here to the tiles data
4811 001 SDBD ; R5 = pointer into GRAM
4812 2BD 000 038 MVII #GRAM, R5
4815 2A0 @loop MVI@ R4, R0 ; R0 = tile data
4816 268 @copy MVO@ R0, R5 ; write the byte to the GRAM
4817 338 100 SUBI #$100, R0 ; decrement the upper nibble
4819 223 004 BPL @copy ; copy again if still positive
481B 2F9 2CD ADDI #717, R1 ; this will make R1 negative-looking
481D 223 009 BPL @loop ; after 20 iterations ($4800 -> $8004)
481F 2BA 301 MVII #$301, R2 ; R2 = address of 16-bit counter
4821 291 MVI@ R2, R1 ; R1 = said counter
4822 001 2F9 044 ADDI #1092, R1 ; add 1092 (approximately 2**16 / 60)
4826 251 MVO@ R1, R2 ; save the updated value
4827 203 008 BPL @draw ; if it's negative-looking ...
4829 33D 00D SUBI #13, R5 ; ... adjust the GRAM pointer
; to update the right eye
482B 26A MVO@ R2, R5 ; \
482C 26A MVO@ R2, R5 ; }- right border (R2 = %[..]00000001)
482D 26A MVO@ R2, R5 ; /
482E 268 MVO@ R0, R5 ; --- horizontal line + right border
; (R0 = %[..]11111001)
482F 26A MVO@ R2, R5 ; \__ right border
4830 26A MVO@ R2, R5 ; /
4831 2B9 008 @draw MVII #8, R1 ; draw the tiles
4833 001 SDBD
4834 2B8 007 008 MVII #$807, R0 ; bottom-left
4837 240 281 MVO R0, BT+129
4839 0C8 ADDR R1, R0 ; top-left
483A 240 26D MVO R0, BT+109
483C 0C8 ADDR R1, R0 ; top-right
483D 240 26E MVO R0, BT+110
483F 0C8 ADDR R1, R0 ; bottom-right
4840 240 282 MVO R0, BT+130
4842 004 310 014 J RTN ; return from ISR
ENDP
;; --------------------------------------------------------- ;;
;; tiles data in RBB format: ;;
;; R = number of times to repeat ;;
;; BB = byte to write ;;
;; --------------------------------------------------------- ;;
tiles PROC
; tile #0: bottom-left quarter
4845 184 DECLE (1 SHL 8) OR %10000100
4846 180 DECLE (1 SHL 8) OR %10000000
4847 044 DECLE (0 SHL 8) OR %01000100
4848 043 DECLE (0 SHL 8) OR %01000011
4849 030 DECLE (0 SHL 8) OR %00110000
484A 10F DECLE (1 SHL 8) OR %00001111 ; + 1st row of next tile
; tile #1: top-left quarter
484B 030 DECLE (0 SHL 8) OR %00110000
484C 140 DECLE (1 SHL 8) OR %01000000
484D 384 DECLE (3 SHL 8) OR %10000100
; tile #2: top-right quarter
484E 0F0 DECLE (0 SHL 8) OR %11110000
484F 00C DECLE (0 SHL 8) OR %00001100
4850 102 DECLE (1 SHL 8) OR %00000010
4851 321 DECLE (3 SHL 8) OR %00100001
; tile #3: bottom-right quarter
4852 121 DECLE (1 SHL 8) OR %00100001
4853 101 DECLE (1 SHL 8) OR %00000001
4854 022 DECLE (0 SHL 8) OR %00100010
4855 0C2 DECLE (0 SHL 8) OR %11000010
4856 00C DECLE (0 SHL 8) OR %00001100
4857 0F0 DECLE (0 SHL 8) OR %11110000
; pattern for the horizontal eye
4858 0F9 DECLE (0 SHL 8) OR %11111001
ENDP
Output
PowerShell Core 7.4+, 277 252 227 bytes
for(cls){-split("ff0 300c 4002 4002 $(((,8421*6),"$(,8401*3) 84f9 8401 8401")[++$w%2]) 8001 8001 4422 43c2 300c ff0")|%{1*"0x$_"|% *g b16|% T*y|%{' '|Write-Host -B(15*"$_")-N};''}
sleep -m 500
[Console]::SetCursorPosition(0,0)}
Another -25 bytes off in PowerShell Core 7.4+
.NET 8 introduced the 'b' format specifier, so the expensive
[Convert]::ToString("0x$_",2)|% *ft 16 '0'
can be replaced with
1*"0x$_"|% *g b16
Ungolfed:
[Convert]::ToString("0x$_", 2) | ForEach-Object -Member PadLeft 16 '0'
1*"0x$_" | ForEach-Object -Member ToString b16
PowerShell Windows and Core, 277 252 bytes
for(cls){-split("ff0 300c 4002 4002 $(((,8421*6),"$(,8401*3) 84f9 8401 8401")[++$w%2]) 8001 8001 4422 43c2 300c ff0")|%{[Convert]::ToString("0x$_",2)|% *ft 16 '0'|% T*y|%{' '|Write-Host -B(15*"$_")-N};''}
sleep -m 500
[Console]::SetCursorPosition(0,0)}
-25 bytes thanks to @Julian, who managed to squeeze the bit patterns even further.
One more byte could theoretically be shaved off by using light gray ((7*"$_")) (or any other single-digit color) instead of white ((15*"$_")), but who's counting when it comes to optics.
TIO doesn't support colors (or [console]::SetCursorPosition), so this needs to be saved as script, or pasted into a console. Sorry for the inconvenience.
Note when pasting into a PS console: do NOT use a right-click to paste, use Ctrl-V.
There's a bug in the PSReadline module where a right-click paste inserts the lines in reverse order: Pasting in reverse with right-click #3816
Smiley lines encoded as binary.
Ungolfed (this is not a one-to-one expanded version of the golfed; this is more 'how it began'):
Clear-Host
For (;;) {
$wink = -not $wink
$bits = @(
'ff0 300c 4002 4002 8421 8421 8421 8421 8421 8421 8001 8001 4422 43c2 300c ff0'
'ff0 300c 4002 4002 8401 8401 8401 84f9 8401 8401 8001 8001 4422 43c2 300c ff0'
)[$wink]
$bits | ForEach-Object -Member Split | ForEach-Object {
[Convert]::ToString("0x$_",2) |
ForEach-Object -Member Padleft 16 '0' |
ForEach-Object -Member ToCharArray |
ForEach-Object {' ' | Write-Host -BackgroundColor (15*"$_") -NoNewline}
Write-Output ''
}
Start-Sleep -MilliSeconds 500
[Console]::SetCursorPosition(0,0)
}
Java on Windows, 454 438 384 326 322 bytes
v->{String s="# #\n",t=" # #\n",u=" ## ##\n",w="# # %2$c #\n",x=" ########\n";for(int i=0;;Thread.sleep(500))System.out.printf("\033[H\033[2J%s# # %c #\n"+w+w+"# # %s #\n"+w+w+s+s+" # # # #\n # #### #\n"+u+x,x+u+t+t,35-++i%2*3,i%2<1?" # ":"#####");}
-53 bytes thanks to @jdt, since although printing \033[H\033[2J to clear the Console doesn't work on my local Windows 10 laptop, it does work in this online compiler:
Try it online (click on the maximize icon of the console, and then click run at the top).
-58 bytes thanks to @WeirdGlyphs
Gif in action:
Explanation:
Pretty straight-forward.
v->{ // Method with empty unused parameter and no return-type
String s="# #\n",t=" # #\n",u=" ## ##\n",w="# # %2$c #\n",x=" ########\n";
// Temp Strings for some repeating parts
for(int i=0 // Integer `i`, starting at 0
; // Loop indefinitely:
; // After every iteration:
Thread.sleep(500)) // Sleep 500 ms
System.out.printf( // Print:
"\033[H\033[2J "// Two commands to clear the Console:
// `33[H` moves the cursor to the top-left;
// `33[2J` then clears the console
"%s# # %c #\n"+w+w+"# # %s #\n"+w+w+s+s+" # # # #\n # #### #\n"+u+x,
// And then print the output-string,
// and replace the first `%s` with:
x+u+t+t, // temp Strings `x+u+t+t`
// Then replace all its `%c` and `%2$c` with:
35- // 35 minus:
++i // Increase `i` by 1 first with `++i`
%2 // Modulo-2
*3 // Multiplied by 3
// (35/'#' if `i` is now odd;
// 32/' ' if `i` is now even)
// And finally replace the second `%s` with:
i%2<1? // If `i` is even:
" # " // Replace the `%s` with " # "
: // Else (`i` is odd)
"#####");} // Replace the `%s` with "#####" instead
Perhaps there is a way to compress the String, but knowing Java, I doubt it would be shorter anyway, so I haven't bothered trying..
Commodore 64 Assembler, 93 Bytes (6502/KickAssembler)
TL;DR
The code generates the graphics into a C64 sprite. It first copies the right side of the sprite from the gfx table, mirrors it to the left side, and then toggles between open and winking eye graphics every ~500ms by using an XOR bitmask. There's also some code for cleaning up the unused sprite graphics memory, as C64 sprites are 24x21 pixels and we use only 16x16 pixel area of that.
Code
.const sprite = $40 // Sprite graphics will be generated here on zero page
.const data_ptr = $80 // Free pointer to $20c9, ie. 1st byte of sprite gfx data
* = $20c9
gfx: .by %11110000 // Right side of the sprite. Mirrored in code for left side.
.by %00001100 // Flipped horizontally so that the incrementing data pointer
.by %11000010 // will end up pointing to the EOR mask table after gfx data
.by %00100010 // has been copied to sprite.
.by %00000001
.by %00000001
.by %00100001
.by %00100001
.by %00100001
.by %00100001
.by %00100001
.by %00100001
.by %00000010
.by %00000010
.by %00001100
.by %11110000
eormask:.by %00100001^%00000001 // These 6 bytes are an EOR mask that toggles
.by %00100001^%00000001 // between open and winking eye graphics.
.by %00100001^%00000001
.by %00100001^%11111001
.by %00100001^%00000001
.by %00100001^%00000001
// Start with SYS 8415
ldx #62 // 2 First we need to create 63 (0-62) bytes of sprite data
stx $d000 // 3 Save 62 as Sprite #0 X and Y positions (otherwise the
stx $d001 // 3 sprite would be hidden in top left, behind the border)
draw: sty sprite,x // 2 Y=0 here. Clear rightmost byte of sprite pixel row
dex // 1 Decrement sprite byte pointer
cpx #47 // 2 Repeat until we've cleared sprite pixel rows 17-21
bcs draw // 2 If we still have complete rows to clear, repeat
lda (data_ptr),y // 2 Load byte from sprite graphics data
sta sprite,x // 2 Save as middle byte on sprite pixel row
inc data_ptr // 2 Increment sprite graphics data pointer
dex // 1 Decrement sprite byte pointer
bit $2 // 2 Reverses order of bits in a byte. Found from an old
!: php // 1 Google groups thread. Just 10 bytes. There's another
asl // 1 10 byte solution but it uses X register which we need
bne !- // 2 ourselves. Super clever: Pushes the bits from left
!: rol // 1 into the carry flag and saves processor flags to stack,
plp // 1 then pulls the flags and pushes carry to the byte from
bne !- // 2 the right, effectively reversing the order.
sta sprite,x // 2 Save mirrored byte (left side of smiley) to sprite
dex // 1 Decrement sprite byte pointer
bpl draw // 2 Loop back until we've drawn all sprite pixel rows
iny // 1 Increment Y to 1
sty $d015 // 3 Sprite enable register - enable Sprite #0
sty $07f8 // 3 Sprite #0 pointer - point to the 2nd 64 byte block in memory
anim: ldy #5 // 2 Animate eye winking: Change 6 bytes of graphics on sprite
ldx #12 // 2
!: lda sprite+16,x // 2 Load an eye byte from sprite
eor (data_ptr),y // 2 EOR it with mask to toggle between open and winking eye
sta sprite+16,x // 2 Save toggled eye byte to sprite
dex // 1 Decrement sprite byte pointer three times to point to...
dex // 1 ...the same byte on previous row
dex // 1
dey // 1 Decrement EOR mask table index
bpl !- // 2 Loop until all 6 bytes have been changed
delay: jsr $eeb3 // 3 KERNAL routine: 1ms delay
jsr $eeb3 // 3 KERNAL routine: 1ms delay
dex // 1 X=250 when we enter the delay loop
bne delay // 2 repeat for 250 times
beq anim // 2 Animate, delay, rinse and repeat
Usage
Run the program with SYS 8415.
Explanation
Quite a few tricks were used to make the code smaller:
- When we init the X index for the sprite generating routine, we reuse that value for moving the sprite to a visible part of the screen (ie. away from far top left, behind the border). Saves 2 bytes.
- Sprite is generated to the first fully available 64 byte block on zero page. This allows us to use 8bit addressing instead of 16bit, saving 5 bytes. It also enables us to use another trick later to save additional 2 bytes.
- As sprite is located on the 2nd 64 byte block of memory (index=1), we can use 1 for both setting the sprite pointer and enabling the sprite. Saves 2 bytes.
- As Y is 0 after the SYS command, we keep it as 0 and use it to clear the redundant bytes of the sprite, saving 2 bytes. Also we later increment Y to 1 for setting the aforementioned sprite pointer and enabling the sprite, saves 1 byte vs. loading an immediate value.
- Sprite graphics table is located to address $20c9, which allows us to use addresses $80-$81 of KERNAL's CHRGET routine on zero page as an indirect pointer to it, saving 2 bytes.
- The sprite drawing routine increments the pointer after reading a byte from the gfx table, meaning that after it's read all the bytes from the table, the pointer conveniently points to the next table in memory (eor mask table). This later saves us a byte in the eye winking routine.
- Instead of defining the 16 left hand side bytes of the smiley gfx, we use a neat little bit reversing routine of just 10 bytes to mirror the right hand side, thus savings of 6 bytes.
- Winking animation is done by toggling the pixels of the right eye with an XOR bitmask (eye is 6 pixels high, thus we need to toggle 6 bytes of the sprite). I don't know what the exact saving is here versus e.g. toggling a pointer between two 6-byte pieces of graphics, but the XOR bitmask method was at least 3-4 bytes smaller than the smallest gfx toggling method I could come up with.
- Delay is implemented by calling the KERNAL's 1ms delay routine twice, and then repeating it 250 times. In the animation routine we take advantage of the 6502 CPU's feature (some call it the page crossing bug): If e.g. we have an instruction
STA $ff,x, and X is 2, A is getting saved into address $0001 instead of $0101. For the anim routine, we set the value of X in such a way that it is 250 when we continue from the routine to the delay, and then just compensate the offset in the base address of theSTA NN,xinstruction. This negates the need to init X for the delay routine, saving 2 bytes.
JS, 398 366 246 bytes
New method
Setting image src to a base64 gif of the smiley/winkey.
b=1,setInterval(_=>document.open().write(`<img src=data:image/gif;base64,R0lGODdhEAAQAIAAAAAAAP///yH5BAgKAAAALAAAAAAQABAAAAIpjAOpecftgIMUGVmbx${['Fdrbk2RJ17g+ZHdWIZmRj3wxKHrqagytJvLXg','DcjbmVPJ4LYcpreGFas98Faq5KmMl+gtn8oWA'][b^=1]}AAOw==>`),500)
Old method
Saving image as hex, and printing each pixel to canvas.
a="0ff0300c4002400284218421842184218421842180018001442243c2300c0ff0",d=document,d.write("<canvas>"),x=d.querySelector("canvas").getContext("2d"),f=0,setInterval((_=>(f?a.replace(a.substr(18,21),"018401840184f98401840"):a).match(/.{1,2}/g).map((n=>(+("0x"+n)).toString(2).padStart(8))).join``.split``.map((f=!f,x.reset(),(b,i)=>+b&&x.fillRect(i%16,i/16|0,1,1)))),500)
a="0ff0300c4002400284218421842184218421842180018001442243c2300c0ff0", // Original image converted into bytes (ex. 11111111 -> ff)
d=document,d.write("<canvas>"),x=d.querySelector("canvas").getContext("2d"), // Setting up canvas
f=0, // Image flipper boolean
setInterval(
_=>(f?a.replace(a.substr(18,21),"018401840184f98401840"):a) // Replacing winking eye bytes every 0.5 sec
.match(/.{1,2}/g) // Splitting image string into bytes
.map(n=>(+("0x"+n)).toString(2).padStart(8)) // ... and turning them into 8 bit chunks (empty spaces will be converted to zeroes)
.join`` // ... flattening all the bits into a single string
.split``.map(
(f=!f,x.reset(),(b,i)=>+b&&x.fillRect(i%16,i/16|0,1,1)) // Flipping boolean, clearing canvas, drawing each pixel (i/16|0 same as Math.floor(i/16))
),
500
)
Edits
398-> 390:Math.floor()->~~390-> 386:forEach->map386-> 381: Removed setting canvas to a var, removed semicolon from the end.- Added expanded code and explanation.
381-> 377: Removed extra parentheses and one NOT (!)377-> 376: Turned function parentheses into_376-> 374: Changed how I floor the y position (from~~(i/16)toi/16|0).374-> 372: Removed extra{}from around draw func.372-> 366: Converted two function calls from("")-> to `` (thanks @Weird Glyphs), and removed padding0from padStart, as spaces will be falsy.366-> 246: Changed to a simpler solution using base64 gifs.
HTML + CSS + JS, 588 432 bytes
Disclaimer: Entirely based on @A.L's answer.
New version: encoded the bitmap as a base-5 BitInt -- Oops, now below 512 bytes.
<style>.b{background:#000}</style><table><script>w=0x3e069e01a401efc9ea7fe983ad46adaa384a346fdd0397dccfb1907ddd5e9ac3c2c69c82ffc3ee9c41e812d4f1094c58672f9e16b215bb9ee03929e83e12580d4b5ec76d63ece8aea0d85ef67f4n
s=1
u=document
setInterval(_=>{for(t of'ft')for(e of u.querySelectorAll('.'+t))e.classList.toggle('b',s^t=='t')
s^=1},500)
for(l=271;c=w%5n,l--;w/=5n)u.write(c==4?'<tr>':`<td class=${'0bft'[c]} width=7 height=9>`)</script>
Produced by the following Python script from the bitmap in @A.L's answer:
for ch in reversed(wink):
result *= 5
if ch == '\n':
result += 4
else:
result += int(ch)
Edits:
- Remove margin and padding CSS:
506476 bytes (thanks @Ray Wallace); also reduced the width oftds so they remain squares. - Use hex BigInt literals
476446 bytes. - Absorb the divmod operation into the loop condition
446442 bytes. - Use
setIntervalinstead ofsetTimeout442434 bytes. - Change the last loop to a C-style
forloop434432 bytes.
Old:
Still 77 bytes to go before we can make it 512.
<style>*{margin:0;padding:0;border:0}.b{background:#000}</style><table><script>w="0000bbbbbbbb0000D00bb00000000bb00D0b000000000000b0D0b000000000000b0Db0000b0000t0000bDb0000b0000t0000bDb0000b0000t0000bDb0000b00ffbff00bDb0000b0000t0000bDb0000b0000t0000bDb00000000000000bDb00000000000000bD0b000b0000b000b0D0b0000bbbb0000b0D00bb00000000bb00D0000bbbbbbbb0000"
s=1
u=document
f=()=>{for(t of'ft')for(e of u.querySelectorAll('.'+t))e.classList.toggle('b',s^t=='t')
s^=1
setTimeout(f,500)}
f()
w.split('D').map(l=>{u.write('<tr>')
for(c of l)u.write(`<td class=${c} width=9 height=9>`)})</script>
ZX Spectrum Basic, 293 bytes
1 OVER SGN PI: LET a$="2 2 13
3-13 5 03 3 12 1 23-1 33 0 53 1
32 2143 3 13 5 03 3-1214 23 1 3
3 0 53-1 32 5 32 6 23 3 0210 32
5 63 0 52 8 83 4 0425552 8 83 4
0210 63 0 542555210 63 0 555555"
: FOR i=VAL "5" TO LEN a$ STEP V
AL "5": LET x=VAL a$(i-INT PI TO
i-VAL "2"): LET y=VAL a$(i-SGN
PI TO i): GO TO VAL a$(i-VAL "4"
)
2 PLOT x,y: NEXT i
3 DRAW x,y: NEXT i
4 PAUSE x: NEXT i
5 LET i=x+y: NEXT i
Line 1 is very long but it looks like that on the ZX Spectrum because its lines are only 32 characters wide. It starts by turning on overplot, which makes it easy to erase. It then defines a string of compressed plot instructions as sets of five characters, the first being the line number to execute, then two pairs of two-digit numbers being the x and y values. The string is looped over, the values are extracted and the appropriate line is executed. The 55555 at the end actually causes the code to loop back to a previous point of the string. The timing is a little shaky because ZX Spectrum Basic is quite slow but the 425s can be lowered a little to speed it up. Unfortunately I don't have any video capture facility to show you what the live output looks like, so here are two screen captures from an emulator:
HTML + CSS + JS, 1024 bytes
I didn't try to optimize it much, I just tried to start from an ASCII representation of the pixels (maybe it can help other people), then minimized it to 1 kb.
The code will draw a HTML table with the different possible states:
0: always white pixel1: always black pixel2and3: alternate between black and white
A JS loop will switch on and off the pixels of the right eye.
Quickly minimized version and output
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<style>
* {margin: 0;padding: 0;border: none;}td {width: 10px;height: 10px;}.t1 {background: #000}
</style>
<script>
var wink = `0000111111110000
0011000000001100
0100000000000010
0100000000000010
1000010000300001
1000010000300001
1000010000300001
1000010022122001
1000010000300001
1000010000300001
1000000000000001
1000000000000001
0100010000100010
0100001111000010
0011000000001100
0000111111110000`;
var state = true;
function flipState() {
document.querySelectorAll(state ? '.t2' : '.t3').forEach((element) => {element.classList.add('t1');});document.querySelectorAll(state ? '.t3': '.t2').forEach((element) => {element.classList.remove('t1');});state = !state;setTimeout('flipState()', 500);}
flipState();
</script>
</head><body><table><script>
wink.split('\n').forEach(function (line) {document.write('<tr>');line.split('').forEach(function (char) {document.write('<td class="t' + char+ '"></td>');});document.write('</tr>');});
</script></table></body>
</html>
Ungolfed
Use any tool to reformat this code with new lines between blocks.






