Nayuki's personal site with programming projects, tutorials, and libraries, including a QR code generator and articles on algorithms and x86 assembly.
HN commenters recommend it warmly, citing its nice writing style, wide variety of projects, and the step-by-step QR code guide.
I use roamlikes as a combined bookmark / note-taking system.
I tend to spend a few minutes every day taking some interesting links from HN or elsewhere (that I may or may not read that day) and creating entries for them in my personal wiki system.
(This is how I keep track of collections of related links -- for my post above, I just searched for [[knowledge-graph]] tags in my wiki system and copied the results into an HN comment)
I find this most useful for topics that I know I'd like to explore in the future, but just don't have time for right now. The Google search signal-to-noise ratio has lessened so much that I know I'll never be able to find a specific link again unless I remember the exact title, so it's useful to have a way to quickly assign tags to a URL and forget about it until later. Tagging systems are much better than a hierarchical bookmark system for recall later [1].
Then, when I take the time to read about a certain topic, I start taking notes in the .md file corresponding to the appropriate keyword or citation.
The best part is discovering new connections between topics -- sometimes I'll type a [[keyword]] in my notes, and see that several of my existing notes already link to it.
I'm still learning how to best use a system like this, it does take some effort to maintain. Right now what works for me is really short, concise notes about very specific keywords to start. Then I'll do a "synthesis" pass where I'll summarize the relationships between…
Thanks!
Grabbing the sources from https://www.nayuki.io/page/fast-sha2-hashes-in-x86-assembly and compiling them more or less as recommended (and unlike they are compiled in the talk):
$ clang -O3 sha256-test.c sha256.c -o sha256-test ; for i in 1 2 3; do ./sha256-test ; done
Self-check passed
Speed: 197.2 MB/s
Self-check passed
Speed: 196.1 MB/s
Self-check passed
Speed: 196.1 MB/s
$ gcc -O3 sha256-test.c sha256.c -o sha256-test ; for i in 1 2 3; do ./sha256-test ; done
Self-check passed
Speed: 209.7 MB/s
Self-check passed
Speed: 209.2 MB/s
Self-check passed
Speed: 209.1 MB/s
This is a baseline for us. It has nothing to do with Zig and nothing to do with Andrew's machine (hardware or compiler versions).
But wait, the page above suggests that adding -march=native might help. Indeed it does:
$ clang -O3 -march=native sha256-test.c sha256.c -o sha256-test ; for i in 1 2 3; do ./sha256-test ; done
Self-check passed
Speed: 255.6 MB/s
Self-check passed
Speed: 259.0 MB/s
Self-check passed
Speed: 254.3 MB/s
$ gcc -O3 -march=native sha256-test.c sha256.c -o sha256-test ; for i in 1 2 3; do ./sha256-test ; done
Self-check passed
Speed: 275.1 MB/s
Self-check passed
Speed: 268.4 MB/s
Self-check passed
Speed: 270.0 MB/s
In the talk Andrew suggests that the difference might be due to using rorx instructions, which Zig might be able to do due to aggressive loop unrolling.…
> compile-time speed ups and potentially the use of the rorx instruction
Indeed, but the 'compile-time speedups' are a legitimate point in favour of the compiler. If they didn't occur to the assembly programmer, or struck them as too complex to pull off, then the compiler deserves the point.
Have to say I don't follow why the hand-tuned assembly doesn't use the rorx instruction. It's not mentioned in the assembly file, at least, but I thought that was the point? https://www.nayuki.io/page/fast-sha2-hashes-in-x86-assembly
Also, it's neat to see instruction-selection being so significant. Generally might expect cache/branch behaviour to be the kicker.
> It cannot be faster than the fastest assembly
Well, 'fastest assembly' is the domain of so-called 'superoptimisers', and has us pushing at the stubborn bounds of computability.
We were talking about hand-written assembly-code, compared to compiler-generated. Odds are that none of the binaries tested were the optimal assembly.
The only interesting question is whether the hand-tuned assembly code they tested, was the fastest available at the time. If not, the whole demonstration is a straw-man, of course.
Also I don't like that the winning Zig program runs for so much longer. A good benchmark should provide ironclad assurances that no candidate is getting an unfair advantage re. loading/'warm-up'.
Just thought this would be interesting to share.
The base64 encoding in JWT's forces the QR-code to use segments in byte-mode. This will encode individual JWT characters in 8 bits of data.
The size of the characterset of a base64-encoded JWT is 65 (64-characters in base64 + '.'). Actually, in this spec, it is 66, including the `|`.
An optimal encoding would use Log2(66) amount of bits per character. Alphanumeric mode at 5.5 bits per character is too small, but encoding individual JWT chars as 2 numeric characters (at 3 1/3 bits each) results in a more optimal encoding (~20% space savings).
The mapping from the JWT char to 2 numeric coding is also quite trivial: take the ascii value of the char and subtract by 43.
```
def enc(c):
return "%02d"%(ord(c) - 43)
```
The fantastic website
https://www.nayuki.io/page/creating-a-qr-code-step-by-step
shows, for the JWT you posted, a size of 2164 bits needed to encode the data inside the QR-code at low error-correction (resulting in a version 10 QR-code).
If we run every char through the numeric encoding process, we get the following result:…
No. In Mathematica important operations like mapping functions over sets (arrays/tensors) at various depths have simple operators such as (/@, @, @@, @@@). You can do functional composition using @*, etc. You don't need to define your variables and functions before being able to write them in expressions. Often you want to have intermediate terms that have some temporary name, and which get substituted later on. The replacement rules in Mathematica are very powerful for this.
As another example, I googled some project Euler solutions in Mathematica and (pure Python) and found this: https://www.nayuki.io/page/project-euler-solutions. Compared to the pure Python solutions, the Mathematica code is typically much smaller. Of course this is not Sympy, but a lot of the Python syntax carries over to SymPy as well.
A very vaguely related thing that might be useful to someone: in QR codes, using ALL-CAPS actually saves you data, making the QR code less "dense" and so easier to read at smaller sizes.
The trick is in the "alphanumeric" encoding mode of the QrR standard, which lets you encode 3 character per 11 bit (as opposed to 1 character per 8 bits) if you limit yourself to just numbers, uppercase letters and a few common URL symbols [0].
Besides making the code less dense, you can also add more error correction at the same density, making the code more resilient to wear, damage and reflections.
For more QR code trivia, see this excellent demo: https://www.nayuki.io/page/creating-a-qr-code-step-by-step
[0] https://www.thonky.com/qr-code-tutorial/alphanumeric-table