108
\$\begingroup\$

I always used aMandelbrot image as the 'graphical' version of Hello World in any graphical application I got my hands on. Now it's your guys' turn.

  • Language must be capable of graphical output or drawing charts (saving image files disallowed)
  • Render a square image or graph. The size at least 128 and at most 640 across*
  • The fractal coordinates range from approximately -2-2i to 2+2i
  • The pixels outside of the Mandelbrot set should be colored according to the number of iterations before the magnitude exceeds 2 (excluding* black & white)
  • Each iteration count must have a unique color*, and neighboring colors should preferably be easily distinguishable by the eye
  • The other pixels (presumably inside the Mandelbrot set) must be colored either black or white
  • At least 99 iterations
  • ASCII art not allowed

* unless limited by the platform,e.g. graphical calculator

Allowed:
Allowed
Disallowed:
Disallowed
(shrunken images)

Winning conditions:

Shortest version (size in bytes) for each language will get a mention in this post, ordered by size.
No answer will ever be 'accepted' with the button.

Leaderboard:

/* Configuration */var QUESTION_ID = 23423; // Obtain this from the url// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question pagevar ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";var OVERRIDE_USER = 17419; // This should be the user ID of the challenge author./* App */var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;function answersUrl(index) {  return "https://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;}function commentUrl(index, answers) {  return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;}function getAnswers() {  jQuery.ajax({    url: answersUrl(answer_page++),    method: "get",    dataType: "jsonp",    crossDomain: true,    success: function (data) {      answers.push.apply(answers, data.items);      answers_hash = [];      answer_ids = [];      data.items.forEach(function(a) {        a.comments = [];        var id = +a.share_link.match(/\d+/);        answer_ids.push(id);        answers_hash[id] = a;      });      if (!data.has_more) more_answers = false;      comment_page = 1;      getComments();    }  });}function getComments() {  jQuery.ajax({    url: commentUrl(comment_page++, answer_ids),    method: "get",    dataType: "jsonp",    crossDomain: true,    success: function (data) {      data.items.forEach(function(c) {        if (c.owner.user_id === OVERRIDE_USER)          answers_hash[c.post_id].comments.push(c);      });      if (data.has_more) getComments();      else if (more_answers) getAnswers();      else process();    }  });  }getAnswers();var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;var OVERRIDE_REG = /^Override\s*header:\s*/i;function getAuthorName(a) {  return a.owner.display_name;}function process() {  var valid = [];    answers.forEach(function(a) {    var body = a.body;    a.comments.forEach(function(c) {      if(OVERRIDE_REG.test(c.body))        body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';    });        var match = body.match(SCORE_REG);    if (match)      valid.push({        user: getAuthorName(a),        size: +match[2],        language: match[1],        link: a.share_link,      });    else console.log(body);  });    valid.sort(function (a, b) {    var aB = a.size,        bB = b.size;    return aB - bB  });  var languages = {};  var place = 1;  var lastSize = null;  var lastPlace = 1;  valid.forEach(function (a) {    if (a.size != lastSize)      lastPlace = place;    lastSize = a.size;    ++place;        var answer = jQuery("#answer-template").html();    answer = answer.replace("{{PLACE}}", lastPlace + ".")                   .replace("{{NAME}}", a.user)                   .replace("{{LANGUAGE}}", a.language)                   .replace("{{SIZE}}", a.size)                   .replace("{{LINK}}", a.link);    answer = jQuery(answer);    jQuery("#answers").append(answer);    var lang = a.language;    lang = jQuery('<a>'+lang+'</a>').text();        languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang, user: a.user, size: a.size, link: a.link};  });  var langs = [];  for (var lang in languages)    if (languages.hasOwnProperty(lang))      langs.push(languages[lang]);  langs.sort(function (a, b) {    if (a.lang_raw.toLowerCase() > b.lang_raw.toLowerCase()) return 1;    if (a.lang_raw.toLowerCase() < b.lang_raw.toLowerCase()) return -1;    return 0;  });  for (var i = 0; i < langs.length; ++i)  {    var language = jQuery("#language-template").html();    var lang = langs[i];    language = language.replace("{{LANGUAGE}}", lang.lang)                       .replace("{{NAME}}", lang.user)                       .replace("{{SIZE}}", lang.size)                       .replace("{{LINK}}", lang.link);    language = jQuery(language);    jQuery("#languages").append(language);  }}
body {  text-align: left !important;  display: block !important;}#answer-list {  padding: 10px;  width: 290px;  float: left;}#language-list {  padding: 10px;  width: 290px;  float: left;}table thead {  font-weight: bold;}table td {  padding: 5px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Sites/codegolf/all.css?v=ffb5d0584c5f"><div>  <h2>Shortest Solution by Language</h2>  <table>    <thead>      <tr><td>Language</td><td>User</td><td>Score</td></tr>    </thead>    <tbody>    </tbody>  </table></div><div>  <h2>Leaderboard</h2>  <table>    <thead>      <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>    </thead>    <tbody>    </tbody>  </table></div><table>  <tbody>    <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>  </tbody></table><table>  <tbody>    <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>  </tbody></table>

askedMar 7, 2014 at 21:39
Mark Jeronimus's user avatar
\$\endgroup\$
14
  • 9
    \$\begingroup\$"Easily distinguished by the eye" is hard to make objective. ...Also, apart from your personal association of the two, the Mandelbrot set has nothing to do with Hello World, so it's best to omit that from the title unless you are deliberately trolling the search engines.\$\endgroup\$CommentedMar 7, 2014 at 21:50
  • 4
    \$\begingroup\$I've seen a few people now mentioning that they render the Mandelbrot as a "Hello World". I've done that too, for something like 30 years. The Mandelbrot is the perfect "Hello World" because it shows both that you have pixel access to the display and gives a good feel for compute bound performance on the new platform.\$\endgroup\$CommentedMar 9, 2014 at 2:00
  • 7
    \$\begingroup\$Great idea to ask a question which requires a combination of mathematical and aesthetic sensitivities, then impose all the the design decisions in advance.\$\endgroup\$CommentedMar 10, 2014 at 8:25
  • 3
    \$\begingroup\$Anyone manages to make one in brainfuck WINS, I'd say :D\$\endgroup\$CommentedMar 10, 2014 at 18:45
  • 3
    \$\begingroup\$Not mine and not golfed, butthis code is a marvel of obfuscated python producing a mandelbrot fractal\$\endgroup\$CommentedMay 26, 2017 at 8:37

45 Answers45

4
\$\begingroup\$

JavaScript + HTML5 (356B)

(Note: lines ending with '//' are added here for some readability)

Performant version (375B):

<body onload='varw,h=w=C.width=C.height=500,X=C.getContext("2d"),I=X.createImageData(w,h),D=I.data, //y=0,f=255,T=setInterval(function(x,i,j,k,l,c,o){for(x=0;x<w;){                     //for(i=x*4/w-2,j=y*4/h-2,k=l=0,c=f;--c&&k*k+l*l<4;)t=k*k-l*l+i,l=2*k*l+j,k=tD[o=(y*w+x++)*4]=(c*=0xc0ffeeee)&fD[++o]=c>>8&fD[++o]=c>>16&fD[++o]=f}X.putImageData(I,0,0)++y-h||clearInterval(T)},0)'><canvas id=C>

Slow version (356B): remove the 'var' and parameters in the inner function so that the global scope is used.

Try it out:http://jsfiddle.net/neuroburn/Bc8Rh/

enter image description here

answeredMar 8, 2014 at 21:22
ɲeuroburɳ's user avatar
\$\endgroup\$
2
  • \$\begingroup\$Forgive me if I don't understand your instructions on making the short version.\$\endgroup\$CommentedMar 8, 2014 at 21:33
  • \$\begingroup\$No problem. Removevar w, at the beginning, and changefunction(x,i,j,k,l,c,o) tofunction().\$\endgroup\$CommentedMar 8, 2014 at 21:35
4
\$\begingroup\$

Matlab (89 bytes)

[X,Y]=ndgrid(-2:.01:2);C=X+i*Y;Z=C-C;K=Z;for j=1:99,Z=Z.*Z+C;K=K+(abs(Z)<2);end,imagesc(K)

Output -

enter image description here

Doesn't satisfy the requirement that the inner cells must be black orwhite, but that can be satisfied by either (1) usingimshow(K) insteadofimagesc(K) (requires 1 fewer byte but needs the image processingtoolbox) or (2) appendingcolormap hot (requires 12 more bytes).

Ungolfed version -

Z = zeros(N);K = Z;[X,Y]=ndgrid(-2:.01:2);C = X+1i*Y;for j = 1:99  Z = Z.*Z + C;  K(K==0 & abs(Z) > 2) = j;endimagesc(K)
answeredMar 10, 2014 at 10:57
Chris Taylor's user avatar
\$\endgroup\$
7
  • \$\begingroup\$Using a library is fine if it's packaged in Matlab by default and any user can guess it's being used from the code or the error messages.\$\endgroup\$CommentedMar 10, 2014 at 19:19
  • \$\begingroup\$Nice, you beat me. I like theC-C in place of my0*e(401). Plus, you're not usingN. And we can get a little shorter using mym+=abs(z)<2 idea in place of yourK(~K&abs(Z)>2)=j.\$\endgroup\$CommentedMar 11, 2014 at 12:33
  • \$\begingroup\$The defaultcolormap jet andcolormap hot are both incorrect though - they only have 64 distinct colors.colormap(hot(101)) doesn't look visually distinguishable to me.colormap([0,0,0;jet(100)]) is maybe acceptable but iffy.\$\endgroup\$CommentedMar 11, 2014 at 12:39
  • \$\begingroup\$Does that work? On Octave,K=K+abs(Z)<2 meansK=((K+abs(Z))<2). (So I was wrong about the one byte estimate to eliminate+=.)\$\endgroup\$CommentedMar 11, 2014 at 13:06
  • 2
    \$\begingroup\$The Mandelbrot set rotated by 90 degrees is still the Mandelbrot set.\$\endgroup\$CommentedMar 5, 2015 at 23:19
4
\$\begingroup\$

Javascript, 285B

Based off my code and some improvements onMT0's code, I've got this down to 285B in colour:

document.body.appendChild(V=document.createElement('Canvas'));j=(D=(X=V.getContext('2d')).createImageData(Z=V.width=V.height=255,Z)).data;for(x=Z*Z;x--;){k=a=b=c=0;while(a*a+b*b<4&&Z>k++){c=a*a-b*b+4*(x%Z)/Z-3;b=2*a*b+4*x/(Z*Z)-2;a=c;}j[4*x]=99*k%256;j[4*x+3]=Z;}X.putImageData(D,0,0);

in action:http://jsfiddle.net/acLhe/7/

was: Coffeescript, 342B

document.body.appendChild V=document.createElement 'Canvas'N=99Z=V.width=V.height=400P=[]P.push "rgba(0,0,0,"+Math.random()*i/N+')' for i in [N..0]X=V.getContext '2d'for x in [0..Z] for y in [0..Z]  k=a=b=0  [a,b]=[a*a-b*b+4*x/Z-3,2*a*b+4*y/Z-2] while a*a+b*b<4 and N>k++  X.fillStyle=P[k-1]  X.fillRect x,y,1,1

Coffeescript is supposed to be readable :-/ see it in action:http://jsfiddle.net/acLhe/6/

Mandelbrot Coffeescript

answeredMar 13, 2014 at 16:17
alyx-brett's user avatar
\$\endgroup\$
2
  • \$\begingroup\$OP asks for color unless your platform doesn't support color. Looks great, though, and nice concise code. Welcome to PPCG!\$\endgroup\$CommentedMar 13, 2014 at 16:45
  • \$\begingroup\$I start from this size 285B and improve it more in thisanswer\$\endgroup\$CommentedOct 17, 2019 at 10:04
4
\$\begingroup\$

QBasic, QuickBasic, QB64 -156 153

SCREEN 13FOR J=0TO 191B=J/48-2FOR I=0TO 191A=I/48-2X=AY=BC=0DOU=X*XV=Y*YY=2*X*Y+BX=U-V+AC=C+1LOOP UNTIL C>247OR U+V>4PSET(I,J),CNEXTNEXT

Standard DOS palette:

enter image description here

answeredMar 14, 2014 at 18:29
Mark Jeronimus's user avatar
\$\endgroup\$
1
  • \$\begingroup\$Surprising that in all of 11 years no one noticed the ways in which this can be optimized. (I left inefficiencies in there on purpose)\$\endgroup\$CommentedMar 15 at 11:52
4
\$\begingroup\$

Python 3, 290 Bytes

from PIL import Imageimport numpy as ns=640;d=n.zeros((s,s,3),dtype=n.uint8)for k in range(s*s):    r=4/s*(k%s)-2;i=2-4/s*(k//s);z=c=complex(r,i)    for i in range(50,9950,100):        if abs(z)>2:            d[k//s,k%s]=[i*5,i*9,i*7];break        z=z*z+cImage.fromarray(d).show()

mandelbrot

answeredOct 6, 2019 at 16:38
r3dapple's user avatar
\$\endgroup\$
4
\$\begingroup\$

QBasic, 139 bytes

-1 c/oDLosc

SCREEN 13FOR i=0TO 199FOR j=0TO 199x=0y=0FOR c=0TO 255t=y*yc=c-255*(x*x+t>4)y=2*x*y+j/50-2x=x*x-t+i/50-2NEXTPSET(i,j),cNEXT j,i

Output:

It may be necessary to append aINPUT$(1) to prevent the window from closing until a key is pressed.


FreeBASIC, 139 bytes

UsingFreeBASIC'sSCREEN 16, we can generate a more detailed image at the same code length:

SCREEN 16FOR i=0TO 383FOR j=0TO 383x=0y=0FOR c=0TO 255t=y*yc=c-255*(x*x+t>4)y=2*x*y+j/96-2x=x*x-t+i/96-2NEXTPSET(i,j),cNEXT j,i

Compile asfbc -lang qb mandel.bas.

Higher resolutions are also available.

answeredSep 27, 2017 at 14:09
primo's user avatar
\$\endgroup\$
4
  • \$\begingroup\$Please count newlines as a byte too\$\endgroup\$CommentedSep 27, 2017 at 14:32
  • \$\begingroup\$@MarkJeronimus my mistake, I though I had.\$\endgroup\$CommentedSep 28, 2017 at 4:31
  • \$\begingroup\$Modifyingc to exit theFOR loop is really clever! You can save 2 bytes by usingy*y directly instead of assigning tot, and one more byte by writingNEXT j,i instead ofNEXT twice. (Not sure if that second one works in FreeBASIC.)\$\endgroup\$CommentedJun 3, 2021 at 19:59
  • \$\begingroup\$The assignment tot is necessary, because the old value ofy is used in the computation ofx. Thanks for the multi-NEXT tip ;)\$\endgroup\$CommentedJun 4, 2021 at 11:49
3
\$\begingroup\$

Perl + GD, 264

$I=new GD::Image $s=499,$s;Z(0,0,0);Z(map rand 256,1..3)for0..99;for$x(0..$s){for$y(0..$s){for($H=$K=$c=$t=0;$c++<99&&$H*$H+$K*$K<4;){subZ{$I->colorAllocate(@_)}($H,$K)=($H*$H-$K*$K+4*$x/$s-2,2*$H*$K+4*$y/$s-2)}useGD;$I->setPixel($x,$y,$c<99&&$c)}}print $I->png

Mandelbrot fractal from Perl+GD

Golfed fromthis code

answeredMar 9, 2014 at 5:56
mob's user avatar
\$\endgroup\$
1
  • 2
    \$\begingroup\$Nominated: most ugly color scheme.\$\endgroup\$CommentedMar 9, 2014 at 9:41
3
\$\begingroup\$

SmileBASIC, 126 bytes

X=RNDF()*4-2Y=RNDF()*4-2@NN=N+16I=X+S*S-T*TT=Y+S*T*2S=IIF N<#L&&S*S+T*T<4GOTO@NGPSET X*50+99,Y*50+99,RGB(99XOR N,N,N)EXEC.

enter image description here

answeredFeb 15, 2017 at 18:50
12Me21's user avatar
\$\endgroup\$
3
  • \$\begingroup\$Nice use of randoms to save on loops\$\endgroup\$CommentedFeb 19, 2017 at 9:07
  • \$\begingroup\$Should make it 240x240, but I guess that would be longer.\$\endgroup\$CommentedMar 20, 2017 at 12:28
  • 1
    \$\begingroup\$Code golf is about what you can get away with, not what youshould do.\$\endgroup\$CommentedJun 17, 2017 at 15:28
3
\$\begingroup\$

Tcl/Tk, 316

322324336348349351352353354355

Now a shorter version using 3 letter #RGB shorthands style color triplets (instead of #RRGGBB triplets), which results in different colors.

And some more golfing.

rename set sgrid [canvas .c -w 640 -he 640].c cr i 320 320 -i [s p [image c photo -w 640 -h 640]]time {incr xs y 0time {incr ys a 0s b 0s n 0while \$n<99 {s A [expr $a*$a-$b*$b+$x[s f *4/639.-2]]if [s b [expr 2*$a*$b+$y$f]]*$b+[s a $A]*$a>4 breakincr n}$p p [format #%03x [expr $n*41]] -t $x $y} 640} 640

fractal


Tcl/Tk, 325

331333345357358360361362364365

I think I would win if the criterium was beauty!

rename set sgrid [canvas .c -w 640 -he 640].c cr i 320 320 -i [s p [image c photo -w 640 -h 640]]time {incr xs y 0time {incr ys a 0s b 0s n 0while \$n<99 {s A [expr $a*$a-$b*$b+$x[s f *4/639.-2]]if [s b [expr 2*$a*$b+$y$f]]*$b+[s a $A]*$a>4 breakincr n}$p p [format #%06x [expr $n*16777215/99]] -t $x $y} 640} 640

Presentation:

fractal

answeredMar 19, 2017 at 19:11
sergiol's user avatar
\$\endgroup\$
1
  • 1
    \$\begingroup\$Nice. You can reduce a few characters (down to 380, I think) by addingrename set s at the top and then replacing all theset bys\$\endgroup\$CommentedApr 4, 2017 at 0:00
3
\$\begingroup\$

GLSL, 146 bytes

void mainImage( out vec4 o, vec2 C ) {o -= o; vec2 z;for(;o.z++<99.^^length(z)>2.;)z=mat2(z.rg,-z.g,z)*z+C/99.-2.;o=mod(vec4(o.z)/vec4(4,2,6,0),1.19);}

https://www.shadertoy.com/view/sly3RW

enter image description here

answeredNov 18, 2021 at 11:24
Max's user avatar
\$\endgroup\$
4
  • \$\begingroup\$no unique color for you\$\endgroup\$CommentedNov 18, 2021 at 11:28
  • \$\begingroup\$For some reason I see 95% animated noise and 5% Mandelbrot\$\endgroup\$CommentedNov 18, 2021 at 13:51
  • \$\begingroup\$Changing the final statement too=vec4(mod(o.z/2.,2.),mod(o.z,2.),mod(o.z/4.,2.),0) might make it colorful (my theory at least)\$\endgroup\$CommentedNov 18, 2021 at 13:53
  • \$\begingroup\$You're right :) Thanks, updated it to fit the rules now. But +25 bytes\$\endgroup\$CommentedNov 18, 2021 at 14:10
3
\$\begingroup\$

JavaScript (pixel shader), 88 bytes

m=(x,y,A=0,B=0,n=99)=>n--&&A*A+B*B<4?m(x,y,A*A-B*B+x,2*A*B+y,n):`hsl(${n*7} 99%${n/2}%)`

A pixel shader function that takesx andy between[-2, -2] and[2, 2] and returns CSS<color> (HSL).

mandelbrot

m=(x,y,A=0,B=0,n=99)=>n--&&A*A+B*B<4?m(x,y,A*A-B*B+x,2*A*B+y,n):`hsl(${n*7} 99%${n/2}%)`const size = 512;const scale = 4;const ratio = scale / size;const canvas = document.getElementById('canvas');canvas.width = canvas.height = size;const ctx = canvas.getContext('2d');let x, y;for (x = 0; x < size; x++) for (y = 0; y < size; y++) {  ctx.fillStyle = m((x - size / 2) * ratio, (y - size / 2) * ratio);  ctx.fillRect(x, y, 1, 1);}
<canvas/>

Ungolfed and Explained

m = (  x,    // Re(c)  y,    // Im(c)  A=0,  // Re(z[i])  B=0,  // Im(z[i])  n=99  // 99 - i) =>  n-- && // if haven't reached max depth  A * A + B * B < 4 ? // and |z| < 2    m( // recurse      x,      y,      A * A - B * B + x, // Re(z[i] ^ 2 + c)      2 * A * B + y,     // Im(z[i] ^ 2 + c)      n    ) : // else return HSL colour    `hsl(${n * 7} 99% ${n / 2}%)` // n * 7 always unique in mod 360
answeredApr 21, 2022 at 23:15
Matthew Jensen's user avatar
\$\endgroup\$
3
\$\begingroup\$

AWK, 198 bytes

BEGIN{a=-2;c=d=1;b=-1;w=140;h=40;m=250;x=(c-a)/w;y=(d-b)/h;for(r=0;r<h;r++){for(c=0;c<w;c++){q=a+c*x;s=d-r*y;for(R=I=t=0;R*R+I*I<=5&&t<m;t++){T=R*R-I*I+q;I=2*R*I+s;R=T}printf t==m?"#":" "}print""}}'

To Test:

awk 'BEGIN{a=-2;c=d=1;b=-1;w=140;h=40;m=250;x=(c-a)/w;y=(d-b)/h;for(r=0;r<h;r++){for(c=0;c<w;c++){q=a+c*x;s=d-r*y;for(R=I=t=0;R*R+I*I<=5&&t<m;t++){T=R*R-I*I+q;I=2*R*I+s;R=T}printf t==m?"#":" "}print""}}'

Nice B&W

Color Attempt, 268 bytes

BEGIN{a=-2;c=d=1;b=-1;w=140;h=40;m=250;x=(c-a)/w;y=(d-b)/hsplit("\033[31m \033[33m \033[32m \033[34m \033[35m",C)for(r=0;r<h;r++){for(c=0;c<w;c++){q=a+c*x;s=d-r*yfor(R=I=t=0;R*R+I*I<=5&&t<m;t++){T=R*R-I*I+qI=2*R*I+s;R=T}printf t==m?"#":C[1+int(4*t/m)]" "}print""}}

To test:

awk 'BEGIN{a=-2;c=d=1;b=-1;w=140;h=40;m=250;x=(c-a)/w;y=(d-b)/h;split("\033[31m \033[33m \033[32m \033[34m \033[35m",C);for(r=0;r<h;r++){for(c=0;c<w;c++){q=a+c*x;s=d-r*y;for(R=I=t=0;R*R+I*I<=5&&t<m;t++){T=R*R-I*I+q;I=2*R*I+s;R=T}printf t==m?"#":C[1+int(4*t/m)]" "}print""}}'

Color Test

answeredNov 27, 2024 at 19:41
xrs's user avatar
\$\endgroup\$
2
  • \$\begingroup\$I really like hacker solutions like this. Please provide a full command line and a screenshot of the output.\$\endgroup\$CommentedNov 29, 2024 at 8:58
  • \$\begingroup\$Cheers, didn't realize it was so easy to add photos.\$\endgroup\$CommentedNov 29, 2024 at 15:05
3
\$\begingroup\$

Typst, 210 bytes

(specifically Typst v0.14.0)

#(w=>image(format:(encoding:"rgb8",width:w,height:w),for i in(w=range(w).map(y=>y/w*4-2))+w{for j in w{let(a,b,k)=(0,0,99);while 1>k<(4>a*a+b*b){(a,b)=(-b*b+a*a+j,2*a*b+i);k -=1};(k*k).to-bytes(size:3)}}))(640)

enter image description here

Explanation

First we have some boilerplate to get image output:

#(w=>image(format:(encoding:"rgb8",width:w,height:w), {  ...  } ))(640)

Since we specifyencoding:"rgb8", the positional argument is expected to be abytes object (essentially a tightly-packed array of u8s) of length3*w*w (in the format(r,g,b,r,g,b,r,g,b,...)). Typst automatically joins together the results of consecutive expressions, and, like Rust, considersfor loops,if-else blocks, and the like to be expressions. In particular,bytes objects join together by concatenation, so we can construct abytes object of length (for example) 300 with an expression of the following structure:

for i in range(10){    for j in range(10){        bytes((0,0,0)) //all 100 of these are joined together    }}

We use the same structure in the golf, where the expression within the innerfor loop returns a length-3bytes object (as we will see):

for i in(w=range(w).map(y=>y/w*4-2))+w{for j in w{ {  ...  } }}

In the expression(w=range(w).map(y=>y/w*4-2))+w, the left operandw=range(w).map(y=>y/w*4-2) evaluates first, shadowingw (reusing the same variable name means we don't needlet for this assignment) and evaluating tonone (as all assignments do). The right operand is then evaluated, returning the updated value ofw, and the additionnone + w leaves it unchanged (none can be added to anything without changing it). The code is thus equivalent to if we had just created a new block for the assignment:

{w=range(w).map(y=>y/w*4-2);for i in w{for j in w{ {  ...  } }}}

but our version is one byte shorter for having removed the space betweenin andw.

Inside thefor loops, we have:

let(a,b,k)=(0,0,99);while 1>k<(4>a*a+b*b){(a,b)=(-b*b+a*a+j,2*a*b+i);k -=1};{  ...  }

The expression1>k<(4>a*a+b*b) uses the fact thatbools are comparable (andfalse < true is the only true case) to compute the equivalent ofk>=1 and 4>a*a+b*b. Note that the seemingly obvious byte saves of-b*b+a*a+j ->a*a-b*b+j andk -=1 ->k-=1 are in fact impossible, since Typst permits hyphens in identifier names (including at the end) so will interpreta-b andk- as nonexistent variables.

Finally, we return a length-3bytes object representing the pixel colour, based on the iteration count:

(k*k).to-bytes(size:3)

In other words, we get the three least-significant bytes (sinceto-bytes defaults to little-endian) ofk*k. This achieves a fairly high degree of dispersion (particularly when the iteration count is lower, and hencek is larger) for a low byte count, and keeps the points inside the Mandelbrot set (for whichk is 0) pure black.

Typst, 207 bytes

#(w=>image(format:(encoding:"rgba8",width:w,height:w),for i in(w=range(w).map(y=>y/w*4-2))+w{for j in w{let(a,b,k)=(0,0,1);while k>0>(a*a+b*b>4){(a,b)=(-b*b+a*a+j,2*a*b+i);k/=2.1};k.to-bytes(size:4)}}))(640)

enter image description here

Mostly works the same as the previous solution, except that instead of usingk as an integer and counting down, we make it a float and repeatedly divide it by 2.1, with the exit condition being float underflow (k will eventually be so small that it is rounded to 0); we then take the colour from the 4 (little-endian) bytes of a single-precision representation ofk, with the 4th byte representing alpha (resulting in everything being a bit washed out).We lose one byte toencoding:"rgba8", but save 4 bytes in the main body:

let(a,b,k)=(0,0,1);while k>0>(a*a+b*b>4){(a,b)=(-b*b+a*a+j,2*a*b+i);k/=2.1};k.to-bytes(size:4)

This is horribly inefficient, since it takes about 1000 iterations fork to reach 0, but when rounded to single-precision it reaches 0 in only 140 iterations, so we compute far more iterations than we display. Nonetheless, this means we correctly display >99 iterations, meeting the challenge minimum.

Typst, 205 bytes

#(w=>image(format:(encoding:"rgba8",width:w,height:w),for i in(w=range(w).map(y=>y/w*4-2))+w{for j in w{let(a,b,k)=(0,0,1);while k>0>(a*a+b*b>4){(a,b)=(-b*b+a*a+j,2*a*b+i);k/=2};k.to-bytes(size:4)}}))(640)

enter image description here

The previous solution, but with 2.1 cut down to 2. For obvious reasons, this makes the bytes of the floating point representations much more predictable; however, it luckily happens to produce a near-alternating pattern (so the neighbouring colours are clearly distinguishable), and each seemingly-identical colour is actually a very slightly different shade, so the challenge conditions are again met. (The number of displayed iterations is 150 in this case. Note that we can't use a divisor of 3, since that reaches single-precision zero by iteration 95).

answeredOct 29 at 22:34
sungodmoth's user avatar
\$\endgroup\$
1
  • \$\begingroup\$How cheeky of you to use a float as both the iteration counter and as a color. I learned a new trick.\$\endgroup\$CommentedNov 2 at 9:48
2
\$\begingroup\$

Julia

Well, better late than never:

function mandelbrot(x0,y0,side,N=800,L=55,R=3.)    m = [0 for i=1:N,j=1:N]    delta = side/N    for i=1:N, j=1:N        c = x0+delta*i+(y0+delta*j)*im        z, h = 0+0*im, 0        while (h<L) && (abs(z)<R)            z = z^2+c            h+=1        end        m[j,i]=h    end    return mendn=2.6m = mandelbrot(-n/1.3,-n/2, n)using Winston, Colorimagesc(m)title("Mandelbrot Set")

Colormap Mod. :

function RGB_cm()    colormap = [RGB(0,0,0) for t=1:255*5]    rgb = [255,0,0]    for t in 0:(255*5-1)    c = [0, 0, 0]    i = ifloor(t/255)    c[(i+3)%3!=0?(i+3)%3:3] = (-1)^i    rgb+=c    colormap[t+1] = RGB(rgb[1],rgb[2],rgb[3])    end    colormap[(end-25):end] = RGB(0,0,0)    return colormapendc = RGB_cm()Winston.colormap(c)

Output:

Mandelbrot Set

answeredMar 13, 2014 at 4:27
CCP's user avatar
\$\endgroup\$
3
  • \$\begingroup\$Should I byte-count only the first program or both?\$\endgroup\$CommentedMar 29, 2014 at 10:10
  • \$\begingroup\$I think both, because without the color map mod the image would not satisfy the rules.\$\endgroup\$CommentedMar 29, 2014 at 15:35
  • 2
    \$\begingroup\$I'm sure you can save much on whitespace.\$\endgroup\$CommentedSep 25, 2017 at 17:15
2
\$\begingroup\$

CASIO BASIC (CASIO fx-9750GIII), 96 bytes

translation of12Me21's Answer it TI-80 BASIC

For -2→R To 2 Step .1For -2→Q To 2 Step .10→S~TFor 1→N To 21SS+TT≥4⇒BreakSS-TT+Q→I2ST+R→TI→SNextFrac (.5N⇒Plot Q,RNextNext

this is unbelievably slow.

mandelbrot

check it out online

answeredMar 13 at 15:42
madeforlosers's user avatar
\$\endgroup\$
1
  • \$\begingroup\$You can get a ""photo"" of it if you let it run in that online emulator\$\endgroup\$CommentedMar 15 at 11:46

Your Answer

More generally…

  • …Please make sure to answer the question and provide sufficient detail.

  • …Avoid asking for help, clarification or responding to other answers (use comments instead).

Draft saved
Draft discarded

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.