Storing patterns as numbers

General Hexcasting chattery.
(get it cause it's like the irc client hyuck hyuck)
User avatar
StickHexxing
Posts: 3
Joined: Sat Jun 15, 2024 7:09 pm

Storing patterns as numbers

Post by StickHexxing »

This idea started when I saw Object's Heap Storage, seen here. And I misunderstood heaps as a large Number Storage, (if that is what they are, please let me know), and that made me think if you could "compact" a Hex into numbers. After a bit of digging around with the Hex Addons, I found that you could use Hex Bound's Fragment's Purf,, and Winding Pruf to find the number of patterns in a pattern, and find the direction of a pattern; so mixing those 2, and some number shifting, you could turn a Hex into a number.

Likely the format would be StartingNumber BendNumber BendNumber... and so on. The main question is would it be worth it. I thought so since Hex stores its numbers as Doubles, or a max of 9007199254740992, but that is only about 15 bends in a single pattern let alone a full on Hex. I do still think the idea of storing Hexes as numbers would be cool, but number compression would need to be used, and sadly that is out of my knowledge level.
-Arco_Stickia was here
deaqqwwwqqaed
User avatar
Math321
Posts: 5
Joined: Fri Feb 17, 2023 12:25 am

Re: Storing patterns as numbers

Post by Math321 »

Random thoughts on this:

1. As you suggested, we can store the patterns as a list of "bend numbers". I'd make it something like:
A=1
Q=2
W=3
E=4
D=5
S=0
S is normally impossible in a pattern (since it would require an 180 degree bend), so we can use that to say "this pattern is finished, move on to the next one". This way, we can store multiple small patterns in a single number just as easily as we could store one large pattern.


2. Nature ignores the rotation of patterns, so we can too. We can just assume that the first line always points the same direction (east seems like a sensible default, but it doesn't matter much), and put an eastern-pointing line at the start of every new pattern. (If you REALLY want to support pattern rotation, I suppose the first "bend number" of each pattern could be used to represent which of the 6 directions the pattern is facing.)


3. You are correct that the maximum useful number a double can store for this purpose is 9007199254740992 (or 2^53), but I'm not sure how that translates to only 15 bends. From my math, 2^53 = a little over 6^20.5, so we could could store 20 bends per double as a base-6 number.


4. Even without any fancy addons, it's possible to store 3 numbers in a single iota - a vector. This brings us up to 60 bends per double, which could hold several small patterns or one of the largest ones. From a quick search, Craft Artifact is a 42-segment pattern, so it fits with room to spare. If there's anything larger in an addon, it's not coming to mind immediately. But even if someone wants to store a stupidly giant pattern (like the world's most convoluted Numerical Reflection), it wouldn't matter anyway, since we could use a list of vectors to store data if necessary.


5. If we allow ourselves to use addons, MoreIotas grants you access to matrices. The maximum size is configurable, but the default max size is 144x144. Each of those 20,736 cells can hold a double, so that'd be 414,720 bends. If that feels like cheating, you could also stuff 1,023 vector iotas into a focus (though reading a focus of that size may require some shenanigans with a single-execution Thoth, so you can drop your entire stack, read the focus, keep the vector(s) you want, then end the Thoth to get your original stack back). A focus with 1,023 vectors would have 3,069 doubles, or 61,380 bends. Not as good as a matrix, but still good enough to hold more patterns than a focus would normally be able to.


---

We could also take another tactic entirely - instead of storing raw pattern data, we could assign each pattern an ID number. Mind's Reflection could be ID #0, Compass' Purification could be ID #1, and so on.

If we assume we can use a max of 1,024 IDs (2^10, 10 bits), that means we can stuff 5 pattern IDs (50 bits) into each double with a few bits of room to spare. That outperforms the previous method by a fair bit, at the cost of needing to make a look-up table for all the patterns, and only being able to support patterns that are in the lookup table.

Of course, there's nothing stopping us from using the two systems together. This is useful in cases where we can't give a pattern a specific ID, like with Bookkeeper's Gambits or Numerical Reflections, or if you somehow have a modpack with more than 1,000 canonical patterns (base Hex has a bit under 200 by itself). We can store those special patterns using the bend-based method. We'll treat ID #1023 as a marker that means "go look in the bend-data, and grab the next custom pattern out of it". Similarly, ID #1022 can mean "stop treating doubles as ID numbers - every double after this should be read as bend-data".

I'm sure that someone with more brain cells than me could use Huffman coding (or some other compression algorithm) to turn the list of pattern IDs into some super-efficient string of binary, and encode that into doubles instead to give us _even more_ patterns per double. But even without that compression, 5 pattern IDs per double is still pretty dang efficient - that's 15,345 pattern IDs if we use a focus full of vector iotas, or 103,680 pattern IDs if we use a 144x144 MoreIotas matrix. In practice, we'd want to use some of those doubles to encode bend-data, but even then we'd still be storing quite a large number of patterns this way.

Unfortunately, this system would _only_ store patterns - many useful hexes contain embedded iotas too. We can solve this in a similar way to the bend-data problem: ID #1021 can mean "go grab the next iota from the list of embedded iotas, and put it here".

The whole data structure can be set up as a list of vectors or a matrix, followed by a list of embedded iotas afterwards.

We could also program other IDs with special behavior for common embed-types - for example, IDs #1020 and #1019 could indicate that the next ID number should be ignored, and treated as a positive or negative number embedded into the hex. ID #1018 could mean that the next 3 ID numbers should skipped and turned into a vector instead, subtracting 512 from each coordinate so we can support (small) positive and negative integers.

---

A project of this nature would be far more feasible in Minecraft 1.20, where the limit is "100,000 patterns evaluated total", instead of 1.19's limit of "512 meta-evaluations". You'd still run into 1.20's limit when you're dealing with very large blocks of compressed data, though. Depending on your addons (or lack thereof), you could use a wisp, a genie, a cassette, or (if all else fails) a circle that executes over and over. Give the hex access to a bunch of focuses to store everything (including a way of tracking its progress), and you're good to go.

...Much easier said than done, of course. A project like this would probably be a monumental headache to actually code, and I'm not willing to go through the trouble myself. If anyone else wants to take the idea and run with it, feel free.
hello world