Live data from Hacker News

A neat XOR trick

mattkeeter.com

101–110 of 181 posts

Re: A neat XOR trick

#101
I had a very similar solution for my AoC in Toit, but I used a Deque instead of just having a trailing index into the input string. https://github.com/erikcorry/advent-of-code-2022/blob/main/d...

Then a friend solved it with regular expressions, but I found a sicker regex. After all, that's what regexes are about.

https://mobile.twitter.com/erikcorry/status/1600524753596456...

Re: A neat XOR trick

#102

One issue with this technique is when the set of characters grow above 64, so you can no longer give each one a unique bit. This could happen if we are instead interested in a window of unique words in a long document. Amazingly there is still a solution based on XOR! It is a variant of Bloom Filters, which I know everyone loves, but it uses XOR instead of OR to combine things. Basically each word is hashed to three…

>One issue with this technique is when the set of characters grow above 64, so you can no longer give each one a unique bit.

You can xor arrays of integers.

Re: A neat XOR trick

#103
post #90

One issue with this technique is when the set of characters grow above 64, so you can no longer give each one a unique bit. This could happen if we are instead interested in a window of unique words in a long document. Amazingly there is still a solution based on XOR! It is a variant of Bloom Filters, which I know everyone loves, but it uses XOR instead of OR to combine things. Basically each word is hashed to three…

This article’s technique can definitely expand into dynamically allocated bitsets.

In that case the complexity becomes O(N * A) where A is the size of the alphabet, since at every step you have to go through the whole bitset in order to count how many bits are set.

Edit - actually it should be possible to update the count incrementally, so it should still be O(N) I think.

Re: A neat XOR trick

#104
post #87

W cannot be larger than the size of the character set, so even the first algorithm runs in O(N) time. It's a cool trick, but it didn't make the algorithm asymptotically more efficient as the OP suggests.

You could imagine a much larger character set though. For example you might be interested in a sliding window of unique words instead.

Yes, but then the last algorithm runs in the same time as the one before it. Using xor here really only gives you a constant factor improvement (which is still nice!).

Reminds me of the problem “find the only missing number in a scrambled list of 1..n”. You can get an “O(n)” solution using xor, but once bit size becomes a concern, there are less hacky solutions that are just as fast.

Re: A neat XOR trick

#105
Isn't the real performance gained by eliminating the triple nested for loops and memoizing over a sliding window, rather than the use of XOR? You would get the same order-of-magnitude improvement if you used a map combined with iterate-only-once approach.

Ie, it's undeniable that the final program works much faster, but the article should really be called "a smarter memoization trick."

Re: A neat XOR trick

#106
I may be missing something, but isnt the obvious answer just to scan-and-compare 4 chars/time ? (Noting that != is XOR).

    int main(void) {

        char *c = 0, *data = "nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg";

        for (
            c = data; 
            !((c[1] != c[0]) &&
            ((c[2] != c[1]) && (c[2] != c[0])) &&
            ((c[3] != c[2]) && (c[3] != c[1]) && (c[3] != c[0])));
            c++
        );

        printf("%ld", c-data+4);
    }

Re: A neat XOR trick

#107

Earlier quoted context omitted.

Bit operations are fast, branches are slow.

Well, yes, but most of these branches can be if-converted into conditional moves anyway if you want. So they are data dependencies and not control ones. There are still some control ones. Beyond that, let me be super clear: Imagine the following six versions: 1. One window at a time processing. No early exit, no bit munging. 2. One window at a time processing. No early exit, bit munging. 3. One window at a time proce…

I don't think you are correct. Certainly not with a word size of 4. For very large word sizes, the early return will be a big win. But you are really under-rating how expensive the hashmap will be vs "bit munging".

You could roll your own perfect hash, but you would end up with a solution that looks almost identical to TFA. If you use a stdlib hash, you are going to be chasing pointers all over memory to do a single insert / lookup. De-referencing a single pointer not in cache costs 50 - 100 clock cycles on a modern system. By the time you do one insert, TFA will have XOR'd at least 32 chars into its bit mask. And your cache won't be as nice as in TFA, slowing you down even more.

Given the two scenarios: 1) bit munging, no early return 2) hash lookup, early return

I would guess scenario 1 wins until word size gets above ~256. And obviously, we can add an early return to scenario 1 to make it unquestionably the fastest.

Re: A neat XOR trick

#108

I may be missing something, but isnt the obvious answer just to scan-and-compare 4 chars/time ? (Noting that != is XOR). int main(void) { char *c = 0, *data = "nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg"; for ( c = data; !((c[1] != c[0]) && ((c[2] != c[1]) && (c[2] != c[0])) && ((c[3] != c[2]) && (c[3] != c[1]) && (c[3] != c[0]))); c++ ); printf("%ld", c-data+4); }

Sure, but now do 11 at a time with a similar algorithm (which was part 2 of the problem).

Re: A neat XOR trick

#109

One issue with this technique is when the set of characters grow above 64, so you can no longer give each one a unique bit. This could happen if we are instead interested in a window of unique words in a long document. Amazingly there is still a solution based on XOR! It is a variant of Bloom Filters, which I know everyone loves, but it uses XOR instead of OR to combine things. Basically each word is hashed to three…

>One issue with this technique is when the set of characters grow above 64, so you can no longer give each one a unique bit. You can xor arrays of integers.

Right, but if the universe of possible characters grow much larger than the window size (as it does in many applications), we want a method that only pays in terms of window size, not universe size.

Re: A neat XOR trick

#110

Something about seeing fun bit tricks solving higher level problems is exciting. As someone who writes higher level software in general using golang/rust/python to solve "boring business" problems, seeing someone using XORs to accomplish something feels like leaving my house and going camping for the weekend.

Right? Things like fast inverse square root feel like total black magic.
Post reply on HN