Time tracking with timewarrior

I’ve been working from home for a bit more than a month – or, as we say around here, “doing home office”, which is apparently a typically German turn of phrase ๐Ÿ˜‰ Since I’m working part-time (60%), and days and hours tend to melt into each other, actually tracking the time that I spend working has proven pretty useful for me to dose the “right” amount of work: make sure I’m working the hours I’m supposed to work, make sure I’m not working significantly more than the hours I’m supposed to work. For those who know me a little, they’ll have an inkling that my issue is more the latter one than the former, with me being much more worried about the former than the latter ๐Ÿ˜‰

I had done that sort of tracking a long while ago with some software called arbtt. It was fairly neat when it came to automating that tracking (and that’s why I’m mentioning it here explicitly): it uses the mouse focus to determine on which window you are working, identifies said windows by their titles, and allows to define rules to classify which belongs to what. I ran that thing for a while when I was working as a freelancer, and that worked pretty well – if you’re not allergic to Haskell. (My window manager is in Haskell too, so I can survive :p )

This time around, I didn’t feel the need to fight with arbtt rule system to fit everything into categories that would be too fine-grained for my liking; after a bit of poking, I found timewarrior. There’s a package on my Ubuntu, so I just installed it, and I started tracking.

In timewarrior, you track by associating tags to intervals of time. For instance, when I start working on documentation, I open a terminal and type

$ timew start work doc

and it starts an interval tagged with work and doc. I have a very coarse set of tags: my current tags are doc (writing documentation), qa (helping our QA department with testing our software), meeting (daily and weekly status meetings, mostly) and social (when I’m socializing with colleagues, not necessarily being productive per se, although such discussions are very often fruitful). To that, I add a generic work tag to these all categories except social, so that I can easily tally my whole work hours. I’m not actively developing these days, but when that comes back, I’ll handle tags for that as well. I also track lunch when I go for my lunch break ๐Ÿ˜‰

Whenever I start a new interval, it automatically closes the previous one – so if I switch from timew start work doc to timew start lunch, the interval lunch starts, and the interval work/doc is closed. If I want to stop the current interval without starting a new one (typically at the end of the day), I just go

$ timew stop

and no interval is running anymore.

To display what’s been logged so far, timew summary is the way to go. I actually experimented with tracking my Sunday yesterday, and if I want to know how long I spent cooking, I can look at my cuisine tag that way:

[isa@wayfarer ~]$ timew summary :yesterday cuisine

Wk  Date       Day Tags       Start      End    Time   Total
W17 2020-04-26 Sun cuisine 11:28:00 11:59:00 0:31:00
                   cuisine 18:04:59 18:28:09 0:23:10
                   cuisine 18:44:23 19:05:10 0:20:47 1:14:57

It gives me all the instances and a sum of the time I spent overall during the day. This is particularly useful for my work usage: I tag everything I do for work with work, and that allows me to keep track of the amount of work I’ve put in the day.

If I forget to start or stop an activity, it’s trivial to do a posteriori if I’m in an “open” interval, slightly more tricky but still feasible if I need to re-insert things in the middle of other things. Generally speaking, I haven’t found something that I wanted to do that I didn’t find how to yet. The interface can be somewhat clunky, but it’s surprisingly input-flexible (the easy example is that I can do “timew start work doc” or “timew work doc start” or even “timew doc start work” – and it’ll start tracking an activity with tags doc and work in both cases).

The documentation is also very good, allowing both discoverability of features and reference. There’s also ways of getting pretty charts, to export data as JSON, and to develop extensions.

Obviously, if you’re looking for something that synchronizes between several computers, or that you can use on your phone, or or or…. this may not be the software for you. (Although running it somewhere on the internet and tracking via SSH would probably be a viable option). Me, I just want to open a term, type timew start mystuff, close my term, and be done with it – and I don’t care about tracking different things on different computers, because the context of what I’m tracking is different anyway. If your needs align with mine, I can only recommend you have a look at timewarrior ๐Ÿ™‚

Advent of Code 2019

2019 was the fifth year of Advent of Code – and I consequently spent December waking up at 6AM and spending a lot of brain cycles solving puzzles to bring back Santa from the other side of the solar system, where he was stranded.

Let me quote myself to describe the whole thing to the people who are not familiar with it.  Advent of Code is an advent calendar with puzzles that can mostly be solved by programming: the input is a problem description and a user-specific input (as far as I know, thereโ€™s a set of a โ€œfewโ€ pre-validated/pre-tested inputs), and you have to compute a number or a short string, and provide that as a result. If you have the correct result, you unlock a star and the second part of the puzzle, which allows to unlock a second star. Over the course of the 25 first days of December, you consequently get to collect 50 stars.

When I wrote my Advent of Code 2018 blog post last year, it was December 26th, and I had solved everything – this year it took me until yesterday (so, December 31th) before I got the 50th star. I don’t know if the problems were harder or if I got worse at solving them (maybe a mix of both?), but I still made it before the end of 2019, so I’ll count that as a win ๐Ÿ™‚

This year, I worked in Kotlin, a JVM-based language designed by JetBrains, and that I enjoy quite a lot – it is fully compatible with Java, and allows for a much terser syntax, and requires to do things explicitly when it comes to mutability of variables and collections. I like it. My solution repository is on GitHub – beware, here be dragons… and spoilers!

And, like last year, let me give a few impressions of the different puzzles for this year. I WILL spoil the problems and at least hint at their solutions – if you want to start solving the problems with no preconception at all, you may want to stop reading here ๐Ÿ™‚

Continue reading “Advent of Code 2019”

New monitor, new setup!

I just replaced my 24″ monitor with a new shiny 27″ – 3 more inches in the diagonal, but 4 times more pixels – which required a bit of tinkering – so here’s a bit of a write-up, so that a/ I can share what worked for me and b/ I have something to refer to myself whenever I do that again (I’ll probably have to tinker is some similar ways for the laptop…)

General setup

I have a fairly… personal setup – it DOES work for me, but it’s definitely in the “less common” category, which makes searching for information somewhat more challenging.

  • First things first, obviously: I run Linux, specifically right now Ubuntu 19.04 Disco Dingo – that’s probably the most standard element of my setup.
  • I run it with xmonad/xmobar/dmenu as my user interface.
  • My main screen is now a 27″, 3840ร—2160 (very pixels, wow)
  • I have a second screen, left of my main one, as a secondary screen, which I mostly use for “browsing documentation when I’m doing something on the main screen” or “chat window when I’m playing in full screen on the main screen”. It’s a 19″, 1280ร—1024. So, yes, that means multiple-DPI setup – I will admit that the thought had not crossed my mind when I bought the new one. Eh.

So, essentially, this looks like this:

Display configuration

I have a fair amount of things running in the browser, so the first thing I experimented with was changing the scale of the pages of what I was browsing. That went okay on the large screen, but then the scale was completely off for my secondary screen – and switching scale levels depending on the screen would have been a major pain. There is some automated and experimental stuff there; since my setup is already atypical, I decided to not dig much more into why it didn’t work. (I tried. Vaguely.)

I ran into a reasonable solution almost by chance (I didn’t know exactly what I was looking for) here: Configuring mixed DPI monitors with xrandr. I’m now scaling the secondary monitor by a factor of 1.5, which makes it still “good enough for my use” when it comes to the look of the screen (it’s wobbly on my terminal. I can live with that.) and which is “compatible enough with my large screen” when it comes to displaying stuff that’s configured for my large screen.

I’ve been running a “screen setup” script for a long while (which I basically run every time I boot my computer – both on the laptop and on the desktop), so it was a matter of editing the xrandr line to the following:

xrandr --output DVI-D-0 --scale 1.5x1.5 --output DP-2 --pos 1920x0 \
    --mode 3840x2160 --primary 

So from there, I know that whatever I do on the large screen is going to be “good enough” on the secondary screen.


Chrome has been a bit of a pain. My first attempt was playing with the default scaling of the rendered web pages and fonts, but the tabs and the UI were still (as expected) super small. I finally found the right flag, specifically --force-device-scale-factor=1.5. As far as I can tell, there’s no way to make that configuration persistent at Chrome level (or, at least, I didn’t find it). And since I’m not starting my browser from an icon or a shortcut or anything like that, I couldn’t set it up there either. I ended up creating a google-chrome launch script in my personal bin directory (which was already setup in front of my PATH, thankfully, otherwise I would have required additional yaks) to pass the flag.

Moreover, the flag worked to scale the UI, but it also re-scaled the web page rendering, so I had to roll back my earlier config attempts. But now everything is fine and I can use Chrome without squinting too much, yay.

The “Save” dialog is still tiny, but I really don’t want to try to fix that now, so it’ll wait.

xmonad / xmobar / dmenu / trayer

My top bar with xmobar and the trayer were feeling a bit cramped, and so did my dmenu (the text-based launcher I use to start everything else). Some adjustments were required there:

  • I changed the configuration of the xmobar position in .xmobarrc to read position = Static { xpos = 1920, ypos = 0, width = 3456, height = 30 } ; the xpos parameter is set to 1920 because I don’t want that bar to be present on my secondary screen (and it’s setup to have a width of 1920); the width is 90% of 3840 so that I have 10% of the width for my trayer.
  • I wouldn’t have needed to touch my xmonad config if not for the fact that it’s launching dmenu, and that dmenu’s config is in the command line; I just modified the font of dmenu so that I have ((modMask, xK_p), spawn "dmenu_run -fn xft:terminus:style=medium:pixelsize=22") to start dmenu on Mod-P.
  • Finally, I only changed the height of the trayer (since the width is expressed as a percentage of the total width) so that it now reads trayer --edge top --align right --SetDockType true --SetPartialStrut true --expand true --width 10 --transparent true --tint 0x191970 --height 30 --monitor 1 &. This part is in my “setup screen” script, so the modification here was minor.


I use gnome-terminal as my standard terminal: it’s the only thing I ever managed to configure exactly as I wanted it (set of colors, unicode handling, non-blinking cursor, and that sort of things.)

The font was on the small side on the highres display, so I switched to Terminus Regular size 22. I’m not convinced yet by that choice, because it feels bolder than I think it should be, so I may have to play with alternate choices at some point or another. For now, it’s good enough. And I don’t care about the UI scaling in general because I don’t use “anything else than writing on the terminal” often enough for it to be a problem.


I just zoomed to 150% in the default preferences in Accessibility. The menus and whatnot are still tiny, but I actually don’t care (because I don’t use them much). Good enough for now.


Darktable the software I use to do most of my photo post-processing. The picture area is much nicer on the new screen (ahem. It may also have something to do with “the picture area is much nicer on a clean screen.), but the interface was also very tiny. Two things there:

  • in .config/darktable/darktablerc, set screen_dpi_overwrite=150 – I didn’t feel the need to experiment more with other values, this works for me
  • in the UI settings (available from the interface), set the “width of the side panels in pixels” to 400.

It is necessary to restart Darktable after this modification.


Since I also started to learn how to use GIMP, it did cross my mind to set it up during my initial setup. Two things:

  • I defined the icon size to “Large” in Preferences > Interface > Icon Theme
  • I also defined the font name to “sans 16” in my theme file, /usr/share/gimp/2.0/themes/gtkrc (defined in Preferences > Interface > Theme).

And this can be reloaded without restarting Gimp ๐Ÿ™‚

IntelliJ / CLion

I’m using IntelliJ at work, and the rest of the JetBrains IDEs at home. These days, I’m using CLion to develop on Marzipan (my fractal generator). IntelliJ scales its interface depending on the UI font size; so in Settings > Appearance & Behavior > Appearance, I modified the custom font for a size of 20.

This doesn’t modify the editor font size, though, which needs to be defined in Settings > Editor > Font.

Also, I know have a stronger incentive to continue working on my fractal generator: now that I have a higher res screen, I’m tempted to generate high res images, so I need to optimize that ๐Ÿ˜‰ And also probably to decouple the size of the image from the size of my UI ๐Ÿ˜›

World of Warcraft

I’ll admit, WoW is one of the first things I tested after plugging in everything and checking that basic function was there. I’m running WoW on WINE – and this was actually the least painful experience: it started without problem, the UI scaled properly immediately, and everything was just as I left it. The only difference is that the cursor is smaller (and that I probably need to modify my mouse sensitivity). But all in all, flawless. And it still runs 100fps, which is cool. (I did feel the need to triple check that I was indeed running in that large resolution. It seems I am.)

Slay the Spire

Other game I play a lot, Slay the Spire – there, I had to adjust resolution manually, but once that was done, nothing to see here, move along.


This may seem like quite a lot of work, and some snark along the lines of “if you ran Windows/MacOS/GNOME/KDE you wouldn’t have to configure things in such a gazillion places” may be warranted – but to me the “having things exactly as I want them” is definitely worth a bit of extra work – as well as knowing that once the configuration is stable, it doesn’t break at every update ๐Ÿ˜‰

I’ll probably find a couple more things to fix in the near future, and I’ll update this post with my findings.

Marzipan update – now with context menu!

It may seem trivial, but I unlocked an achievement on Marzipan: I added a menu. I’ve been wanting to have a few “quality of life” improvements for a while now, but so far I had been hiding under the duvet of “I really don’t want to touch the UI/Qt code more than I strictly have to”.

My experience with graphical toolkits in general has never been great. It’s really out of my comfort zone; I tend to find that the tutorials on the Internet don’t have anything between an equivalent of “Hello, World!” and an equivalent of “here’s some advanced quantum mechanics” (I do suck at physics in general as well); I kind of have the impression that my use cases are dead simple and should just Be Available As Is and that For Sure I Don’t Need To Read All That Documentation. (Yeah, yeah, I may be somewhat guilty here.) And I get upset and impatient, and generally speaking it’s not a good experience – neither for myself nor for anyone else in the room. (My apologies to my husband!)

But when you’re the only coder and the only user of a project, at some point biting the bullet gets inevitable. Consequently, in the last pull request, I did a fair amount of refactoring. When I started my coding session, everything was contained in a QWindow, in which I was painting an image directly on the QBackingStore. I then read a bunch of stuff about menus, which made me update my QWindow to a QMainWindow – for which the QBackingStore seems less trivially accessible, so I modified that. But then, the refresh was only working when resizing the window, which kind of sucked (and I’m still not entirely sure why). So I put a QWidget inside my QMainWindow as a main widget, and that allowed me to have both the refresh and the menu – yay! I needed to tinker a bit more to get back the keyboard control (move them from the QWidget to the QMainWindow), and now it’s all nice and shiny.

The undo/redo function itself is basically storing the fractal parameters in a couple of stacks and re-computing on undo/redo – nothing fancy (and my memory management is utter shit – read “nonexistent”, I really need to fix that – and I don’t handle storing the orbits properly yet, but one thing at a time.)

As a result: I do have at least half-functional Undo/Redo, and more importantly, I have a reasonable base for future UI/QoL development: I hope that the major hurdle of figuring out how things might fit together is behind me, and I’m a bit less scared of it.

I can’t say I’m happy with that session, because I still have the impression that I tried to put stuff together while having no idea what I’m doing, and while having the impression that I’m not actually learning anything in the process, but this may actually be better than I think. We’ll see ๐Ÿ™‚

Some more Marzipan bitmap fun

I did track down my zoom/scaling issue that I was mentioning in the previous post, and I improved the distance map for my bitmap orbit coloring. I’m still not 100% happy with it – I need to think a bit more about what I want to do there exactly, but it’s still enough that I spent a couple of hours yesterday playing with Marzipan as a “fractal generating software” and having fun with it, and not only as a “software project I’m working on”. Granted, the “UI” is still mostly “let me change the color palette and recompile”, but I was having too much fun making pretty images to dig into making the UI usable ๐Ÿ™‚

So – here are a few pictures from my last “creative” session ๐Ÿ™‚

Purple explosion

For “Purple explosion,” the seed bitmap is a bunch of rectangles of the same size put randomly on the canvas.

Rainbow equation

“Rainbow equation” is dedicated to Matthias, who was the one mentioning I should put the set equation in the image. And it’s rainbow because why the hell not ๐Ÿ™‚

Lace flowers

“Lace flowers” uses one of the brushes from GIMP (Manju’s Flower – Large) as its base. I quite like this one, except for the fact that my processing of the flower should be smoother so that the end result is also smoother. That’s how I learn ๐Ÿ˜‰

Tux funnel

For “Tux funnel”, I used as a base the Tux Mono drawing by gg3po, Iwan Gabovitch, GPL licensed, via Wikimedia Commons.

One of the things that amuses me is the ephemeral quality of what I do here. Choosing to save a picture (and that’s still somewhat of an ordeal) is the only way to keep a trace of what I’m doing. I cannot get back to an image and try to “keep it, but improve it”: since I don’t have my settings and I don’t remember where I zoom, any new attempt will be a new image. I even didn’t keep my seed bitmaps so far – so reproducing an image would really be hopeless. And I quite like it that way.

Marzipan – bitmap orbits (and some bugs)

I worked a bit on Marzipan this week-end, and started playing with bitmap orbits. The idea is the same as for point orbits and line orbits: we look at the iterations of the escaping points, and we look at the distance on the plane between the complex numbers represented by these iterations and a given set on the same plane.

Since my creativity was apparently all used up by trying to make the algorithm work instead of trying to find a nice bitmap to play with, I simply have the name of my project somewhere on an image, as black&white. I pre-compute a distance map to that bitmap (in a very approximate and most probably buggy way right now – something’s not quite right there, but good enough for a first approximation) and I use that distance map to display the points I’m interested in when rendering the fractal.

The very annoying thing is that I do have a bug on the zooming algorithm – things tend to flip and/or to go to weird places. I haven’t been able to track it down yet: it must be said that I’m typically hopeless at handling 2D grids and scaling factors without breaking a neuron or two, and that on top of that, as mentioned previously, I’m probably making my own life miserable by using a non-standard window manager. I’ll probably need to go to KDE or something to debug this thing properly (sigh :/)

Still, in the meantime, I’m not unhappy with the results ๐Ÿ™‚

Marzipan progress

Today I added a couple of features to Marzipan, my fractal generator, so I’m going to show a few images of what I worked on ๐Ÿ™‚

First, I refactored the orbit trap coloring to be able to expand it with other types of orbit traps; then I added the implementation for line orbit traps. Turns out, adding random line and point orbit traps is pretty fun, and can yield pretty results!

A mix of line and point trap orbits

The other thing that I did was to add “multi-color palettes”: instead of giving a “beginning color” and an “end-color”, I can now pass a set of colors that will get used over the value interval. Which means, I can get much more colorful (and hence incredibly more eye-hurting) images!

Yay, rainbows!

And, well, I can also combine these two approaches to get NEON RAINBOWS!


Finally, I also played a bit with the ratios of the image that I generate – the goal is to not distort the general shape of the bulbs when zooming in the image. This is still pretty unsatisfactory, I need to make that work better (and to understand exactly how the size of the Qt window interacts with my window manager, because I’m probably making my life more complicated than it strictly needs to be there).

I had a lot of fun today implementing all of that, and then losing myself into finding fun colorings and fun trap orbits and all that kind of things. Now, the issue is that if I have more colors, I have more leeway to generate REALLY UGLY IMAGES, and I may need to develop a bit of taste if I want to continue doing pretty stuff ๐Ÿ˜‰

Now what crossed my mind today:

  • I believe I have a bug, either in the multi-color palette or in the orbit trap coloring – I’ve seen suspicious things when zooming on certain parts (colors changing whereas they should not have), so I’ll need to track it and fix it. I also made performance worse when playing with multiple orbits for laziness reasons, I’ll need to fix that too.
  • I have some more things that I want to experiment with on orbit traps – I think there’s some prettiness I haven’t explored yet and I want to do that.
  • I should really start thinking about getting a better UI. I want a have better UI, I don’t want to code the better UI ๐Ÿ˜›
  • I should at least add a proper way to save an image instead of relying on getting them from the place where I dump them before displaying them – that would be helpful.
  • I should also find a way to import/export “settings” so that a given image can be reproduced – right now it’s very ephemeral. Which is not necessarily a bad thing ๐Ÿ˜‰
  • I can probably improve the performance of the “increasing the number of iterations” operation, and I should do that.
  • The “image ratio” thing is still very fuzzy and I need to think a bit more about what I want and how to do it.

Smooth coloring of Mandelbrot

I got half nerd-sniped (by my dad, as it quite often happens) after my blog post on my fractal renderer – “but… your continuous coloring, there… how does it work?”. I had implemented it 8 months ago without really asking myself the question, so after answering “eh, some magic”, I finally got curious for real, and I started digging a bit more into it.

Starting from the Wikipedia article footnotes, I ended up on a couple of articles: Renormalizing the Mandelbrot Escape and Smooth Escape Iteration Counts, as well as smooth iteration count for generalized Mandelbrot sets, that mostly allowed me to piece together some understanding of it. I will admit that my own understanding is still a bit messy/sloppy – my aim here is to try to give some understanding somewhere between “apply this function and you get smooth coloring” and “spectral analysis of eigenvalues in Hilbert spaces” (it’s APPARENTLY related; I’m pretty sure I’ve known at SOME point what this group of words meant, but right now it’s barely a fuzzy concept. Math: if you don’t use it you lose it ๐Ÿ˜ฆ ).

Mandelbrot set and discrete coloring

Before talking about continuous coloring, let me set a few concepts and notations so that we’re on the same page.

We iterate, from a point c = x + y\mathrm{i} (where (x,y) are coordinates on the plane), the sequence z = z^2 + c, where z is a starting constant, typically 0, and we look at the points for which this sequence diverges to infinity or does not. The points for which the sequence does not diverge to infinity (i.e., the sequence is bounded) are part of the Mandelbrot set.

Counting to infinity is, however, a bit long. The first thing we can do is – if we know early that the sequence goes to infinity, we can stop counting: the sequence diverges. We happen to know that, for z = z^2 + c, the sequence diverges as soon as its magnitude |z| > R (or equivalently, x^2 + y^2 > R). (Note that the minimum value for this to work is R = 2.) So we can iterate on every point and, as soon as its magnitude reaches 2, conclude that the point is not in the Mandelbrot set. This process gives another information: the iteration at which this condition is met – which is an indication about how fast the sequence diverges.

That only solves a part of the problem – because by definition, the points for which the sequence is bounded will never stop the process in that model. So the second thing we do is to consider that if a sequence has not diverged after a given, fixed number of iterations, then probably it won’t.

Finally, for every possible number of iterations, we define a color (in a way that eventually makes the result pretty/interesting); we also define a color for points whose sequence does not diverge (and that are considered in the set); and we color each point according to that.

Now the thing with this approach is that the number of iterations tend to gather in “bands” – as in the following picture.

Discrete coloring bands

Smooth coloring

The bands come from the fact that two neighboring pixels “tend to” have the same number of iterations, and hence the same color. If the range of possible values is smooth, and if two neighboring points end up not being associated to the exact same value, and if the palette maps them to different colors, then the coloring should be smooth – even with a fairly reduced palette.

The idea is that we want to represent whether a sequence “barely” reached the escape radius or whether it could have done so almost on the previous iteration, so far it is from the threshold. Ideally, we represent that by a function that goes from 0 to 1, we get a nice smooth range, and that yields a nice smooth coloring.

Now many sources go from this statement to “and now, like a rabbit out of the hat, take \log(\log(z)) and we’re done”. Some of them mumble something about “deriving it from Douady-Hubbard potential“, but it’s not really satisfying either. I gave a quick look to that, and I may revisit the topic eventually, but right now the maths go wayyyy over my head ๐Ÿ˜ฆ

Still, the main question I had was “well, if we’re only interested in mapping ‘the space between the bands’, why not just drop a linear operator on that and be done?”. My reasoning was as follows: we know that at iteration i, we’re above the radius of convergence R, and we were not in the previous iteration, that means that we can bound it. If z_{i-1} and z_i are the values of z at escape iteration i, we have, by definition of i, |z_i| > R and |z_{i-1}| \leq R. To bound z_i from the above, we write |z_i| = |z_{i-1}^2 + c| (by definition of z), which is less than |z_{i-1}|^2 + |c| (by triangular inequality), which is in turn less than R^2 + |c|.

Hence, our “escape margin” |z| - R is between 0 and r^2 + |c|, and we want to map that to something between 0 and 1, so let’s just divide those two things, define my fractional iteration count as \displaystyle i + 1 - \frac{|z| - R}{r^2 + |c|} and we’re done, right?

Hmmm. It DOES look smooth-er. It’s not… smooth. I have two guesses here. First: the triangular inequality is a bit too rough for my estimate. Second: it may be that I’m generally speaking missing something somewhere. Maybe a bit of both.

Now that’s where the “magic” happens. I’ve read enough on the topic to have some inkling that there’s actual, proper math behind that makes it work, but I’m not able to understand, let alone explain it in simple terms ๐Ÿ˜‰

The fractional iteration count that makes things work is \displaystyle i + 1 - \frac{\ln \ln |z|}{\ln 2}. The best intuition/simplified explanation I’ve seen for this comes from Renormalizing the Mandelbrot Escape, where they have the following quote:

The following simplified and very insightful explanation is provided by Earl L. Hinrichs:
“Ignoring the +C in the usual formula, the orbit point grows by Z := Z^2. So we have the progression Z, Z^2, Z^4, Z^8, Z^16, etc. Iteration counting amounts to assigning an integer to these values. Ignoring a multiplier, the log of this sequence is: 1, 2, 4, 8, 16. The log-log is 0, 1, 2, 3, 4 which matches the integer value from the iteration counting. So the appropriate generalization of the discrete iteration counting to a continuous function would be the double log.”

Smooth coloring

So, there. I’m going to leave the topic there for now – that was quite fun to dig into, but I do need more advanced math if I want to dig deeper. It might happen – who knows – but not now ๐Ÿ™‚

New year Marzipan

Around a year ago, I started playing with a small fractal generator that I called Marzipan (because, well, Mandelbrot – basically marzipan, right). Okay, in all fairness, I re-used that name from a previous small fractal generator that I had coded in Javascript several years ago ๐Ÿ™‚

It’s primarily (for now) a renderer of colored Mandelbrot sets. The Mandelbrot set is fairly well-known:

Mandelbrot set

This image is a made on a 2D plane whose upper-left coordinate is at (-2, -1) and lower-end coordinate is at (1, 1). For each point (x, y) of this plane, we consider the complex number z = x + yi, we do some operations (called iterations) repeatedly on z, and we see what is the result. If z grows larger and larger (if the sequence of operations diverges), the point z is not in the Mandelbrot set, and we color it grey. If it does not, or if we give up before seeing that it diverges, the point z in in the Mandelbrot set, and we color it black. The longer we wait before deciding that a point is in the set, the more precise the boundary is (because we have “more chances” that it diverges if it is going to diverge).

And it’s technically possible to zoom as much as you want on the border of the set and to get “interesting” results at infinite amount of zoom – every little part of the border has an infinite amount of detail.

Now one of the reason why Mandelbrot (and other similar computation) renderings are quite popular is that they’re colorful and pretty. In particular, I have a fair amount of screen wallpaper coming from Blatte’s Backgrounds, that contain some of this kind of images. The connection between my set above and the colorful images I linked is not a priori obvious.

Enter: coloring algorithms. The idea is to try to represent graphically how the points outside of the set diverge. The first algorithm I implemented was a escape time algorithm: if the point diverges after 5 iterations, color it in a given color, after 6, in an other color, after 50, in yet another color, and so on. And the fastest way to generate a color palette is to just generate it randomly (and to affect one color to each possible number of iterations), which can yield… fairly ugly images ๐Ÿ˜‰

Random coloring of the escape time

A variation of that approach is to affect to each number of iteration a color that is “proportional” (for instance, more or less saturated) to the number of points that actually reach that number of iterations.

Histogram coloring of the escape time

Then the next idea is to go from “discrete coloring” to “continuous coloring” – right now, we have bands of colors that may have some aesthetic quality, but that may not work for what one has in mind in the end. To achieve that, we add a “continuous” component to our iteration computation (so that it’s not integer anymore) and we map it to the color palette.

Continuous coloring of the escape time

The other coloring algorithm that I started exploring today is coloring by orbit traps. Instead of considering when the iteration escape, we look at how it escapes, and we try to represent that. The first idea is to take an arbitrary, “interesting” point (from an aesthetic point of view, and mostly found by trial and error at this stage), and to look at how close the iterations of the escaping points come to this fixed point). The colored values are the distances to this point. (And the image at the beginning of this post is a (low) zoom from this one ๐Ÿ™‚ ) Note: on this one I also tweaked the palette computation to get more contrast. That was fun ๐Ÿ™‚

Coloring of the distance to an orbit point (-0.25 + 0.5i)

Generally speaking, this project is also for me a nice visual sandbox to play around – on top of practicing my C++, my goal is to generate pretty images, but that typically requires a fair amount of “quality of life” updates:

  • a very basic set of command-line options so that I could generate images without hard-coding all the values
  • quicker than I would have thought: a minimal Qt UI that allows me to zoom and increase/decrease the number of iterations – and right now I kind of feel the need to expand that UI so that it’s… actually useable (being able to change parameters on the UI, re-scaling the window to fit the ratio of the rendered input, that sort of things)
  • yesterday, I sped up the rendering by… well, adding threads ๐Ÿ˜› (via the QtConcurrent library).

Generally speaking, it’s a fun project – and it’s actually something I can go back to quite quickly (once I go over the shock of “urgh C++” – I actually DO like C++, but I did AoC in Go, and it’s a fairly different language) and implement a thing or two here or there, which is nice. For instance, a few months ago, I went “given my current code, can I add support for Julia sets within 10 minutes before going to bed?” and the answer was yes:

Julia set for z = -0.4+0.6i

Advent of Code 2018

In the past few years, December has been for me “the month of Advent of Code”. Advent of Code is an advent calendar with puzzles that can mostly be solved by programming: the input is a problem description and a user-specific input (as far as I know, there’s a set of a “few” pre-validated/pre-tested inputs), and you have to compute a number or a short string, and provide that as a result. If you have the correct result, you unlock a star and the second part of the puzzle, which allows to unlock a second star. Over the course of the 25 first days of December, you consequently get to collect 50 stars.

I like the puzzles, I like the fluff around it (typically a more-or-less-sensical story around the Christmas theme), I like the duration and effort involved, I like that I learn something every year – all in all, I’m a fan ๐Ÿ™‚ There’s a “global leaderboard” that tracks all the users who are in the first 100 to solve each puzzle; although I’m on a “favorable” timezone for the puzzles (they come up at 6am for me), I have no hope of ever scoring points on the leaderboard; my claim to fate this year is that I was in the first 1000 players for 11 stars out of 50 ๐Ÿ™‚

This year, as last year, I solved the whole thing in Go; my Go is still quite bad, probably not-a-all Go-like, and I tend to try to avoid spending too much time second-guessing and refactoring my code in that kind of contexts (it’s good training against analysis paralysis ๐Ÿ˜‰ ), and it’s available on my GitHub if you’re not afraid of bad code and spoilers ๐Ÿ™‚ (Oh, and also: truly horrifying code organization.)

After this general introduction, I want to talk a bit about my experience of the individual problems, so beware: spoilers ahead!

Continue reading “Advent of Code 2018”