v7.8 — share strings 2.0: big-base packing cuts them to ~28% of the script (was ~51%)

The user asked for more compression 'by any means possible', suggesting
base-62 numbers and dictionary phrases. Both ideas shipped — cranked up:

- Dictionary grew ~170 data-mined entries: every function WITH its open
  paren (sin(, if(, megabuf(, …), every engine variable (vol_att, time,
  bpm, sv, …), AVS idioms ("hue = hue + dt * ", "t = t + dt * ", " * 0.",
  ") * ", "(0."), header lines ("linewidth: ", "blend: additive",
  "mode: lines"), blank-line+section skeletons ("\n\n[point]\n"), CRLF
  statement ends, ~70 number literals, and the library's common variable
  names (ring, spokes, chroma, segs, …) — all mined by frequency over the
  101-preset embedded corpus with a greedy-cover scorer.
- New scheme ▼ 'big-base packing': the dictionary output is read as ONE
  BIG NUMBER over its own alphabet and rewritten in base 32,164 — one
  digit per character from CJK Unified + Hangul. ~15 bits/char vs
  base-62's 5.95 ("1400" costs ~0.85 chars). The body's alphabet rides
  in a ~32-char bitmap header (dict-symbol bitmap + ASCII bitmap + raw
  non-ASCII tail) instead of ~80 literal symbols.
- Pair-packing kept as the fallback for short scripts (encoder picks
  whichever body is shorter); ▲ strings from v7.7 still decode via the
  kept legacy tables; still lossless for ANY text (verified: 101-preset
  corpus + 21 edge cases incl. CRLF, Hangul/CJK literals, lone
  surrogates, platform-injected zero-widths), still copy-safe, still
  self-checking (8 FNV check digits).
- Base packing gated at 16K symbols (O(n²) BigInt); encode 1.1 ms on the
  largest preset. Decode input capped at 40K chars.

Corpus measure: 64854 → 18026 chars = 72.2% reduction (v7.7: 49.1%);
median share string 26.9% of source, best 21.9%. Bass Bloom: 1341 → 326.
Browser-verified: encode→copy→paste→decode→load round-trip through the
dialogs for both ▼ and legacy ▲ strings, What's New 7.8 entry, mobile +
desktop layout, sticky footer.
This commit is contained in:
Z User 2026-10-29 10:49:56 +00:00
parent 80782609b2
commit 698fc1c2a3
4 changed files with 897 additions and 167 deletions

View file

@ -1,4 +1,4 @@
// AVA — Script ⇢ Hash share dialogs (v7.7).
// AVA — Script ⇢ Hash share dialogs (v7.8).
//
// Two dialogs used by the Script tab toolbar:
// • ScriptToHashDialog — encodes the current editor script into ONE
@ -126,11 +126,13 @@ export function ScriptToHashDialog({
</div>
<p className="rounded-md border border-zinc-800 bg-zinc-900/40 px-2.5 py-2 text-[11px] leading-relaxed text-zinc-400">
Built-in references keep it short:{' '}
Short scripts spell themselves in built-in references (
<span className="font-mono text-zinc-300">
{SHARE_LEGEND.map((l) => `${l.symbol} = ${l.meaning}`).join(' · ')}
</span>
. The string works even if the script doesn&apos;t compile — perfect for asking for
) — longer ones additionally pack ~15 bits of script into every
character, which is why they read as dense CJK. Either way the string
works even if the script doesn&apos;t compile — perfect for asking for
help or sharing work in progress.
</p>
</div>
@ -248,7 +250,7 @@ export function HashToScriptDialog({
setInput(e.target.value)
setError(null)
}}
placeholder={'My Script:[▲…]'}
placeholder={'My Script:[▼…]'}
aria-label="Paste a share string here"
rows={5}
spellCheck={false}

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,24 @@ export interface ReleaseNote {
}
export const RELEASE_NOTES: ReleaseNote[] = [
{
version: '7.8',
name: 'Share strings, supersized',
changes: [
{
kind: 'improved',
text: 'Script⇢Hash strings are now ~72% shorter than the script (was ~49%) — the median share string is about a QUARTER of the script’s length. “1400” now costs less than one character: the whole script is packed into CJK + Hangul digits carrying ~15 bits apiece (your base-62 idea, with 32,164 digits instead of 62).',
},
{
kind: 'improved',
text: 'The symbol dictionary grew ~170 data-mined entries — every function with its open paren, every audio variable, AVS idioms like “hue = hue + dt * ”, header lines like “linewidth: ”, and ~70 number literals.',
},
{
kind: 'added',
text: 'Share strings from v7.7 (the ▲ ones) still paste back perfectly — and short scripts keep the readable symbol form, since the encoder always picks whichever is shorter.',
},
],
},
{
version: '7.7',
name: 'Share scripts as one string',

View file

@ -12,6 +12,24 @@
// warns in the console when the two drift apart.
//
// History:
// 7.8 — share strings 2.0: ~72% shorter than the script (was ~49%). The
// base-62 idea, cranked to 11,172… 32,164: after the symbol
// dictionary (which grew ~170 data-mined entries — every function
// WITH its open paren, every engine variable, the AVS idioms
// "hue = hue + dt * " and "t = t + dt * ", " * 0.", ") * ",
// blank-line+section skeletons, "linewidth: " / "blend: additive"
// headers, ~70 number literals, and the library's common
// variable names incl. chroma) the whole body is read as ONE BIG
// NUMBER and rewritten in base 32,164 — one digit per character
// from the CJK + Hangul blocks, ~15 bits a character vs base-62's
// 5.95 (so "1400" costs ~0.85 of a character). The decoder gets
// the body's alphabet back from a ~32-character bitmap header
// instead of ~80 literal symbols. Short scripts where the header
// wouldn't pay keep the v7.7 symbol form (encoder picks whichever
// is shorter); ▲ strings from v7.7 still decode; still lossless
// for ANY text, still copy-safe, still self-checking. Corpus
// measure: median share string is 27% of the script's length
// (best 22%), e.g. Bass Bloom 1341 → 326 characters
// 7.7 — script sharing + settings declutter. Script⇢Hash / Hash⇢Script:
// two buttons in the Script tab turn the editor's script into ONE
// short shareable Unicode string ("Bass Bloom:[▲…①①①①①①①①]") and
@ -242,4 +260,4 @@
export const APP_NAME = 'Open Visualization Engine'
export const APP_SHORT = 'OVE'
export const APP_VERSION = '7.7'
export const APP_VERSION = '7.8'