This was inspired by @frncsdrk's submission from earlier today [0]. The generative concepts used were inspired by and derived from dweets from @KilledByAPixel and @FireFly [1] [2] [3]
The concept is to use HN usernames as the seed into a deterministic avatar generator. This generator is built from the famously simple xorshift32 PRNG, which both provides a random variable for the image generator steps, and "pseudo-hashes" the seed string to provide the initial PRNG state using a non-linear step (adding each codepoint - which is likely not very robust against collisions compared to proper hashing algorithms, but is simple and good enough).
The image generation part is a probability distribution with mirrored pixels... specifically: r>>>29 > X*X/3+Y/2 where the left side is 3 of the upper bits of the PRNG state (providing a random integer 0-7), and the right side is the squared distance from the centre for X + the linear distance from the top for Y. i.e the further from the top centre the pixel is, the less likely it will be filled, but linearly for Y and squared for X.
Un-golfed version:
for (const u of document.querySelectorAll('.hnuser')) {
const p=2;
const c=document.createElement('canvas');
const x=c.getContext('2d');
c.width=p*7, c.height=p*7;
u.parentElement.prepend(c);
for (let s=u.innerText, r=1, i=28+s.length; i--;) {
// xorshift32
r^=r<<13, r^=r>>>17, r^=r<<5;
const X=i&3, Y=i>>2;
if (i >= 28) {
// seed state
r+=s.charCodeAt(i-28);
x.fillStyle='#'+(r>>8&0xFFFFFF)
.toString(16).padStart(0, 6);
} else {
// draw pixel
if (r>>>29 > X*X/3+Y/2)
x.fillRect(p*3+p*X, p*Y, p, p),
x.fillRect(p*3-p*X, p*Y, p, p);
}
}
}
Was fun to play with, but also surprisingly helpful in following discussions.
It's worth mentioning these were heavily inspired by three particular dweets by @KilledByAPixel and @FireFly:
There's actually a slight difference between the golfed and un-golfed version: the un-golfed adds the avatar to the beginning of the line with the username, whereas the golfed version adds it right next to the username. I actually find it to be more visually appealing at the beginning of the line, so I'm sticking with that in my Greasemonkey script.
To anyone interested, I've added links to how the un-golfed version looks with Dark Reader enabled[1] and how it looks without Dark Reader[2]. To clarify, I've set my zoom level for Hacker News to 150% as I find the default to not be conducive to reading.
Your minified version lacks the .padStart(0, 6) you have in this comment, without which colour selection fails in just under 1⁄16 of cases, yielding black. (Or in just under 1⁄256 of cases, a semi-transparent colour!)
Thanks, I know it's absent (it's golfed not minified), which means I manually manipulated it to make as small as possible which sometimes means making "concessions" where things are not ideally preserved - But in retrospect you're probably right, I was being too aggressive and should have either left the padding in or replaced it with some guarantee of formatting length length like "&FFF|0x111"
Yeah! he's done a deep dive into it more recently. Attempting to follow his twitter thread at the moment is like trying to consume a fire-hydrant of generative art :D hard to keep up, but looks amazing.
The concept is to use HN usernames as the seed into a deterministic avatar generator. This generator is built from the famously simple xorshift32 PRNG, which both provides a random variable for the image generator steps, and "pseudo-hashes" the seed string to provide the initial PRNG state using a non-linear step (adding each codepoint - which is likely not very robust against collisions compared to proper hashing algorithms, but is simple and good enough).
The image generation part is a probability distribution with mirrored pixels... specifically: r>>>29 > X*X/3+Y/2 where the left side is 3 of the upper bits of the PRNG state (providing a random integer 0-7), and the right side is the squared distance from the centre for X + the linear distance from the top for Y. i.e the further from the top centre the pixel is, the less likely it will be filled, but linearly for Y and squared for X.
Un-golfed version:
Was fun to play with, but also surprisingly helpful in following discussions.It's worth mentioning these were heavily inspired by three particular dweets by @KilledByAPixel and @FireFly:
[1] https://www.dwitter.net/d/3078
[2] https://www.dwitter.net/d/19786
[3] https://www.dwitter.net/d/23326
[0] https://news.ycombinator.com/item?id=30660316