|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: Happy Trees |
| 4 | +tags: golang math color |
| 5 | +username: mediocregopher |
| 6 | +source: "https://github.com/mediocregopher/happy-tree" |
| 7 | +--- |
| 8 | + |
| 9 | +This project was inspired by [this video](https://www.youtube.com/watch?v=_DpzAvb3Vk4), |
| 10 | +which you should watch first in order to really understand what's going on. |
| 11 | + |
| 12 | +My inspiration came from his noting that happification could be done on numbers |
| 13 | +in bases other than 10. I immediately thought of hexadecimal, base-16, since I'm |
| 14 | +a programmer and that's what I think of. I also was trying to think of how one |
| 15 | +would graphically represent a large happification tree, when I realized that |
| 16 | +hexadecimal numbers are colors, and colors graphically represent things nicely! |
| 17 | + |
| 18 | +## Colors |
| 19 | + |
| 20 | +Colors to computers are represented using 3-bytes, encompassing red, green, and |
| 21 | +blue. Each byte is represented by two hexadecimal digits, and they are appended |
| 22 | +together. For example `FF0000` represents maximum red (`FF`) added to no green |
| 23 | +and no blue. `FF5500` represents maximum red (`FF`), some green (`55`) and no |
| 24 | +blue (`00`), which when added together results in kind of an orange color. |
| 25 | + |
| 26 | +## Happifying colors |
| 27 | + |
| 28 | +In base 10, happifying a number is done by splitting its digits, squaring each |
| 29 | +one individually, and adding the resulting numbers. The principal works the same |
| 30 | +for hexadecimal numbers: |
| 31 | + |
| 32 | +``` |
| 33 | +A4F |
| 34 | +A*A + 4*4 + F*F |
| 35 | +64 + 10 + E1 |
| 36 | +155 // 341 in decimal |
| 37 | +``` |
| 38 | + |
| 39 | +So if all colors are 6-digit hexadecimal numbers, they can be happified easily! |
| 40 | + |
| 41 | +``` |
| 42 | +FF5500 |
| 43 | +F*F + F*F + 5*5 + 5*5 + 0*0 + 0*0 |
| 44 | +E1 + E1 + 19 + 19 + 0 + 0 |
| 45 | +0001F4 |
| 46 | +``` |
| 47 | + |
| 48 | +So `FF5500` (and orangish color) happifies to `0001F4` (A darker blue). Since |
| 49 | +order of digits doesn't matter, `5F50F0` also happifies to `0001F4`. From this |
| 50 | +fact, we can make a tree (hence the happification tree). I can do this process |
| 51 | +on every color from `000000` (black) to `FFFFFF` (white), so I will! |
| 52 | + |
| 53 | +## Representing the tree |
| 54 | + |
| 55 | +So I know I can represent the tree using color, but there's more to decide on |
| 56 | +than that. The easy way to represent a tree would be to simply draw a literal |
| 57 | +tree graph, with a circle for each color and lines pointing to its parent and |
| 58 | +children. But this is boring, and also if I want to represent *all* colors the |
| 59 | +resulting image would be enormous and/or unreadable. |
| 60 | + |
| 61 | +I decided on using a hollow, multi-level pie-chart. Using the example |
| 62 | +of `000002`, it would look something like this: |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | +The inner arc represents the color `000002`. The second arc represents the 15 |
| 67 | +different colors which happify into `000002`, each of them may also have their |
| 68 | +own outer arc of numbers which happify to them, and so on. |
| 69 | + |
| 70 | +This representation is nice because a) It looks cool and b) it allows the |
| 71 | +melancoils of the hexadecimals to be placed around the happification tree |
| 72 | +(numbers which happify into `000001`), which is convenient. It's also somewhat |
| 73 | +easier to code than a circle/branch based tree diagram. |
| 74 | + |
| 75 | +An important feature I had to implement was proportional slice sizes. If I were |
| 76 | +to give each child of a color an equal size on that arc's edge the image would |
| 77 | +simply not work. Some branches of the tree are extremely deep, while others are |
| 78 | +very shallow. If all were given the same space, those deep branches wouldn't |
| 79 | +even be representable by a single pixel's width, and would simply fail to show |
| 80 | +up. So I implemented proportional slice sizes, where the size of every slice is |
| 81 | +determined to be proportional to how many total (recursively) children it has. |
| 82 | +You can see this in the above example, where the second level arc is largely |
| 83 | +comprised of one giant slice, with many smaller slices taking up the end. |
| 84 | + |
| 85 | +## First attempt |
| 86 | + |
| 87 | +My first attempt resulted in this image (click for 5000x5000 version): |
| 88 | + |
| 89 | +[](/imgs/happy-tree/happy-tree-atmp1.png) |
| 90 | + |
| 91 | +The first thing you'll notice is that it looks pretty neat. |
| 92 | + |
| 93 | +The second thing you'll notice is that there's actually only one melancoil in |
| 94 | +the 6-digit hexadecimal number set. The innermost black circle is `000000` which |
| 95 | +only happifies to itself, and nothing else will happify to it (sad `000000`). |
| 96 | +The second circle represents `000001`, and all of its runty children. And |
| 97 | +finally the melancoil, comprised of: |
| 98 | + |
| 99 | +``` |
| 100 | +00000D -> 0000A9 -> 0000B5 -> 000092 -> 000055 -> 00003 -> ... |
| 101 | +``` |
| 102 | + |
| 103 | +The final thing you'll notice (or maybe it was the first, since it's really |
| 104 | +obvious) is that it's very blue. Non-blue colors are really only represented as |
| 105 | +leaves on their trees and don't ever really have any children of their own, so |
| 106 | +the blue and black sections take up vastly more space. |
| 107 | + |
| 108 | +This makes sense. The number which should generate the largest happification |
| 109 | +result, `FFFFFF`, only results in `000546`, which is primarily blue. So in effect |
| 110 | +all colors happify to some shade of blue. |
| 111 | + |
| 112 | +This might have been it, technically this is the happification tree and the |
| 113 | +melancoil of 6 digit hexadecimal numbers represented as colors. But it's also |
| 114 | +boring, and I wanted to do better. |
| 115 | + |
| 116 | +## Second attempt |
| 117 | + |
| 118 | +The root of the problem is that the definition of "happification" I used |
| 119 | +resulted in not diverse enough results. I wanted something which would give me |
| 120 | +numbers where any of the digits could be anything. Something more random. |
| 121 | + |
| 122 | +I considered using a hash instead, like md5, but that has its own problems. |
| 123 | +There's no gaurantee that any number would actually reach `000001`, which isn't |
| 124 | +required but it's a nice feature that I wanted. It also would be unlikely that |
| 125 | +there would be any melancoils that weren't absolutely gigantic. |
| 126 | + |
| 127 | +I ended up redefining what it meant to happify a hexadecimal number. Instead of |
| 128 | +adding all the digits up, I first split up the red, green, and blue digits into |
| 129 | +their own numbers, happified those numbers, and finally reassembled the results |
| 130 | +back into a single number. For example: |
| 131 | + |
| 132 | +``` |
| 133 | +FF5500 |
| 134 | +FF, 55, 00 |
| 135 | +F*F + F*F, 5*5 + 5*5, 0*0 + 0*0 |
| 136 | +1C2, 32, 00 |
| 137 | +C23200 |
| 138 | +``` |
| 139 | + |
| 140 | +I drop that 1 on the `1C2`, because it has no place in this system. Sorry 1. |
| 141 | + |
| 142 | +Simply replacing that function resulted in this image (click for 5000x5000) version: |
| 143 | + |
| 144 | +[](/imgs/happy-tree/happy-tree-atmp2.png) |
| 145 | + |
| 146 | +The first thing you notice is that it's so colorful! So that goal was achieved. |
| 147 | + |
| 148 | +The second thing you notice is that there's *significantly* more melancoils. |
| 149 | +Hundreds, even. Here's a couple of the melancoils (each on its own line): |
| 150 | + |
| 151 | +``` |
| 152 | +00000D -> 0000A9 -> 0000B5 -> 000092 -> 000055 -> 000032 -> ... |
| 153 | +000D0D -> 00A9A9 -> 00B5B5 -> 009292 -> 005555 -> 003232 -> ... |
| 154 | +0D0D0D -> A9A9A9 -> B5B5B5 -> 929292 -> 555555 -> 323232 -> ... |
| 155 | +0D0D32 -> A9A90D -> B5B5A9 -> 9292B5 -> 555592 -> 323255 -> ... |
| 156 | +... |
| 157 | +``` |
| 158 | + |
| 159 | +And so on. You'll notice the first melancoil listed is the same as the one from |
| 160 | +the first attempt. You'll also notice that the same numbers from the that |
| 161 | +melancoil are "re-used" in the rest of them as well. The second coil listed is |
| 162 | +the same as the first, just with the numbers repeated in the 3rd and 4th digits. |
| 163 | +The third coil has those numbers repeated once more in the 1st and 2nd digits. |
| 164 | +The final coil is the same numbers, but with the 5th and 6th digits offset one |
| 165 | +place in the rotation. |
| 166 | + |
| 167 | +The rest of the melancoils in this attempt work out to just be every conceivable |
| 168 | +iteration of the above. This is simply a property of the algorithm chosen, and |
| 169 | +there's not a whole lot we can do about it. |
| 170 | + |
| 171 | +## Third attempt |
| 172 | + |
| 173 | +After talking with [Mr. Marco](/members/#marcopolo) about the previous attempts |
| 174 | +I got an idea that would lead me towards more attempts. The main issue I was |
| 175 | +having in coming up with new happification algorithms was figuring out what to |
| 176 | +do about getting a number greater than `FFFFFF`. Dropping the leading digits |
| 177 | +just seemed.... lame. |
| 178 | + |
| 179 | +One solution I came up with was to simply happify again. And again, and again. |
| 180 | +Until I got a number less than or equal to `FFFFFF`. |
| 181 | + |
| 182 | +With this new plan, I could increase the power by which I'm raising each |
| 183 | +individual digit, and drop the strategy from the second attempt of splitting the |
| 184 | +number into three parts. In the first attempt I was doing happification to the |
| 185 | +power of 2, but what if I wanted to happify to the power of 6? It would look |
| 186 | +something like this (starting with the number `34BEEF`): |
| 187 | + |
| 188 | +``` |
| 189 | +34BEEF |
| 190 | +3^6 + 4^6 + B^6 + E^6 + E^6 + E^6 + F^6 |
| 191 | +2D9 + 1000 + 1B0829 + 72E440 + 72E440 + ADCEA1 |
| 192 | +1AEB223 |
| 193 | +
|
| 194 | +1AEB223 is greater than FFFFFF, so we happify again |
| 195 | +
|
| 196 | +1^6 + A^6 + E^6 + B^6 + 2^6 + 2^6 + 3^6 |
| 197 | +1 + F4240 + 72E440 + 1B0829 + 40 + 40 + 2D9 |
| 198 | +9D3203 |
| 199 | +``` |
| 200 | + |
| 201 | +So `34BEEF` happifies to `9D3203`, when happifying to the power of 6. |
| 202 | + |
| 203 | +As mentioned before the first attempt in this blog was the 2nd power tree, |
| 204 | +here's the trees for the 3rd, 4th, 5th, and 6th powers (each image is a link to |
| 205 | +a larger version): |
| 206 | + |
| 207 | +3rd power: |
| 208 | +[](/imgs/happy-tree/happy-tree-atmp3-pow3.png) |
| 209 | + |
| 210 | +4th power: |
| 211 | +[](/imgs/happy-tree/happy-tree-atmp3-pow4.png) |
| 212 | + |
| 213 | +5th power: |
| 214 | +[](/imgs/happy-tree/happy-tree-atmp3-pow5.png) |
| 215 | + |
| 216 | +6th power: |
| 217 | +[](/imgs/happy-tree/happy-tree-atmp3-pow6.png) |
| 218 | + |
| 219 | +A couple things to note: |
| 220 | + |
| 221 | +* 3-5 are still very blue. It's not till the 6th power that the distribution |
| 222 | + becomes random enough to become very colorful. |
| 223 | + |
| 224 | +* Some powers have more coils than others. Power of 3 has a lot, and actually a |
| 225 | + lot of them aren't coils, but single narcissistic numbers. Narcissistic |
| 226 | + numbers are those which happify to themselves. `000000` and `000001` are |
| 227 | + narcissistic numbers in all powers, power of 3 has quite a few more. |
| 228 | + |
| 229 | +* 4 looks super cool. |
| 230 | + |
| 231 | +Using unsigned 64-bit integers I could theoretically go up to the power of 15. |
| 232 | +But I hit a roadblock at power of 7, in that there's actually a melancoil which |
| 233 | +occurs whose members are all greater than `FFFFFF`. This means that my strategy |
| 234 | +of repeating happifying until I get under `FFFFFF` doesn't work for any numbers |
| 235 | +which lead into that coil. |
| 236 | + |
| 237 | + All images linked to in this post are licensed under the [Do what the fuck you |
| 238 | + want to public license](http://www.wtfpl.net/txt/copying/). |
0 commit comments