39
\$\begingroup\$

In 2014, demoscener Jakub 'Ilmenit' Debski released a 250-byte(1) procedural graphics demo for the Atari XL called Mona. It's drawing the following picture(2):

mona

Your task is to generate the exact same picture, using the language of your choice.


(1) Breakdown: 136 bytes of data + 114 bytes of code.
(2) The original picture is 128x96. The above version was magnified to 256x192. A few pixels differ from the original, but this is the expected output with the pseudo-code described in this challenge.

How?

This is . Although you're authorized to use any method, best results will most probably be achieved by using the original algorithm which is described below.

NB: This paragraph is not a specification but rather a general description. Please refer to the pseudo-code and the reference implementation for the details of the algorithm.

The image is made of 64 pseudo-random brush strokes (see this video), cycling through the following colors (in RRGGBB hexadecimal format):

COLOR = [ 0xFFE289, 0xE99E45, 0xA55A00, 0x000000 ]

The background is initially filled with the 4th color (black). Each stroke is shorter than the previous one.

The pseudo-random generator is using a Linear-Feedback Shift Register (LFSR) on a 32-bit integer initially set to 0x7EC80000 and XOR'ed with 0x04C11DB7.

Each stroke is initialized with a 16-bit value which overwrites the lowest bytes of the seed:

BRUSH = [
  0x030A, 0x37BE, 0x2F9B, 0x072B, 0x0E3C, 0xF59B, 0x8A91, 0x1B0B,
  0x0EBD, 0x9378, 0xB83E, 0xB05A, 0x70B5, 0x0280, 0xD0B1, 0x9CD2,
  0x2093, 0x209C, 0x3D11, 0x26D6, 0xDF19, 0x97F5, 0x90A3, 0xA347,
  0x8AF7, 0x0859, 0x29AD, 0xA32C, 0x7DFC, 0x0D7D, 0xD57A, 0x3051,
  0xD431, 0x542B, 0xB242, 0xB114, 0x8A96, 0x2914, 0xB0F1, 0x532C,
  0x0413, 0x0A09, 0x3EBB, 0xE916, 0x1877, 0xB8E2, 0xAC72, 0x80C7,
  0x5240, 0x8D3C, 0x3EAF, 0xAD63, 0x1E14, 0xB23D, 0x238F, 0xC07B,
  0xAF9D, 0x312E, 0x96CE, 0x25A7, 0x9E37, 0x2C44, 0x2BB9, 0x2139
];

These values are also used to set the new position (bx, by) of the brush at the beginning of the stroke: bx is given by the least significant byte and by is given by the most significant byte.

The direction of the stroke is given by bits #1 and #7 of the seed. (See the SWITCH statement in the pseudo-code.)

Pseudo-code

Below is the algorithm in pseudo-code, assuming 0-indexed arrays, where AND, OR and XOR mean bitwise operations.

seed = 0x7EC80000
dir = 0x00

FOR part = 0 TO 63
  word = BRUSH[part]
  seed = (seed AND 0xFFFF0000) OR word
  bx = word AND 0xFF
  by = (word >> 8) AND 0xFF

  FOR len = 0 TO (64 - part) * 32 - 1
    carry = seed AND 0x80000000
    seed = (seed << 1) AND 0xFFFFFFFF

    IF carry
      seed = seed XOR 0x04C11DB7
      dir = seed AND 0xFF
    ENDIF

    SWITCH dir AND 0x82
      CASE 0x00:
        by = (by + 1) AND 0x7F
      ENDCASE
      CASE 0x02:
        bx = (bx + 1) AND 0x7F
      ENDCASE
      CASE 0x80:
        by = (by - 1) AND 0x7F
      ENDCASE
      CASE 0x82:
        bx = (bx - 1) AND 0x7F
      ENDCASE
    ENDSWITCH

    drawPixel(bx, by, COLOR[part AND 3])
  ENDFOR
ENDFOR

Reference implementation

Below is an ungolfed reference implementation in JavaScript.

const SEED    = 0x7EC80000,
      XOR_MSK = 0x04C11DB7,
      COLOR   = [
        '#FFE289', '#E99E45', '#A55A00', '#000000'
      ],
      BRUSH   = [
        0x030A, 0x37BE, 0x2F9B, 0x072B, 0x0E3C, 0xF59B, 0x8A91, 0x1B0B,
        0x0EBD, 0x9378, 0xB83E, 0xB05A, 0x70B5, 0x0280, 0xD0B1, 0x9CD2,
        0x2093, 0x209C, 0x3D11, 0x26D6, 0xDF19, 0x97F5, 0x90A3, 0xA347,
        0x8AF7, 0x0859, 0x29AD, 0xA32C, 0x7DFC, 0x0D7D, 0xD57A, 0x3051,
        0xD431, 0x542B, 0xB242, 0xB114, 0x8A96, 0x2914, 0xB0F1, 0x532C,
        0x0413, 0x0A09, 0x3EBB, 0xE916, 0x1877, 0xB8E2, 0xAC72, 0x80C7,
        0x5240, 0x8D3C, 0x3EAF, 0xAD63, 0x1E14, 0xB23D, 0x238F, 0xC07B,
        0xAF9D, 0x312E, 0x96CE, 0x25A7, 0x9E37, 0x2C44, 0x2BB9, 0x2139
      ];

var ctx = document.getElementById('output').getContext('2d'),
    seed = SEED,
    bx, by, word, len, carry,
    dir = 0,
    part;

ctx.fillStyle = COLOR[3];
ctx.fillRect(0, 0, 128 * 2, 128 * 2);

for(part = 0; part < 64; part++) {
  word = BRUSH[part];
  seed = (seed & 0xffff0000) | word;
  bx = word & 0xff;
  by = (word >> 8) & 0xff;

  ctx.fillStyle = COLOR[part & 3];

  for(len = 0; len < (64 - part) * 32; len++) {
    carry = seed & 0x80000000;
    seed <<= 1;

    if(carry) {
      seed ^= XOR_MSK;
      dir = seed & 0xff;
    }

    switch(dir & 0x82) {
      case 0x00:
        by = (by + 1) & 0x7f;
        break;

      case 0x02:
        bx = (bx + 1) & 0x7f;
        break;

      case 0x80:
        by = (by - 1) & 0x7f;
        break;

      case 0x82:
        bx = (bx - 1) & 0x7f;
        break;
    }
    ctx.fillRect(bx * 2, by * 2, 2, 2);
  }
}
<canvas id="output" width=256 height=192></canvas>

You can also see an animated version here.

Clarification and rules

  • The output must be cropped to 128x96, even though the algorithm draws outside this area.
  • If your language/platform is not able to output the exact colors described above, you must use colors that are as close as possible.
  • Should you decide to use an alternate method, you still must generate the exact same output.
  • Just in case: submitting the original 6502 assembly code or any slightly edited version is not allowed.
  • Can you beat 250 bytes? Happy drawing!
\$\endgroup\$
  • 1
    \$\begingroup\$ The "you're encouraged to" is problematic, because if doing so conflicts with saving bytes, should someone do so or not? It should either be "you must" (do it even if it costs bytes), or "you may" (do it only if it saves bytes). \$\endgroup\$ – user62131 Jun 16 '17 at 2:19
  • 1
    \$\begingroup\$ Usually I think it's better to split the ascii option into another challenge, otherwise there are kind of 2 sub-challenges anyway. \$\endgroup\$ – FryAmTheEggman Jun 16 '17 at 2:33
  • 1
    \$\begingroup\$ @FryAmTheEggman It was originally meant to be graphical output only and adding this ASCII option was probably a bad idea indeed. Hopefully I'm not ruining some WIP answer by removing it... \$\endgroup\$ – Arnauld Jun 16 '17 at 2:47
  • 4
    \$\begingroup\$ @ATaco Paint Starry Nigh was a code-challenge with a different goal (reproducing the image as closely as possible). This one is plain kolmogorov-complexity with a constant output. \$\endgroup\$ – Arnauld Jun 16 '17 at 2:57
  • 1
    \$\begingroup\$ That's understandable, Redacting my close vote. \$\endgroup\$ – ATaco Jun 16 '17 at 3:10

14 Answers 14

7
\$\begingroup\$

x86 opcode, 227 224 223 Bytes

0000h: 68 20 A8 07 B8 13 00 CD 10 66 BF 40 00 C8 7E 5A
0010h: 89 FD BE 5B 01 AD 89 C7 89 E9 C1 E1 05 66 D1 E7
0020h: 73 09 66 81 F7 B7 1D C1 04 89 FA 80 E2 82 74 09
0030h: 7A 04 78 08 40 40 05 7F 7F 80 C4 02 FE CC 25 7F
0040h: 7F 89 EB 83 E3 03 8A B7 DB 01 88 E3 6B DB 40 01
0050h: C3 26 88 37 E2 C7 4D 75 BC EB FE 0A 03 BE 37 9B
0060h: 2F 2B 07 3C 0E 9B F5 91 8A 0B 1B BD 0E 78 93 3E
0070h: B8 5A B0 B5 70 80 02 B1 D0 D2 9C 93 20 9C 20 11
0080h: 3D D6 26 19 DF F5 97 A3 90 47 A3 F7 8A 59 08 AD
0090h: 29 2C A3 FC 7D 7D 0D 7A D5 51 30 31 D4 2B 54 42
00a0h: B2 14 B1 96 8A 14 29 F1 B0 2C 53 13 04 09 0A BB
00b0h: 3E 16 E9 77 18 E2 B8 72 AC C7 80 40 52 3C 8D AF
00c0h: 3E 63 AD 14 1E 3D B2 8F 23 7B C0 9D AF 2E 31 CE
00d0h: 96 A7 25 37 9E 44 2C B9 2B 39 21 43 00 06 42   

  0100 6820A8                 push A820
  0103 07                     pop es
  0104 B81300                 mov ax, 0013
  0107 CD10                   int 10
  0109 66BF4000C87E           mov edi, 7EC80040
  010F 5A                     pop dx
  0110 89FD                   mov bp, di
  0112 BE5B01                 mov si, 015B
  0115 AD                     lodsw
  0116 89C7                   mov di, ax
  0118 89E9                   mov cx, bp
  011A C1E105                 shl cx, 05
  011D 66D1E7                 shl edi, 01
  0120 7309                   jnb 012B
  0122 6681F7B71DC104         xor edi, 04C11DB7
  0129 89FA                   mov dx, di
  012B 80E282                 and dl, 82
  012E 7409                   je 0139
  0130 7A04                   jpe 0136
  0132 7808                   js 013C
  0134 40                     inc ax
  0135 40                     inc ax
  0136 057F7F                 add ax, 7F7F
  0139 80C402                 add ah, 02
  013C FECC                   dec ah
  013E 257F7F                 and ax, 7F7F
  0141 89EB                   mov bx, bp
  0143 83E303                 and bx, 0003
  0146 8AB7DB01               mov dh, [bx+01DB]
  014A 88E3                   mov bl , ah
  014C 6BDB40                 imul bx, 0040
  014F 01C3                   add bx, ax
  0151 268837                 mov es:[bx], dh
  0154 E2C7                   loop 011D
  0156 4D                     dec bp
  0157 75BC                   jne 0115
  0159 EBFE                   jmp 0159
  015B 0A03BE37...3921        brush_dw
  01DB 43000642               color_db

Image: enter image description here

\$\endgroup\$
  • 1
    \$\begingroup\$ Would you mind including an explanation of this and a screenshot of the output - as it is it is not self explanatory \$\endgroup\$ – Taylor Scott Dec 28 '17 at 19:42
  • \$\begingroup\$ Should I use a camera or a virtual environment, as I run it on full screen and no screen capture anymore \$\endgroup\$ – l4m2 Dec 29 '17 at 3:20
  • 1
    \$\begingroup\$ Image: imagebin.ca/v/3mJb1bFSlGRY \$\endgroup\$ – l4m2 Dec 29 '17 at 3:34
  • 1
    \$\begingroup\$ 0122 6681F7B71DC104 xor edi, 00001DB7 bug found in W32Dasm \$\endgroup\$ – l4m2 Mar 9 '18 at 17:03
22
\$\begingroup\$

8086 Assembly - NASM (MBR) - 248 245 bytes

[org 0x7C00]
[bits 16]
    push 0xA000
    pop es
    mov si, $brush
    xor cx, cx

    mov ax, 0x0013
    int 0x10

    mov ebx, 0x7EC80000

part_loop:
    lodsw
    mov bx, ax

    mov bp, 64
    sub bp, cx
    shl bp, 5
    mov sp, bp

len_loop:
    shl ebx, 1
    jnc not_carry
    xor ebx, 0x04C11DB7
    mov dh, bl
    not_carry:

    and dh, 0x82
    je dir_00
    jpe dir_82
    js dir_80
    dir_02:
        inc al  
        jmp dir_end
    dir_82:
        dec al
        jmp dir_end
    dir_00:
        inc ah
        jmp dir_end 
    dir_80:
        dec ah  
    dir_end:

    and ax, 0x7F7F
    cmp ah, 96
    jae skip

    movzx di, ah
    movzx bp, al
    imul di, 320
    add di, bp
    mov bp, cx
    and bp, 3
    mov dl, byte[bp + color]
    mov [es:di], dl
    skip:

    dec sp
    jnz len_loop
    inc cx
    cmp cx, 64
    jl part_loop    
    jmp $

color:
    db 0x43, 0x42, 0x06, 0x00

brush:
    dw  0x030A, 0x37BE, 0x2F9B, 0x072B, 0x0E3C, 0xF59B, 0x8A91, 0x1B0B
    dw  0x0EBD, 0x9378, 0xB83E, 0xB05A, 0x70B5, 0x0280, 0xD0B1, 0x9CD2
    dw  0x2093, 0x209C, 0x3D11, 0x26D6, 0xDF19, 0x97F5, 0x90A3, 0xA347
    dw  0x8AF7, 0x0859, 0x29AD, 0xA32C, 0x7DFC, 0x0D7D, 0xD57A, 0x3051
    dw  0xD431, 0x542B, 0xB242, 0xB114, 0x8A96, 0x2914, 0xB0F1, 0x532C
    dw  0x0413, 0x0A09, 0x3EBB, 0xE916, 0x1877, 0xB8E2, 0xAC72, 0x80C7
    dw  0x5240, 0x8D3C, 0x3EAF, 0xAD63, 0x1E14, 0xB23D, 0x238F, 0xC07B
    dw  0xAF9D, 0x312E, 0x96CE, 0x25A7, 0x9E37, 0x2C44, 0x2BB9, 0x2139


times 510 - ($-$$) db 0
DB 0x55
DB 0xAA

mona.jpg

\$\endgroup\$
  • 6
    \$\begingroup\$ Oh hey, an answer that beats the score in the question (assuming an accurate byte count). Nice! \$\endgroup\$ – Draco18s Jun 21 '17 at 20:48
  • \$\begingroup\$ Welcome to PPCG! wonderful first post. \$\endgroup\$ – Taylor Scott Jun 22 '17 at 18:50
  • \$\begingroup\$ You can reduce to 245 bytes if you remove useless xor dx,dx and change mov bp,0xa000; mov es,bp to push 0xa000; pop es. \$\endgroup\$ – Ruslan Jun 23 '17 at 12:43
  • 1
    \$\begingroup\$ It's not 8086. 8086 has no PUSH imm \$\endgroup\$ – l4m2 Dec 28 '17 at 16:15
  • 1
    \$\begingroup\$ Basic optimize to 240 paste.ubuntu.com/26272648 \$\endgroup\$ – l4m2 Dec 28 '17 at 16:52
18
\$\begingroup\$

Excel VBA 32-Bit, 1011 720 Bytes

Revision 49; ΔScore=291 Bytes

Golfed

Full Subroutine that takes no input and outputs the Mona Lisa to the ActiveSheet object on the range [A1:DX96].

There was a lot of black magic involved in golfing this down to its current state, - of note, some of the tricks involved are pixel art prep, bit shifting colors implicit type conversion, and base64 compression compressing bytes as a String.

Sub M
h Cells,0
t="5¼-™):󙈏"+vbTab+"»‘v¶<®Xn³"+chr(0)+"~ίšÐ‘š;$ÔÝ•óŽ¡¡EˆõW'«¡*{ú{Óx.OÒ/R)°@¯ˆ”'®ïQ*<¹çu¶àªp~ÅP>‹:<­«a°;!¾y­›/,”Ì#¥œ5*B)·7
s=4057*2^19
j=127
For p=0To 63
w=(Asc(Mid(t,2*p+1))+2)*256&+Asc(Mid(t,2*p+2))+2
s=s And-4^8Or w
x=255And w
y=255And w/2^8-.5
For l=1To(64-p)*32
c=s And-2^31
z=2^30And s
s=(1073741823And s)*2
s=IIf(z,s Or-2^31,s)And-1
If c Then:s=79764919Xor s:d=255And s
d=130And d
y=IIf(d,IIf(d=128,y-1And j,y),y+1And j)
x=IIf(d=2,x+1And j,IIf(d=130,x-1And j,x))
h[B2].Cells(y,x),Array(9036543,4562665,23205,0)(3And p)
Next l,p
h[97:999,DY:ZZ],0
End Sub
Sub h(r,c)
r.Interior.Color=c
r.RowHeight=48
End Sub

Note: This solution has been restricted to 32-Bit versions of Excel VBA as ^ is the LongLong type literal in 64-Bit versions

Note, The Second: The string is line 3 is not a comment as is not equivalent to "

Output

Gif showing ouput to the ActiveSheet when M is called in the VBE immediate window. Note that due to file size limitations this fig gif has fewer frames than actually produced. Mona

Ungolfed

Ungolfed full subroutine that takes no input and produces the mona lisa using the method described above on the ActiveSheet object

Option Private Module
Option Compare Text
Option Explicit
Option Base 0


Public Sub MonaLisa()
    On Error GoTo 0

    Dim part As Integer, _
        length As Integer, _
        M As Long, _
        seed As Long, _
        dir As Long, _
        word As Long, _
        carry As Long, _
        bx As Byte, _
        by As Byte, _
        BRUSH, _
        COLOR

    Let COLOR = Array(&H89E2FF, &H459EE9, &H5AA5, 0)
    Let BRUSH = Array( _
            778, 14270, 12187, 1835, 3644, 62875, 35473, 6923, _
            3773, 37752, 47166, 45146, 28853, 640, 53425, 40146, _
            8339, 8348, 15633, 9942, 57113, 38901, 37027, 41799, _
            35575, 2137, 10669, 41772, 32252, 3453, 54650, 12369, _
            54321, 21547, 45634, 45332, 35478, 10516, 45297, 21292, _
            1043, 2569, 16059, 59670, 6263, 47330, 44146, 32967, _
            21056, 36156, 16047, 44387, 7700, 45629, 9103, 49275, _
            44957, 12590, 38606, 9639, 40503, 11332, 11193, 8505)

    Let dir = 0
    Let carry = 0
    Let seed = &H7EC80000

    Let Cells.Interior.Color = 0
    Let Cells.ColumnWidth = 2

    Call Range("A1:DX96").Select
    Let ActiveWindow.Zoom = True
    Call Range("A1").Select

    For part = 0 To 63 Step 1

        Call VBA.DoEvents

        Let word = BRUSH(part)
        Let seed = (seed And &HFFFF0000) Or word

        Let bx = word And 255
        Let by = Int(word / (2 ^ 8)) And 255

        For length = 0 To (64 - part) * 32 - 1 Step 1

            Let carry = seed And &H80000000
            Let M = seed And &H40000000
            Let seed = (seed And &H3FFFFFFF) * 2
            If M <> 0 Then Let seed = seed Or &H80000000

            Let seed = seed And &HFFFFFFFF

            If carry Then
                Let seed = seed Xor 79764919
                Let dir = Int(seed And 255)
            End If

            Select Case dir And 130
                Case 0:   Let by = Int(by + 1) And 127
                Case 2:   Let bx = Int(bx + 1) And 127
                Case 128: Let by = Int(by - 1) And 127
                Case 130: Let bx = Int(bx - 1) And 127
            End Select
            Let Cells(by + 1, bx + 1).Interior.Color = COLOR(part And 3)
        Next length
    Next part

    Let Range("97:999,DY:ZZ").Interior.Color=0

End Sub
\$\endgroup\$
  • 4
    \$\begingroup\$ Hey, nice animation! \$\endgroup\$ – Arnauld Jun 20 '17 at 20:27
  • \$\begingroup\$ @Arnauld, thanks :P it took more work than it should have \$\endgroup\$ – Taylor Scott Jun 21 '17 at 0:45
10
\$\begingroup\$

HTML + CSS + JavaScript (ES6), 499 bytes

  • HTML: 33 bytes
  • CSS: 17 bytes
  • JS: 678 ... 478 475 473 465 459 455 451 447 449 bytes

It's nowhere near 250 bytes, but I'll definitely settle for under 500 bytes! Huge thanks to @Arnauld and @Firefly for helping me golf this monster down.

with(C.getContext`2d`)for(s=4057<<19,d=n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x,y,1,1))(s*=2)/2>>31&&(d=s^=79764919),D=d&128?-1:1,d&2?x=x+D&127:y=y+D&127
*{background:#000
<canvas id=C width=128 height=96>

For a bigger scale, replace the CSS with the following:

canvas { background: #000; image-rendering: pixelated; zoom: 3 }

Annotated History!

I had a blast golfing Arnauld's reference code, and you can get some of that here. Enjoy!

// One pass through Closure Compiler ADVANCED mode
// Added with statement, golfed switch statement, golfed color array
// I was surprised Closure Compiler didn't touch the switch statement, like, at least convert it into a bunch of conditional statements.
with(C.getContext("2d")){e=2127036416;m=0;fillRect(0,0,256,256);for(n=0;n<64;n++)for(h=[778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505][n],e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e<<=1,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1);}

// Background moved to CSS
with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=[778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505][n],e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e<<=1,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1);}

// e<<=1 same as e*=2
with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=[778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505][n],e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1);}

// Semicolon
with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=[778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505][n],e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)}

// Failed to golf those colors down ;-;
a=n=>["FFE289","E99E45","A55A00","000"][n&3]
b=n=>"FFE289E99E45A55A00000".substr(n%4*6,6)
c=n=>btoa`Q6óÑ=ôN9@ÓM4ÓM4`.substr(n%4*6,6)  // <-- there are 2 unprintables somewhere in there
A = [0,1,2,3]
console.log(A.map(n=>a(n)))
console.log(A.map(n=>b(n)))
console.log(A.map(n=>c(n)))
d=n=>`FFE289 E99E45 A55A00 000`.split` `[n&3]


// Let's compress that hunky array of numbers...
[778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505].map(n=>String.fromCharCode(n)).join``
`̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ`.charCodeAt(n)

// And the char at n=20 became 65533 instead of 57113??
with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=`̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ`.charCodeAt(n),e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)}

// Maybe try replacing that char with \u000? (Nope, editor doesn't like that at all)
with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=`̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ`.charCodeAt(n)||57113,e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)}

// Okay, just check if n is 20 and make an exception.
with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=n-20?`̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ`.charCodeAt(n):57113,e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)}

// Also, this could work too... (how to do byte comparison properly? Not so knowledgeable about encodings)
+('0x'+btoa`Ó}ß°DØ_AÓ½ÐMÂAðuÔÐ@C÷~üÍÄN@ï@yÓo4@uô öÛOwÛOBÜ=uÛ ú]}÷±y÷@7~;ð{ÓÎ}ÛÐ}ì1BÐ>ÃÀßNuõçn6]xðzÛÝxAuç}ÓwÐ
=Ü@AÝz×ÎûÁ6.öó@»çn4ð=ÂÜ@>·ÔMxmÃÛNÁ_Cß]÷ Û;ôMûØ.8Ø}Û]ý`.substr(n*4,4))


// ES6 template string syntax, easy-peasy.
with(C.getContext`2d`){e=2127036416;m=0;for(n=0;n<64;n++)for(h=n-20?`̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ`.charCodeAt(n):57113,e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)}

// 0x80000000 = 2147483648 = 2**31 = 1<<31
// 0x4C11DB7 = 2127036416 = 4057<<19
// 0xffff0000 = 4294901760
with(C.getContext`2d`){e=4057<<19;m=0;for(n=0;n<64;n++)for(h=n-20?`̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ`.charCodeAt(n):57113,e=e&0xffff0000|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)}

// Turns out individual x and y vars were better
with(C.getContext`2d`){e=4057<<19;m=0;for(n=0;n<64;n++)for(h=n-20?`̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ`.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++,fillRect(x&127,y&127,1,1)}

// Reverse loop k
with(C.getContext`2d`){e=4057<<19;m=0;for(n=0;n<64;n++)for(h=n-20?`̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ`.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=32*(64-n);k--;)l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++,fillRect(x&127,y&127,1,1)}

// Reverse loop n (wow!)
// Side effects: string is reversed, 20th character becomes 43rd character, color array is reversed, and we must add 1 to n when used in the k loop
with(C.getContext`2d`){e=4057<<19;m=0;for(n=64;n--;)for(h=n-43?`ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["000","A55A00","E99E45","FFE289"][n&3],k=32*-~n;k--;)l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++,fillRect(x&127,y&127,1,1)}

// Everything in the for loop to eliminate "with" brackets
with(C.getContext`2d`)for(e=4057<<19,m=0,n=64;n--;)for(h=n-43?`ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["000","A55A00","E99E45","FFE289"][n&3],k=32*-~n;k--;)l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++,fillRect(x&127,y&127,1,1)

// Use third argument of "for"
with(C.getContext`2d`)for(e=4057<<19,m=0,n=64;n--;)for(h=n-43?`ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["000","A55A00","E99E45","FFE289"][n&3],k=32*-~n;k--;fillRect(x&127,y&127,1,1))l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++

// Iterate 65 to 1 instead of 64 to 0; removes need to add 1 with -~ at cost of increasing string length by 1
with(C.getContext`2d`)for(e=4057<<19,m=0,n=65;n--;)for(h=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++

// Rename variables to be more aligned with original names
// s = seed, d = direction, w = word
with(C.getContext`2d`)for(s=4057<<19,d=0,n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s&0xffff0000|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(s^=79764919,d=s&255),j=d&130,i=j%4,2<j?i?x--:y--:i?x++:y++

// s&0xffff0000|w same as s>>16<<16|w (@Arnauld)
with(C.getContext`2d`)for(s=4057<<19,d=0,n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s>>16<<16|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(s^=79764919,d=s&255),j=d&130,i=j%4,2<j?i?x--:y--:i?x++:y++

// d can be initialized to 65 (@Arnauld)
with(C.getContext`2d`)for(s=4057<<19,d=n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s>>16<<16|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(s^=79764919,d=s&255),j=d&130,i=j%4,2<j?i?x--:y--:i?x++:y++

// Much shorter way to calculate direction (@Arnauld)
// j=d&130,i=j%4,2<j?i?x--:y--:i?x++:y++
// d&128?d&2?x--:y--:d&2?x++:y++
with(C.getContext`2d`)for(s=4057<<19,d=n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s>>16<<16|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(s^=79764919,d=s&255),d&128?d&2?x--:y--:d&2?x++:y++

// "&255" of "d=s&255" isn't necessary now (@Arnauld)
// s^=79764919,d=s&255
// d=s^=79764919
with(C.getContext`2d`)for(s=4057<<19,d=n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s>>16<<16|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(d=s^=79764919),d&128?d&2?x--:y--:d&2?x++:y++

// s>>16<<16 same as s&~65535 (@FireFly)
with(C.getContext`2d`)for(s=4057<<19,d=n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(d=s^=79764919),d&128?d&2?x--:y--:d&2?x++:y++

// Even shorter way to calculate direction (@FireFly)
// d&128?d&2?x--:y--:d&2?x++:y++
// D=d&128?-1:1,d&2?x+=D:y+=D
with(C.getContext`2d`)for(s=4057<<19,d=n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(d=s^=79764919),D=d&128?-1:1,d&2?x+=D:y+=D

// Get rid of l (@Arnauld)
// l=s&1<<31,s*=2,l&&
// (s*=2)/2>>31&&
with(C.getContext`2d`)for(s=4057<<19,d=n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))(s*=2)/2>>31&&(d=s^=79764919),D=d&128?-1:1,d&2?x+=D:y+=D

// "&255" isn't necessary y=w>>8&255 (@Arnauld)
with(C.getContext`2d`)for(s=4057<<19,d=n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))(s*=2)/2>>31&&(d=s^=79764919),D=d&128?-1:1,d&2?x+=D:y+=D

// x and y are constrained within 255 only upon direction change, making the drawing invalid; constraining every time fixes it. (@Arnauld)
// x+=D:y+=D
// fillRect(x&127,y&127,1,1)
// x=x+D&127:y=y+D&127
// fillRect(x,y,1,1)
with(C.getContext`2d`)for(s=4057<<19,d=n=65;n--;)for(w=n-44?` ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊`.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x,y,1,1))(s*=2)/2>>31&&(d=s^=79764919),D=d&128?-1:1,d&2?x=x+D&127:y=y+D&127

\$\endgroup\$
  • 3
    \$\begingroup\$ Nice job and thanks for sharing the history! \$\endgroup\$ – Arnauld Jun 16 '17 at 14:49
  • \$\begingroup\$ @Arnauld Glad to take the challenge! \$\endgroup\$ – darrylyeo Jun 16 '17 at 15:56
9
\$\begingroup\$

Befunge, 1131 1052 bytes

"Dq~"1+00g"Ot"0"-R"0003"7/"727*"E1"5*\2*39*27*"\1"3*\2*:8-"ph"2*2\"N"2*"  =&~a"v
v  *83+"k~>"*524\*2"XS)"*2"E"-1:*2"YT"*2"j0"\+94*3"G}"+"%~)"8*2\+"%~E"-7:+" w"+<
>"V\"2*\2*"@"2*"R/"3*">~/"+56*"Y"2*"##`"2*\5*"1K"2*"%O"2*",+!_"2*25*\"{ "+"+<{"v
v"/~Y"+"y~G"+"%~"*5"1"*55*2"k"+98+9:*3"1"*2\*3";i"*2\+"7~@Z>x"*3"?"+92+" q"+" "<
>+",~"2*"}zQ1+BK"2*45*\45*",~s"+\25*9+9"~="+29+2*"wq"2*"r~I"+"@<c#"5*\45*"=o "+v
  v_,#!>#:<"P3 128 96 127"_v`+" k":p39+1:%*:*82<<0<<<\*5"%9D7"+")~"*2"g."+" }{"<
#@_:63p"@d~"03p2*13p043p0v^_:"@"%\"@"/p93g28*:*+^>\04>1-:93p3g2*+:v>g+\%:v>:"_"`
_3*55+,:2g.:1+2g.2+2g.1+v_:48**\1-:83p\83g:1g:23p\0v |:g39`\0p3g39<3v4\+4<^+1$$<
`v0:\%4g++77/"@"\%"@":::<^!:$$_\73g>0#p0#33g#:`#g^#< _$!#v_28*:*::0^>/2%8*-03p:v
">\:88vv%"@":\g38:\<_\73p\1-:!^v4:%\+g32::p31-*2+%2\*"@"% 4/"@":\++"C~":%\+g31:<
~v<\%*<>\"@"/77++p\0^!-g36:%**<>5*9++\:4/8%4*\2%+2*-23p:3 3g+\%:"="3*+\033g`28*v
">88*/7v>g!+53g2-!-153g2%+28*8^v2`\0\%2/2+*:*82:g34+*:*82<p34p33:-*2++%8\*+88< 8
^-1p++7<^35+*:*28\%**8*28-%2g35>#<*#2+#-:#!5#-3#3p#g1#3-#5!#+< >8+#:/#\4#*%#*^#<

There are a number of issues that make this a challenging problem in Befunge:

  1. Befunge has only got 2000 bytes of memory to work with (and that includes the source code), so there is no way we can render the entire image into memory before outputting it. The way I work around this is by repeatedly running the algorithm 96 times, once for each line. Each run stores just the pixels that are needed for the current line, which are then output at the end of the run. This allows us to get by with a pixel buffer of just 128 bytes.

  2. Befunge has no bit operations whatsoever. Many of the AND operations can simply be emulated with a modulo operator (e.g. a AND 0x7F can be replaced with a % 0x80). However, the XOR requires some rather complicated bit manipulation, which we have to deal with one byte at a time, using a set of custom formulas hardcoded to handle the four bytes we need. For example, to calculate a XOR 0xC1, we use the formula: a + 0xC1 - (a/64%4*64 + a%2)*2

  3. While not a limitation of Befunge per se, the interface on TIO is incapable of handling extended ASCII characters in the source, which would have been the easiest way to store the brush and colour tables. I work around this by generating those tables as a list of numbers on the stack, then have a little initialisation loop that copies the values from the stack to memory. A significant chunk of my time was spent golfing this table, which takes up the first five and half lines of code.

Unfortunately, despite all my effort to make the code compatible with TIO, and my choice of a file format that could be extracted from TIO (PPM), it's just too slow to complete within the 60 second time limit (running the algorithm 96 times probably doesn't help). But since it generates the image line by line, you should still get enough of the output to recover nearly half the image.

Try it online!

If you don't have a local PPM file viewer, you can easily convert to another format using one of the many online converters. One example being Convertio.

\$\endgroup\$
  • \$\begingroup\$ Probably not the easiest tool for the job. Well done! \$\endgroup\$ – Arnauld Dec 25 '17 at 11:56
7
\$\begingroup\$

Python 3, 544 536 523 519 518 bytes

from tkinter import*
s=32456<<16
d=0
b="#000"
a=Canvas(Tk(),w=128,he=96,bg=b)
a.pack()
for p in range(64):w=ord("̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖\udf19韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ"[p]);s=s&~65535|w;*e,=divmod(w,256)[::-1];exec("c=s&8<<28>0;s=s*2^79764919*c;d=[d,s&255][c];e[d&2<1]=e[d&2<1]+(d&128<1)*2-1&127;a.create_line(*e,e[0]+1,e[1]+1,f=['#FFE289','#E99E45','#A55A00',b][p&3]);"*(64-p)*32)

This is a further golfed-down version of CCB60's Python translation of the reference implementation. I originally used a large hex number to represent the brush of the algorithm, but I later realized that my unfounded assumption that a Unicode string representation wouldn't work in Python was false.

I originally thought my byte count was significantly lower, but as ASCII-only pointed out, I didn't remember to count the Unicode characters as more than one byte.

Output (128 x 96)

Mona Lisa in tk window

Identical to CCB60's output.

\$\endgroup\$
  • \$\begingroup\$ This is 518 bytes, not 396 \$\endgroup\$ – ASCII-only Jun 20 '17 at 2:17
  • \$\begingroup\$ @ASCII-only I forgot to count the Unicode characters as more than one byte. Oof. No wonder the byte count seemed so low... \$\endgroup\$ – notjagan Jun 20 '17 at 2:43
7
\$\begingroup\$

Java 7, 681 677 675 626 612 610 bytes

Object l(){BufferedImage g=new BufferedImage(128,96,1);String b="̊㞾⾛
ܫ\u0E3C\uF59B誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖\udf19韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ
㺻\uE916ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝\u312E雎▧鸷ⱄ\u2BB9ℹ";for(int 
s=0x7EC80000,d=0,x,y,z=130,u,w,c,r=255,t=127,p=0,o;p<64;p++)
{w=b.charAt(p);s=s&0xFFFF0000|w;x=w&r;y=(w>>8)&r;for(o=0;o<(64-p)*32;o++)
{c=s&0x80000000;s<<=1;if(c!=0){s^=0x4C11DB7;d=s&r;}x=(u=d&z)==2?x+1&t:u==z?
x-1&t:x;y=u==0?y+1&t:u==128?y-1&t:y;if(x<128&y<96)g.setRGB(x,y,new int[]
{0xFFE289,0xE99E45,0xA55A00,0}[p&3]);}}return g;}

Outputs the following image in resolution 128x96:
enter image description here

I know it is not even near 250 bytes but hey it's java

-2 bytes thanks to Zacharý

\$\endgroup\$
  • \$\begingroup\$ Well hey, it appears that no-one has welcomed you to PPCG, so hi, and welcome to PPCG! Nice post, I only have two formatting recommendations for you 1, the header is, for the sake of having leaderboards supposed to be of the format #Language, <s>Old Scores</s> Score Bytes and 2 you can make your code a bit more readable by adding in a language flag of the form <!-- language-all: lang-java --> before your code block \$\endgroup\$ – Taylor Scott Jun 18 '17 at 15:14
  • 1
    \$\begingroup\$ Hey thank you for welcoming me :)! I've now edited my post with the improvements you proposed. \$\endgroup\$ – Twometer Jun 18 '17 at 15:17
  • 2
    \$\begingroup\$ No problem @Twometer,it looks great and hope you enjoy your golfing \$\endgroup\$ – Taylor Scott Jun 18 '17 at 15:18
  • 1
    \$\begingroup\$ Two bytes can be shaved: 0x04C11DB7 => 0x4C11DB7 and 0x7f => 127. Don't go hex crazy when it's not needed. \$\endgroup\$ – Zacharý Jul 18 '17 at 13:02
  • 1
    \$\begingroup\$ I love that “but hey it’s Java” \$\endgroup\$ – Jack Sep 15 '17 at 18:35
4
\$\begingroup\$

C#, 960 850 bytes

using System.Drawing;_=>{var m = new Bitmap(128,96);Graphics.FromImage(m).FillRectangle(Brushes.Black,0,0,128,96);for(int s=0x7EC80000,d=0,p=0,w,x,y,l,c,t,n=127;p<64;++p){w=new[]{778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505}[p];s=s>>16<<16|w;x=w&255;y=w>>8&255;for(l=0;l++<(64-p)*32;){c=(int)(s&0x80000000);s*=2;if(c!=0){s^=79764919;d=s&255;}t=d&130;x=t==2?(x+1)&n:t==130?(x-1)&n:x;y=t<1?(y+1)&n:t==128?(y-1)&n:y;if(x<=n&y<96)m.SetPixel(x,y,Color.FromArgb((int)new[]{0xFFFFE289,0xFFE99E45,0xFFA55A00,0xFF000000}[p&3]));}}return m;}

A straight forward copy of the pseudo code with some golfing added in. There is still a lot that can be golfed but I wanted to post my answer to get the ball rolling.

Full/Formatted version:

using System.Drawing;

class P
{
    static void Main()
    {
        System.Func<object, Bitmap> f = _ =>
        {
            var m = new Bitmap(128, 96);
            Graphics.FromImage(m).FillRectangle(Brushes.Black, 0, 0, 128, 96);

            for (int s = 0x7EC80000, d = 0, p = 0, w, x, y, l, c, t, n = 127; p < 64; ++p)
            {
                w = new[] { 778, 14270, 12187, 1835, 3644, 62875, 35473, 6923, 3773, 37752, 47166, 45146, 28853, 640, 53425, 40146, 8339, 8348, 15633, 9942, 57113, 38901, 37027, 41799, 35575, 2137, 10669, 41772, 32252, 3453, 54650, 12369, 54321, 21547, 45634, 45332, 35478, 10516, 45297, 21292, 1043, 2569, 16059, 59670, 6263, 47330, 44146, 32967, 21056, 36156, 16047, 44387, 7700, 45629, 9103, 49275, 44957, 12590, 38606, 9639, 40503, 11332, 11193, 8505 }[p];
                s = s >> 16 << 16 | w;
                x = w & 255;
                y = w >> 8 & 255;

                for (l = 0; l++ < (64 - p) * 32;)
                {
                    c = (int)(s & 0x80000000);
                    s *= 2;

                    if (c != 0)
                    {
                        s ^= 79764919;
                        d = s & 255;
                    }

                    t = d & 130;

                    x = t == 2 ? (x + 1) & n : t == 130 ? (x - 1) & n : x;
                    y = t < 1 ? (y + 1) & n : t == 128 ? (y - 1) & n : y;

                    if (x <= n & y < 96)
                        m.SetPixel(x, y, Color.FromArgb((int)new[] { 0xFFFFE289, 0xFFE99E45, 0xFFA55A00, 0xFF000000 }[p & 3]));
                }
            }

            return m;
        };

        f(null).Save("monaLisa.jpg");
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ var m = new Bitmap(128,96) AE IU WAUGH WY \$\endgroup\$ – CalculatorFeline Jun 18 '17 at 2:59
  • 2
    \$\begingroup\$ @CalculatorFeline I don't understand? \$\endgroup\$ – TheLethalCoder Jun 18 '17 at 14:38
  • 8
    \$\begingroup\$ Possible because of the unneeded spaces? \$\endgroup\$ – Zacharý Jun 18 '17 at 19:30
3
\$\begingroup\$

Python 2.7; 880 876 bytes total (including data)

-4 bytes to 876 thanks to ZacharyT. (My python interpreter did not like his suggestion to drop the spaces between the 80s and else).

Taylor Scott's suggestion to put the brush into Base 10 is excellent, but notjagan (in a comment) took his suggestion one step further, using python's extended integer format in hex. notjagan's answer is in Python 3, and is such an improvement from what I did that he deserves credit. I hope he'll post it as a separate answer.

Output into a Tkinter window. Without scaling, the image is very small, but scaling adds about a dozen bytes to the count.

B=[0x030A,0x37BE,0x2F9B,0x072B,0x0E3C,0xF59B,0x8A91,0x1B0B,
0x0EBD,0x9378,0xB83E,0xB05A,0x70B5,0x0280,0xD0B1,0x9CD2,
0x2093,0x209C,0x3D11,0x26D6,0xDF19,0x97F5,0x90A3,0xA347,
0x8AF7,0x0859,0x29AD,0xA32C,0x7DFC,0x0D7D,0xD57A,0x3051,
0xD431,0x542B,0xB242,0xB114,0x8A96,0x2914,0xB0F1,0x532C,
0x0413,0x0A09,0x3EBB,0xE916,0x1877,0xB8E2,0xAC72,0x80C7,
0x5240,0x8D3C,0x3EAF,0xAD63,0x1E14,0xB23D,0x238F,0xC07B,
0xAF9D,0x312E,0x96CE,0x25A7,0x9E37,0x2C44,0x2BB9,0x2139]
s=0x7EC80000
d=0x00
from Tkinter import *
m=Tk()
a=Canvas(m,w=128,he=96,bg='black')
a.pack()
for p in range(64):
 w=B[p];s=(s&0xFFFF0000)|w;x=w%256;y=w/256
 for t in range((64-p)*32):
  c=s&0x80000000;s=(s<<1)&0xFFFFFFFF;
  if c:s=s^0x04C11DB7;d=s&0xFF
  if d&2:x=(x+(-1if d&0x80 else 1))&0x7f
  else:y=(y+(-1if d&0x80 else 1))&0x7f
  a.create_line(x,y,x+1,y+1,f=['#FFE289','#E99E45','#A55A00','#000000'][p&3])
mainloop()

There's not much going on here except translation into Python and some basic golfing. Sometimes bit-wise manipulations are shorter, sometimes integer math. I could not find a way to pack more of the logic into lists or arrays. The basic algorithm is already pretty dense.

Mona Lisa as Tkinter output

\$\endgroup\$
  • 1
    \$\begingroup\$ Just a formatting tip, you can make your code be a bit more readable by adding language specific highlighting using prettify.js . For python this flag, which should be added before you code block(s), looks like <!-- language-all: lang-py --> \$\endgroup\$ – Taylor Scott Jun 18 '17 at 15:16
  • 2
    \$\begingroup\$ You don't need the space between the 80's and the else's. And, 0x00 is the same as 0, right? \$\endgroup\$ – Zacharý Jun 18 '17 at 19:26
  • 2
    \$\begingroup\$ And you can remove the space between import and *. \$\endgroup\$ – Zacharý Jun 18 '17 at 19:30
  • 1
    \$\begingroup\$ Got it down to 641 bytes by switching to Python 3 and making some general golfing improvements. \$\endgroup\$ – notjagan Jun 18 '17 at 21:57
  • 1
    \$\begingroup\$ Shaved off one more byte to 640. \$\endgroup\$ – notjagan Jun 18 '17 at 22:04
2
\$\begingroup\$

Tcl/Tk, 805

808 815 816 819 826 839 840 843

Mona

Still the loser, but I had to do it! may be I can golf it more later!

Not the loser now!

rename set S
rename expr E
pack [canvas .c -w 130 -he 98 -bg #000]
.c cr i 67 51 -i [S I [image c photo -w 128 -h 96]]
S s 0x7EC80000
S d 0
time {S s [E $s&0xFFFF0000|[S w 0x[lindex {. 30A 37BE 2F9B 72B E3C F59B 8A91 1B0B
EBD 9378 B83E B05A 70B5 280 D0B1 9CD2
2093 209C 3D11 26D6 DF19 97F5 90A3 A347
8AF7 859 29AD A32C 7DFC D7D D57A 3051
D431 542B B242 B114 8A96 2914 B0F1 532C
413 A09 3EBB E916 1877 B8E2 AC72 80C7
5240 8D3C 3EAF AD63 1E14 B23D 238F C07B
AF9D 312E 96CE 25A7 9E37 2C44 2BB9 2139} [incr p]]]]
S x [E $w&255]
S y [E $w>>8]
time {S c [E $s&1<<31]
S s [E $s<<1]
if \$c {S s [E $s^79764919]
S d [E $s&255]}
switch [E $d&130] {0 {S y [E $y+[S h 1&127]]}
2 {S x [E $x+$h]}
128 {S y [E $y-$h]}
130 {S x [E $x-$h]}}
$I p #[lindex {FFE289 E99E45 A55A00 000} [E $p-1&3]] -t $x $y} [E (65-$p)*32]} 64

Tcl/Tk, 1370

Very ungolfed transliteration of the Pseudo-code before the golfing spree began! The update line makes possible to view the drawing being done progressively!

pack [canvas .c -w 130 -he 98 -bg #000]
.c create i 67 51 -i [set p [image create photo -w 128 -h 96]]

set COLOR {FFE289 E99E45 A55A00 000000}

set BRUSH {
 0x030A 0x37BE 0x2F9B 0x072B 0x0E3C 0xF59B 0x8A91 0x1B0B 
 0x0EBD 0x9378 0xB83E 0xB05A 0x70B5 0x0280 0xD0B1 0x9CD2 
 0x2093 0x209C 0x3D11 0x26D6 0xDF19 0x97F5 0x90A3 0xA347 
 0x8AF7 0x0859 0x29AD 0xA32C 0x7DFC 0x0D7D 0xD57A 0x3051 
 0xD431 0x542B 0xB242 0xB114 0x8A96 0x2914 0xB0F1 0x532C 
 0x0413 0x0A09 0x3EBB 0xE916 0x1877 0xB8E2 0xAC72 0x80C7 
 0x5240 0x8D3C 0x3EAF 0xAD63 0x1E14 0xB23D 0x238F 0xC07B 
 0xAF9D 0x312E 0x96CE 0x25A7 0x9E37 0x2C44 0x2BB9 0x2139}

set seed 0x7EC80000
set dir 0x00

set part 0
while {$part<64} {
  set word [lindex $BRUSH $part]
  set seed [expr ($seed&0xFFFF0000)|$word]
  set bx [expr $word&0xFF]
  set by [expr $word>>8]

  set len 0
  while {$len<[expr (64-$part)*32]} {
    set carry [expr $seed&0x80000000]
    set seed [expr $seed<<1]

    if \$carry {
      set seed [expr $seed^0x04C11DB7]
      set dir [expr $seed&0xFF]
    }

    switch [expr $dir&0x82] {
      0 {
        set by [expr $by+1&0x7F]
      }
      2 {
        set bx [expr $bx+1&0x7F]
      }
      128 {
        set by [expr $by-1&0x7F]
      }
      130 {
        set bx [expr $bx-1&0x7F]
      }
    }

    $p put #[lindex $COLOR [expr $part&3]] -to $bx $by
    incr len
    update
  }
  incr part
}
\$\endgroup\$
2
\$\begingroup\$

Python 3 + matplotlib, 541

from pylab import*
B='ਃ븷鬯⬇㰎鯵醊ଛ봎碓㺸媰땰耂뇐튜錠鰠ᄽ혦᧟ꎐ䞣夈괩ⲣﱽ納竕儰㇔⭔䊲ᒱ隊ᐩⱓጄऊ묾ᛩ眘犬잀䁒㲍꼾掭ᐞ㶲輣節鶯⸱캖ꜥ㞞䐬뤫㤡'
s=32456<<16
d=0
i=zeros((256,256),'I')
for p in range(64):
    W=ord(B[p]);w=W>>8|W%256<<8;s=s&65535<<16|w;x=[w>>8,w&255]
    for l in range((64-p)*32):
        s*=2
        if s>>32:s=d=s^4374732215
        a=(-1)**(d>>7);b=d>>1&1;x[b]=x[b]+a&127;i[(*x,)]=[9036543,4562665,23205,0][p&3]
imsave('i',i.view('4B')[:96,:128,:3])

This saves the image as a png file "i". To display the image you can replace the imsave with an imshow and a show for 545 bytes.

enter image description here

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

SmileBASIC, 454 447 444 bytes

DIM C[5]C[1]=-7543C[2]=-1466811C[3]=-5940736S=32456<<16FOR P=-63TO.W=ASC("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"[-P])S=W+(S>>16<<16)C[4]=127AND W
C[0]=W>>8FOR L=0TO 31-P*32O=S
S=S<<1IF O<0THEN S=79764919XOR S:D=130AND S
T=D*2AND 4C[T]=127AND C[T]-(D>>6)+1GPSET C[4],C[0]+144,C[3AND P]NEXT
NEXT

The string of "x"s had some invalid unicode characters, so I'm not able to post it here. Here are the character codes in decimal (just the BRUSH array in reverse): 8505, 11193, 11332, 40503, 9639, 38606, 12590, 44957, 49275, 9103, 45629, 7700, 44387, 16047, 36156, 21056, 32967, 44146, 47330, 6263, 59670, 16059, 2569, 1043, 21292, 45297, 10516, 35478, 45332, 45634, 21547, 54321, 12369, 54650, 3453, 32252, 41772, 10669, 2137, 35575, 41799, 37027, 38901, 57113, 9942, 15633, 8348, 8339, 40146, 53425, 640, 28853, 45146, 47166, 37752, 3773, 6923, 35473, 62875, 3644, 1835, 12187, 14270, 778

enter image description here

\$\endgroup\$
  • \$\begingroup\$ You posted an image of the output, would it be possible to post an image of the contents of the "xx...xx" string? \$\endgroup\$ – Taylor Scott Mar 16 '18 at 3:41
  • 1
    \$\begingroup\$ Most of the characters don't actually have symbols defined for them, so it really does look like "xxxxxxxxxxx". I can get a list of the character codes though. \$\endgroup\$ – 12Me21 Mar 16 '18 at 15:19
  • \$\begingroup\$ That actually might be helpful - I think I may be able to use a similar method with yabasic - oh, you already did it - coolio \$\endgroup\$ – Taylor Scott Mar 16 '18 at 17:07
  • \$\begingroup\$ It's not very space efficient since (at least in UTF-8) most of those are saved as 3 or more bytes. But it's still better than hex and you might be able to shorten the decoder too. \$\endgroup\$ – 12Me21 Mar 16 '18 at 17:19
1
\$\begingroup\$

:r4, 764 bytes

the source for run in :r4 github

enter image description here

^r4/lib/gui.txt
#c $FFE289 $E99E45 $A55A00 $000000
#b $37BE030A $072B2F9B $F59B0E3C $1B0B8A91 $93780EBD $B05AB83E $028070B5 $9CD2D0B1 $209C2093 $26D63D11 $97F5DF19 $A34790A3 $08598AF7 $A32C29AD $0D7D7DFC $3051D57A $542BD431 $B114B242 $29148A96 $532CB0F1 $0A090413 $E9163EBB $B8E21877 $80C7AC72 $8D3C5240 $AD633EAF $B23D1E14 $C07B238F $312EAF9D $25A796CE $2C449E37 $21392BB9
:m pick2 + $7f7f and dup $7f and over 8 >> 96 >? ( 2drop ; ) setxy ink@ a! ;
:s +? ( 2* ; ) 2* $4c11db7 xor rot drop dup 24 << 31 >> 1 or over $2 and 2 << 8 xor << rot rot ;
:d $100 $7ec80000 0 ( 64 <? )( dup $3 and 2 << 'c + @ ink dup >r 2* 'b + w@ $ffff and swap $ffff0000 and over or 64 r@ - 5 << ( 1? )( >r s swap m swap r> 1- ) drop nip r> 1+ ) 3drop ;
: cls d show 'exit >esc< ;

I use a trick for make the move without conditionals, transform bit 8 in sign and shift with bit 2. version with stack names:

| PHREDA 2017
| https://codegolf.stackexchange.com/questions/126738/lets-draw-mona-lisa
^r4/lib/gui.txt

#color  $FFE289 $E99E45 $A55A00 $000000
#brush [
$030A $37BE $2F9B $072B $0E3C $F59B $8A91 $1B0B
$0EBD $9378 $B83E $B05A $70B5 $0280 $D0B1 $9CD2
$2093 $209C $3D11 $26D6 $DF19 $97F5 $90A3 $A347
$8AF7 $0859 $29AD $A32C $7DFC $0D7D $D57A $3051
$D431 $542B $B242 $B114 $8A96 $2914 $B0F1 $532C
$0413 $0A09 $3EBB $E916 $1877 $B8E2 $AC72 $80C7
$5240 $8D3C $3EAF $AD63 $1E14 $B23D $238F $C07B
$AF9D $312E $96CE $25A7 $9E37 $2C44 $2BB9 $2139 ]

:movxy | dir seed bxy -- dir seed bxy 
  pick2 + $7f7f and
  dup $7f and
  over 8 >>
  96 >? ( 2drop ; )
  setxy ink@ a! ;

:step | dir bxy seed -- dir bxy seed
  +? ( 2* ; )
  2* $4c11db7 xor
  rot drop
  dup 24 << 31 >> 1 or
  over $2 and 2 << 8 xor <<
  rot rot ;

:draw
  $100      | dir
  $7ec80000 | seed
  0 ( 64 <? )(
    dup $3 and 2 << 'color + @ ink
    dup >r 2* 'brush + w@ $ffff and | dir seed brush
    swap $ffff0000 and over or      | dir bxy seed
    64 r@ - 5 << ( 1? )( >r         | dir bxy seed
        step swap movxy swap r> 1- ) drop nip
    r> 1+ ) 3drop ;

: cls draw show 'exit >esc< ;
\$\endgroup\$
1
\$\begingroup\$

Yabasic, 790 779 bytes

An answer that takes no input and outputs to a new graphics window.

Open Window 128,96
j=127
s=4057*2^19
k=255
For p=-1To 63
Color Mid$("255,226,137233,158,069165,090,0000,0,0",1+And(3,p)*11,11)
If p<0Then Fill Circle 0,0,k:p=0Fi
w=Dec(Mid$("30A37BE2F9B072B0E3CF59B8A911B0B0EBD9378B83EB05A70B50280D0B19CD22093209C3D1126D6DF1997F590A3A3478AF7085929ADA32C7DFC0D7DD57A3051D431542BB242B1148A962914B0F1532C04130A093EBBE9161877B8E2AC7280C752408D3C3EAFAD631E14B23D238FC07BAF9D312E96CE25A79E372C442BB92139",4*p,4),16)
s=Or(And(-4^8,s),w)
x=And(k,w)
y=And(w/2^8,k)
For l=1To(64-p)*32
c=And(-2^31,s)
z=And(2^30,s)
s=And(1073741823,s)*2
t=s
If z Then t=Or(s,-2^31)Fi
s=And(-1,t)
If c Then s=Xor(79764919,s):d=And(k,s)Fi
d=And(130,d)
If d=0Then y=And(y+1,j)Fi
If d=2Then x=And(x+1,j)Fi
If d=128Then y=And(y-1,j)Fi
If d=130Then x=And(x-1,j)Fi
Dot x,y
Next
Next

Output

The below is scaled by a factor of 8

Mona.yab

\$\endgroup\$

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.