Last active
November 23, 2025 23:54
-
-
Save qntm/e8e7591960ed8b26b7b2eaec5ebce709 to your computer and use it in GitHub Desktop.
How many valid JSON strings are there?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| Code for enumerating valid JSON strings. | |
| Bounds checking is the responsibility of the caller. | |
| The case N = 0 is intentionally not handled. | |
| This code attempts to be somewhat readable without significantly impacting performance. | |
| https://qntm.org/jsoncount | |
| https://qntm.org/jsonutf8 | |
| */ | |
| import assert from 'node:assert/strict' | |
| // First some constants | |
| const NUM_DIGITS = BigInt(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].length) | |
| const NUM_1_BYTE_CHARS = (0x7Fn + 1n) - 0x0020n - BigInt(['\\', '"'].length) // 94 | |
| const NUM_2_BYTE_CHARS = (0x7FFn + 1n) - 0x80n // 1920 | |
| const NUM_3_BYTE_CHARS = (0xFFFFn + 1n) - 0x800n // 63488 | |
| const NUM_4_BYTE_CHARS = (0x10FFFFn + 1n) - 0x10000n // 1048576 | |
| const NUM_ESCAPES = BigInt(['"', '\\', '/', 'b', 'f', 'n', 'r', 't'].length) // 8 | |
| const NUM_HEX_CHARS = BigInt([ | |
| '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | |
| 'A', 'B', 'C', 'D', 'E', 'F', | |
| 'a', 'b', 'c', 'd', 'e', 'f' | |
| ].length) // 22, not 16 | |
| const NUM_HEX_ESCAPES = NUM_HEX_CHARS ** 4n // 234,256, not 65,536 | |
| const NUM_ES = BigInt(['E', 'e'].length) // 2 | |
| const NUM_SIGNS = BigInt(['-', '+'].length) // 2 | |
| // Memoization is incredibly important as the numbers get larger, | |
| // there are many combinations | |
| const memoize = f => { | |
| const known = [] | |
| return n => known[n] ??= f(n) | |
| } | |
| // Now for some enumeration. | |
| // Use BigInts throughout because we're going to be exceeding `Number.MAX_SAFE_INTEGER` at N = 5 | |
| class Counter { | |
| #numWs | |
| #encoding | |
| constructor (allowWs, encoding) { | |
| this.#numWs = allowWs | |
| ? BigInt(['\u0020', '\u000A', '\u000D', '\u0009'].length) // 4 | |
| : 0n | |
| this.#encoding = encoding | |
| } | |
| // E.g. "123" | |
| // [1-9][0-9]* | |
| countPositiveIntegers (n) { | |
| return (NUM_DIGITS - 1n) * NUM_DIGITS ** BigInt(n - 1) | |
| } | |
| // E.g. "123.456" | |
| // 0.[0-9]{3} | |
| // [1-9].[0-9][0-9][0-9], [1-9][0-9].[0-9][0-9], [1-9][0-9][0-9].[0-9] | |
| countDecimals (n) { | |
| return NUM_DIGITS ** BigInt(n - 2) + | |
| (NUM_DIGITS - 1n) * NUM_DIGITS ** BigInt(n - 2) * BigInt(n - 2) | |
| } | |
| // E.g. "123e456" | |
| // 0[eE][0-9][0-9][0-9] | |
| // [1-9][eE][0-9][0-9][0-9], [1-9][0-9][eE][0-9][0-9], [1-9][0-9][0-9][eE][0-9] | |
| countExponents (n) { | |
| return NUM_ES * NUM_DIGITS ** BigInt(n - 2) + | |
| (NUM_DIGITS - 1n) * NUM_ES * NUM_DIGITS ** BigInt(n - 2) * BigInt(n - 2) | |
| } | |
| // E.g. "123e+456" | |
| // 0[eE][+-][0-9][0-9][0-9] | |
| // [1-9][eE][+-][0-9][0-9][0-9], [1-9][0-9][eE][+-][0-9][0-9], [1-9][0-9][0-9][eE][+-][0-9] | |
| countSignedExponents (n) { | |
| return NUM_ES * NUM_SIGNS * NUM_DIGITS ** BigInt(n - 3) + | |
| (NUM_DIGITS - 1n) * NUM_ES * NUM_SIGNS * NUM_DIGITS ** BigInt(n - 3) * BigInt(n - 3) | |
| } | |
| // E.g. "123.456e789" | |
| // 0.[0-9][eE][0-9], 1 combination | |
| // [1-9].[0-9][eE][0-9], 1 combination | |
| // 0.[0-9][eE][0-9][0-9], 0.[0-9][0-9][eE][0-9], 2 combinations | |
| // [1-9].[0-9][eE][0-9][0-9], [1-9].[0-9][0-9][eE][0-9], [1-9][0-9].[0-9][eE][0-9], 3 combinations | |
| countDecimalExponents (n) { | |
| return NUM_ES * NUM_DIGITS ** BigInt(n - 3) * BigInt(n - 4) + | |
| (NUM_DIGITS - 1n) * NUM_ES * NUM_DIGITS ** BigInt(n - 3) * (BigInt(n - 4) * BigInt(n - 3) / 2n) | |
| } | |
| // E.g. "123.456E-789" | |
| // 0.[0-9][eE][+-][0-9] | |
| // [1-9].[0-9][eE][+-][0-9] | |
| countDecimalSignedExponents (n) { | |
| return NUM_ES * NUM_SIGNS * NUM_DIGITS ** BigInt(n - 4) * BigInt(n - 5) + | |
| (NUM_DIGITS - 1n) * NUM_ES * NUM_SIGNS * NUM_DIGITS ** BigInt(n - 4) * (BigInt(n - 5) * BigInt(n - 4) / 2n) | |
| } | |
| countNonNegativeNumbers (n) { | |
| let l = 0n | |
| if (n === 1) { | |
| l += 1n // "0" | |
| } | |
| l += this.countPositiveIntegers(n) | |
| if (n >= 3) { | |
| l += this.countDecimals(n) | |
| l += this.countExponents(n) | |
| } | |
| if (n >= 4) { | |
| l += this.countSignedExponents(n) | |
| } | |
| if (n >= 5) { | |
| l += this.countDecimalExponents(n) | |
| } | |
| if (n >= 6) { | |
| l += this.countDecimalSignedExponents(n) | |
| } | |
| return l | |
| } | |
| countNegativeNumbers (n) { | |
| return this.countNonNegativeNumbers(n - 1) | |
| } | |
| countNumbers (n) { | |
| let l = 0n | |
| l += this.countNonNegativeNumbers(n) | |
| if (n >= 2) { | |
| l += this.countNegativeNumbers(n) | |
| } | |
| return l | |
| } | |
| // Highly recursive, memoization is crucial here | |
| countStringInteriors = memoize(n => { | |
| if (n === 0) { | |
| return 1n | |
| } | |
| let l = 0n | |
| if (this.#encoding === 'utf32') { | |
| if (n >= 1) { | |
| l += this.countStringInteriors(n - 1) * (NUM_1_BYTE_CHARS + NUM_2_BYTE_CHARS + NUM_3_BYTE_CHARS + NUM_4_BYTE_CHARS) | |
| } | |
| } else if (this.#encoding === 'utf16') { | |
| if (n >= 1) { | |
| l += this.countStringInteriors(n - 1) * (NUM_1_BYTE_CHARS + NUM_2_BYTE_CHARS + NUM_3_BYTE_CHARS) | |
| } | |
| if (n >= 2) { | |
| l += this.countStringInteriors(n - 2) * NUM_4_BYTE_CHARS | |
| } | |
| } else if (this.#encoding === 'utf8') { | |
| if (n >= 1) { | |
| l += this.countStringInteriors(n - 1) * NUM_1_BYTE_CHARS | |
| } | |
| if (n >= 2) { | |
| l += this.countStringInteriors(n - 2) * NUM_2_BYTE_CHARS | |
| } | |
| if (n >= 3) { | |
| l += this.countStringInteriors(n - 3) * NUM_3_BYTE_CHARS | |
| } | |
| if (n >= 4) { | |
| l += this.countStringInteriors(n - 4) * NUM_4_BYTE_CHARS | |
| } | |
| } else { | |
| throw Error('bad encoding') | |
| } | |
| if (n >= 2) { | |
| l += this.countStringInteriors(n - 2) * NUM_ESCAPES | |
| } | |
| if (n >= 6) { | |
| l += this.countStringInteriors(n - 6) * NUM_HEX_ESCAPES | |
| } | |
| return l | |
| }) | |
| countStrings (n) { | |
| return this.countStringInteriors(n - 2) | |
| } | |
| countArrayInteriorsK = memoize(k => { | |
| if (k === 0) { | |
| return n => this.#numWs ** BigInt(n) | |
| } | |
| if (k === 1) { | |
| return n => this.countElements(n) | |
| } | |
| return memoize(n => { | |
| // Try every possible location for the comma after the first element | |
| let l = 0n | |
| for (let i = 1; (k - 1) * 2 - 1 <= n - (i + 1); i++) { | |
| l += this.countElements(i) * this.countArrayInteriorsK(k - 1)(n - (i + 1)) | |
| } | |
| return l | |
| }) | |
| }) | |
| countArrayInteriors = memoize(n => { | |
| // Try every possible number of array elements | |
| let l = 0n | |
| for (let k = 0; k * 2 - 1 <= n; k++) { | |
| l += this.countArrayInteriorsK(k)(n) | |
| } | |
| return l | |
| }) | |
| countArrays (n) { | |
| return this.countArrayInteriors(n - 2) | |
| } | |
| // A key is a whitespaced string | |
| countKeys = memoize(n => { | |
| // Try every possible size of key | |
| let l = 0n | |
| for (let w = 0; w < n; w++) { | |
| l += this.countStrings(n - w) * this.#numWs ** BigInt(w) * BigInt(w + 1) | |
| } | |
| return l | |
| }) | |
| countMembers = memoize(n => { | |
| // Try every possible location for the colon between the key and value | |
| let l = 0n | |
| for (let i = 2; i + 1 < n; i++) { | |
| l += this.countKeys(i) * this.countElements(n - (i + 1)) | |
| } | |
| return l | |
| }) | |
| countObjectInteriorsK = memoize(k => { | |
| if (k === 0) { | |
| return n => this.#numWs ** BigInt(n) | |
| } | |
| if (k === 1) { | |
| return n => this.countMembers(n) | |
| } | |
| return memoize(n => { | |
| // Try every possible location for the comma after the first key and value | |
| let l = 0n | |
| for (let i = 4; (k - 1) * 5 - 1 <= n - (i + 1); i++) { | |
| l += this.countMembers(i) * this.countObjectInteriorsK(k - 1)(n - (i + 1)) | |
| } | |
| return l | |
| }) | |
| }) | |
| countObjectInteriors = memoize(n => { | |
| // Try every possible number of key-value pairs | |
| let l = 0n | |
| for (let k = 0; 5 * k - 1 <= n; k++) { | |
| l += this.countObjectInteriorsK(k)(n) | |
| } | |
| return l | |
| }) | |
| countObjects (n) { | |
| return this.countObjectInteriors(n - 2) | |
| } | |
| countValues = memoize(n => { | |
| let l = 0n | |
| if (n === 4) { | |
| l += 2n // "null", "true" | |
| } | |
| if (n === 5) { | |
| l += 1n // "false" | |
| } | |
| if (n >= 1) { | |
| l += this.countNumbers(n) | |
| } | |
| if (n >= 2) { | |
| l += this.countStrings(n) | |
| l += this.countArrays(n) | |
| l += this.countObjects(n) | |
| } | |
| return l | |
| }) | |
| countElements = memoize(n => { | |
| // Try every possible size of value | |
| let l = 0n | |
| for (let w = 0; w < n; w++) { | |
| l += this.countValues(n - w) * this.#numWs ** BigInt(w) * BigInt(w + 1) | |
| } | |
| return l | |
| }) | |
| } | |
| const counter32 = new Counter(true, 'utf32') | |
| const counter32NoWs = new Counter(false, 'utf32') | |
| const counter16 = new Counter(true, 'utf16') | |
| const counter8 = new Counter(true, 'utf8') | |
| assert.equal(counter32.countPositiveIntegers(1), 9n) | |
| assert.equal(counter32.countPositiveIntegers(2), 90n) | |
| assert.equal(counter32.countPositiveIntegers(3), 900n) | |
| assert.equal(counter32.countPositiveIntegers(4), 9000n) | |
| assert.equal(counter32.countDecimals(3), 100n) | |
| assert.equal(counter32.countDecimals(4), 1900n) | |
| assert.equal(counter32.countDecimals(5), 28000n) | |
| assert.equal(counter32.countDecimals(6), 370000n) | |
| assert.equal(counter32.countExponents(3), 200n) | |
| assert.equal(counter32.countExponents(4), 3800n) | |
| assert.equal(counter32.countExponents(5), 56000n) | |
| assert.equal(counter32.countExponents(6), 740000n) | |
| assert.equal(counter32.countSignedExponents(4), 400n) | |
| assert.equal(counter32.countSignedExponents(5), 7600n) | |
| assert.equal(counter32.countSignedExponents(6), 112000n) | |
| assert.equal(counter32.countSignedExponents(7), 1480000n) | |
| assert.equal(counter32.countDecimalExponents(5), 2000n) | |
| assert.equal(counter32.countDecimalExponents(6), 58000n) | |
| assert.equal(counter32.countDecimalExponents(7), 1140000n) | |
| assert.equal(counter32.countDecimalExponents(8), 18800000n) | |
| assert.equal(counter32.countDecimalSignedExponents(6), 4000n) | |
| assert.equal(counter32.countDecimalSignedExponents(7), 116000n) | |
| assert.equal(counter32.countDecimalSignedExponents(8), 2280000n) | |
| assert.equal(counter32.countDecimalSignedExponents(9), 37600000n) | |
| assert.equal(counter32.countNumbers(1), 10n) | |
| assert.equal(counter32.countNumbers(2), 100n) | |
| assert.equal(counter32.countNumbers(3), 1290n) | |
| assert.equal(counter32.countNumbers(4), 16300n) | |
| assert.equal(counter32.countNumbers(5), 198700n) | |
| assert.equal(counter32.countNumbers(6), 2367600n) | |
| assert.equal(counter32.countStringInteriors(0), 1n) | |
| assert.equal(counter32.countStringInteriors(1), 1114078n) | |
| assert.equal(counter32.countStringInteriors(2), 1241169790092n) | |
| assert.equal(counter32.countStringInteriors(3), 1382759957415027800n) | |
| assert.equal(counter32.countStrings(2), 1n) | |
| assert.equal(counter32.countStrings(3), 1114078n) | |
| assert.equal(counter32.countStrings(4), 1241169790092n) | |
| assert.equal(counter32.countStrings(4), 1114078n * 1114078n + 8n) | |
| assert.equal(counter32.countArrayInteriorsK(0)(0), 1n) | |
| assert.equal(counter32.countArrayInteriorsK(0)(1), 4n) | |
| assert.equal(counter32.countArrayInteriorsK(1)(1), 10n) | |
| assert.equal(counter32.countArrayInteriorsK(0)(2), 16n) | |
| assert.equal(counter32.countArrayInteriorsK(1)(2), 183n) | |
| assert.equal(counter32.countArrayInteriorsK(0)(3), 64n) | |
| assert.equal(counter32.countArrayInteriorsK(1)(3), 1116690n) | |
| assert.equal(counter32.countArrayInteriorsK(2)(3), 100n) | |
| assert.equal(counter32.countArrayInteriorsK(0)(4), 256n) | |
| assert.equal(counter32.countArrayInteriorsK(1)(4), 1241178737201n) | |
| assert.equal(counter32.countArrayInteriorsK(2)(4), 3660n) // 183 * 10 + 10 * 183 | |
| assert.equal(counter32.countArrayInteriorsK(0)(5), 1024n) | |
| assert.equal(counter32.countArrayInteriorsK(1)(5), 1382769886828373987n) | |
| assert.equal(counter32.countArrayInteriorsK(2)(5), 22367289n) | |
| assert.equal(counter32.countArrayInteriorsK(3)(5), 1000n) | |
| assert.equal(counter32.countArrayInteriorsK(20)(39), 100000000000000000000n) | |
| assert.equal(counter32.countArrayInteriors(0), 1n) | |
| assert.equal(counter32.countArrayInteriors(1), 14n) | |
| assert.equal(counter32.countArrayInteriors(2), 199n) | |
| assert.equal(counter32.countArrayInteriors(3), 1116854n) | |
| assert.equal(counter32.countArrayInteriors(4), 1241178741117n) | |
| assert.equal(counter32.countArrayInteriors(5), 1382769886850743300n) | |
| assert.equal(counter32.countArrays(2), 1n) | |
| assert.equal(counter32.countArrays(3), 14n) | |
| assert.equal(counter32.countArrays(4), 199n) | |
| assert.equal(counter32.countArrays(5), 1116854n) | |
| assert.equal(counter32.countArrays(6), 1241178741117n) | |
| assert.equal(counter32.countArrays(7), 1382769886850743300n) | |
| assert.equal(counter32.countKeys(2), 1n) | |
| assert.equal(counter32.countKeys(3), 1114086n) | |
| assert.equal(counter32.countKeys(4), 1241178702764n) | |
| assert.equal(counter32.countObjectInteriorsK(0)(0), 1n) | |
| assert.equal(counter32.countObjectInteriorsK(0)(1), 4n) | |
| assert.equal(counter32.countObjectInteriorsK(0)(2), 16n) | |
| assert.equal(counter32.countObjectInteriorsK(0)(3), 64n) | |
| assert.equal(counter32.countObjectInteriorsK(0)(4), 256n) | |
| assert.equal(counter32.countObjectInteriorsK(1)(4), 10n) // '{"":0}' through '{"":9}' | |
| assert.equal(counter32.countObjectInteriorsK(0)(5), 1024n) | |
| assert.equal(counter32.countObjectInteriorsK(1)(5), 11141043n) // 1114086 * 10 + 1 * 183 | |
| assert.equal(counter32.countObjectInteriors(0), 1n) | |
| assert.equal(counter32.countObjectInteriors(1), 4n) | |
| assert.equal(counter32.countObjectInteriors(2), 16n) | |
| assert.equal(counter32.countObjectInteriors(3), 64n) | |
| assert.equal(counter32.countObjectInteriors(4), 266n) | |
| assert.equal(counter32.countObjectInteriors(5), 11142067n) | |
| assert.equal(counter32.countObjects(2), 1n) | |
| assert.equal(counter32.countObjects(3), 4n) | |
| assert.equal(counter32.countObjects(4), 16n) | |
| assert.equal(counter32.countObjects(5), 64n) | |
| assert.equal(counter32.countObjects(6), 266n) | |
| assert.equal(counter32.countObjects(7), 11142067n) | |
| assert.equal(counter32.countValues(1), 10n) // 10 numbers | |
| assert.equal(counter32.countValues(2), 103n) // 100 numbers, 1 string, 1 array, 1 object | |
| assert.equal(counter32.countValues(3), 1115386n) // 1290 numbers, 1114078 strings, 14 arrays, 4 objects | |
| assert.equal(counter32.countValues(4), 1241169806609n) // 1 null, 1 true, 16300 numbers, 1241169790092 strings, 199 arrays, 16 objects | |
| assert.equal(counter32.countValues(5), 1382759957416343419n) // 1 false, 198700 numbers, 1382759957415027800 strings, 1116854 arrays, 64 objects | |
| assert.equal(counter32.countElements(1), 10n) | |
| assert.equal(counter32.countElements(2), 183n) | |
| assert.equal(counter32.countElements(3), 1116690n) | |
| assert.equal(counter32.countElements(4), 1241178737201n) | |
| assert.equal(counter32.countElements(5), 1382769886828373987n) | |
| assert.equal(counter32NoWs.countPositiveIntegers(1), 9n) | |
| assert.equal(counter32NoWs.countPositiveIntegers(2), 90n) | |
| assert.equal(counter32NoWs.countPositiveIntegers(3), 900n) | |
| assert.equal(counter32NoWs.countPositiveIntegers(4), 9000n) | |
| assert.equal(counter32NoWs.countDecimals(3), 100n) | |
| assert.equal(counter32NoWs.countDecimals(4), 1900n) | |
| assert.equal(counter32NoWs.countDecimals(5), 28000n) | |
| assert.equal(counter32NoWs.countDecimals(6), 370000n) | |
| assert.equal(counter32NoWs.countExponents(3), 200n) | |
| assert.equal(counter32NoWs.countExponents(4), 3800n) | |
| assert.equal(counter32NoWs.countExponents(5), 56000n) | |
| assert.equal(counter32NoWs.countExponents(6), 740000n) | |
| assert.equal(counter32NoWs.countSignedExponents(4), 400n) | |
| assert.equal(counter32NoWs.countSignedExponents(5), 7600n) | |
| assert.equal(counter32NoWs.countSignedExponents(6), 112000n) | |
| assert.equal(counter32NoWs.countSignedExponents(7), 1480000n) | |
| assert.equal(counter32NoWs.countDecimalExponents(5), 2000n) | |
| assert.equal(counter32NoWs.countDecimalExponents(6), 58000n) | |
| assert.equal(counter32NoWs.countDecimalExponents(7), 1140000n) | |
| assert.equal(counter32NoWs.countDecimalExponents(8), 18800000n) | |
| assert.equal(counter32NoWs.countDecimalSignedExponents(6), 4000n) | |
| assert.equal(counter32NoWs.countDecimalSignedExponents(7), 116000n) | |
| assert.equal(counter32NoWs.countDecimalSignedExponents(8), 2280000n) | |
| assert.equal(counter32NoWs.countDecimalSignedExponents(9), 37600000n) | |
| assert.equal(counter32NoWs.countNumbers(1), 10n) | |
| assert.equal(counter32NoWs.countNumbers(2), 100n) | |
| assert.equal(counter32NoWs.countNumbers(3), 1290n) | |
| assert.equal(counter32NoWs.countNumbers(4), 16300n) | |
| assert.equal(counter32NoWs.countNumbers(5), 198700n) | |
| assert.equal(counter32NoWs.countNumbers(6), 2367600n) | |
| assert.equal(counter32NoWs.countStringInteriors(0), 1n) | |
| assert.equal(counter32NoWs.countStringInteriors(1), 1114078n) | |
| assert.equal(counter32NoWs.countStringInteriors(2), 1241169790092n) | |
| assert.equal(counter32NoWs.countStringInteriors(3), 1382759957415027800n) | |
| assert.equal(counter32NoWs.countStrings(2), 1n) | |
| assert.equal(counter32NoWs.countStrings(3), 1114078n) | |
| assert.equal(counter32NoWs.countStrings(4), 1241169790092n) | |
| assert.equal(counter32NoWs.countStrings(4), 1114078n * 1114078n + 8n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(0)(0), 1n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(0)(1), 0n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(1)(1), 10n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(0)(2), 0n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(1)(2), 103n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(0)(3), 0n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(1)(3), 1115378n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(2)(3), 100n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(0)(4), 0n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(1)(4), 1241169806497n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(2)(4), 2060n) // 103n * 10n + 10n * 103n | |
| assert.equal(counter32NoWs.countArrayInteriorsK(0)(5), 0n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(1)(5), 1382759957416341979n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(2)(5), 22318169n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(3)(5), 1000n) | |
| assert.equal(counter32NoWs.countArrayInteriorsK(20)(39), 100000000000000000000n) | |
| assert.equal(counter32NoWs.countArrayInteriors(0), 1n) | |
| assert.equal(counter32NoWs.countArrayInteriors(1), 10n) | |
| assert.equal(counter32NoWs.countArrayInteriors(2), 103n) | |
| assert.equal(counter32NoWs.countArrayInteriors(3), 1115478n) | |
| assert.equal(counter32NoWs.countArrayInteriors(4), 1241169808557n) | |
| assert.equal(counter32NoWs.countArrayInteriors(5), 1382759957438661148n) | |
| assert.equal(counter32NoWs.countArrays(2), 1n) | |
| assert.equal(counter32NoWs.countArrays(3), 10n) | |
| assert.equal(counter32NoWs.countArrays(4), 103n) | |
| assert.equal(counter32NoWs.countArrays(5), 1115478n) | |
| assert.equal(counter32NoWs.countArrays(6), 1241169808557n) | |
| assert.equal(counter32NoWs.countArrays(7), 1382759957438661148n) | |
| assert.equal(counter32NoWs.countKeys(2), 1n) | |
| assert.equal(counter32NoWs.countKeys(3), 1114078n) | |
| assert.equal(counter32NoWs.countKeys(4), 1241169790092n) | |
| assert.equal(counter32NoWs.countObjectInteriorsK(0)(0), 1n) | |
| assert.equal(counter32NoWs.countObjectInteriorsK(0)(1), 0n) | |
| assert.equal(counter32NoWs.countObjectInteriorsK(0)(2), 0n) | |
| assert.equal(counter32NoWs.countObjectInteriorsK(0)(3), 0n) | |
| assert.equal(counter32NoWs.countObjectInteriorsK(0)(4), 0n) | |
| assert.equal(counter32NoWs.countObjectInteriorsK(1)(4), 10n) // '{"":0}' through '{"":9}' | |
| assert.equal(counter32NoWs.countObjectInteriorsK(0)(5), 0n) | |
| assert.equal(counter32NoWs.countObjectInteriorsK(1)(5), 11140883n) // 1114078 * 10 + 1 * 103 | |
| assert.equal(counter32NoWs.countObjectInteriors(0), 1n) | |
| assert.equal(counter32NoWs.countObjectInteriors(1), 0n) | |
| assert.equal(counter32NoWs.countObjectInteriors(2), 0n) | |
| assert.equal(counter32NoWs.countObjectInteriors(3), 0n) | |
| assert.equal(counter32NoWs.countObjectInteriors(4), 10n) | |
| assert.equal(counter32NoWs.countObjectInteriors(5), 11140883n) | |
| assert.equal(counter32NoWs.countObjects(2), 1n) | |
| assert.equal(counter32NoWs.countObjects(3), 0n) | |
| assert.equal(counter32NoWs.countObjects(4), 0n) | |
| assert.equal(counter32NoWs.countObjects(5), 0n) | |
| assert.equal(counter32NoWs.countObjects(6), 10n) | |
| assert.equal(counter32NoWs.countObjects(7), 11140883n) | |
| assert.equal(counter32NoWs.countValues(1), 10n) // 10 numbers | |
| assert.equal(counter32NoWs.countValues(2), 103n) // 100 numbers, 1 string, 1 array, 1 object | |
| assert.equal(counter32NoWs.countValues(3), 1115378n) // 1290 numbers, 1114078 strings, 10 arrays | |
| assert.equal(counter32NoWs.countValues(4), 1241169806497n) // 1 null, 1 true, 16300 numbers, 1241169790092 strings, 103 arrays | |
| assert.equal(counter32NoWs.countValues(5), 1382759957416341979n) // 1 false, 198700 numbers, 1382759957415027800 strings, 1115478 arrays | |
| assert.equal(counter32NoWs.countElements(1), 10n) | |
| assert.equal(counter32NoWs.countElements(2), 103n) | |
| assert.equal(counter32NoWs.countElements(3), 1115378n) | |
| assert.equal(counter32NoWs.countElements(4), 1241169806497n) | |
| assert.equal(counter32NoWs.countElements(5), 1382759957416341979n) | |
| assert.equal(counter16.countStringInteriors(0), 1n) | |
| assert.equal(counter16.countStringInteriors(1), 65502n) | |
| assert.equal(counter16.countStringInteriors(2), 4291560588n) // 1048584 * 1 + 65502 * 65502 | |
| assert.equal(counter16.countStringInteriors(3), 281174485984344n) // 1048584 * 65502 + 65502 * 4291560588 | |
| assert.equal(counter8.countStringInteriors(0), 1n) | |
| assert.equal(counter8.countStringInteriors(1), 94n) | |
| assert.equal(counter8.countStringInteriors(2), 10764n) // 94 * 94 + 1928 | |
| assert.equal(counter8.countStringInteriors(3), 1256536n) // 94 * 10764 + 1928 * 94 + 63488 | |
| assert.equal(counter8.countStringInteriors(4), 145883824n) | |
| for (let n = 1; n <= 100; n++) { | |
| console.log(n, counter8.countElements(n)) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment