Concepts
{"ScriptPreparationCode":"/*\r\n * These functions are related to the \u0022Concepts\u0022 section, and are unrelated to\r\n * the benchmark. Please find the \u0022Actual Benchmark\u0022 section under the\r\n * \u0022Concepts\u0022 section below. */\r\n\r\nfunction fixUI() {\r\n const iFrame = window.frameElement;\r\n if (iFrame) {\r\n console.log(iFrame.tagName);\r\n iFrame.style.width = \u0022100%\u0022;\r\n iFrame.style.minHeight = \u002250vh\u0022;\r\n }\r\n}\r\n\r\nfixUI();\r\n\r\nconst messageWidth = 40;\r\n\r\nfunction logValue(message, value) {\r\n const spanMessage = document.createElement(\u0022span\u0022);\r\n spanMessage.append(message);\r\n\r\n const spanSpace = document.createElement(\u0022span\u0022);\r\n if (message.length \u003C messageWidth) {\r\n spanSpace.append(\u0022 \u0022.repeat(messageWidth - message.length));\r\n }\r\n\r\n const spanSlashSlash = document.createElement(\u0022span\u0022);\r\n spanSlashSlash.append(\u0022// \u0022);\r\n\r\n const spanValue = document.createElement(\u0022span\u0022);\r\n spanValue.append(value);\r\n\r\n const divLine = document.createElement(\u0022div\u0022);\r\n divLine.style.fontFamily = \u0022monospace\u0022;\r\n divLine.style.whiteSpace = \u0022pre\u0022;\r\n divLine.append(spanMessage);\r\n divLine.append(spanSpace);\r\n divLine.append(spanSlashSlash);\r\n divLine.append(spanValue);\r\n\r\n const divLog = document.querySelector(\u0022div#log\u0022);\r\n divLog.appendChild(divLine);\r\n}\r\n\r\nfunction logMessage(message1, message2 = undefined) {\r\n const divLine = document.createElement(\u0022div\u0022);\r\n divLine.style.fontFamily = \u0022monospace\u0022;\r\n divLine.style.whiteSpace = \u0022pre\u0022;\r\n\r\n const spanMessage1 = document.createElement(\u0022span\u0022);\r\n spanMessage1.append(message1);\r\n divLine.append(spanMessage1);\r\n\r\n if (undefined !== message2) {\r\n if (message1.length \u003C messageWidth) {\r\n const spanSpace = document.createElement(\u0022span\u0022);\r\n spanSpace.append(\u0022 \u0022.repeat(messageWidth - message1.length));\r\n divLine.append(spanSpace);\r\n }\r\n\r\n const spanSlashSlash = document.createElement(\u0022span\u0022);\r\n spanSlashSlash.append(\u0022// \u0022);\r\n divLine.append(spanSlashSlash);\r\n\r\n const spanMessage2 = document.createElement(\u0022span\u0022);\r\n spanMessage2.append(message2);\r\n divLine.append(spanMessage2);\r\n }\r\n\r\n const divLog = document.querySelector(\u0022div#log\u0022);\r\n divLog.appendChild(divLine);\r\n}\r\n\r\nfunction logSeparator() {\r\n const divLine = document.createElement(\u0022div\u0022);\r\n divLine.style.fontFamily = \u0022monospace\u0022;\r\n divLine.style.whiteSpace = \u0022pre\u0022;\r\n divLine.append(\u0022-\u0022.repeat(80));\r\n\r\n const divLog = document.querySelector(\u0022div#log\u0022);\r\n divLog.appendChild(divLine);\r\n}\r\n\r\n// -----------------------------------------------------------------------------\r\n\r\n/* ******** *\r\n * Concepts *\r\n * ******** */\r\n\r\nlogMessage(\u0022Please make sure you understand these results before moving on\u0022);\r\nlogValue(\u0060[1,2].toString()\u0060, [1,2].toString()); // 1,2\r\nlogValue(\u0060[3,4].toString()\u0060, [3,4].toString()); // 3,4\r\nlogValue(\u0060{a:1,b:2}.toString()\u0060, {a:1,b:2}.toString()); // [object Object]\r\nlogValue(\u0060{a:3,b:4}.toString()\u0060, {a:3,b:4}.toString()); // [object Object]\r\nlogValue(\u0060[1,2] === [1,2]\u0060, [1,2] === [1,2]); // false\r\nlogValue(\u0060{a:1,b:2} === {a:1,b:2}\u0060, {a:1,b:2} === {a:1,b:2}); // false\r\nlogSeparator();\r\n\r\nlogMessage(\u0022These are keys for the following demonstrations\u0022);\r\nconst arr45 = [4, 5]; logMessage(\u0022const arr45 = [4,5];\u0022);\r\nconst obj89 = { a: 8, b: 9 }; logMessage(\u0022const obj89 = {a:8,b:9};\u0022);\r\nlogSeparator();\r\n\r\nlogMessage(\u0022Keys of an object are coerced into their string representations\u0022);\r\nconst m1 = {}; logMessage(\u0022const m1 = {};\u0022);\r\nm1[-1] = 0; logMessage(\u0022m1[-1] = 0;\u0022, \u0060m1[\u0022-1\u0022] = 0\u0060);\r\nm1[0] = 10; logMessage(\u0022m1[0] = 10;\u0022, \u0060m1[\u00220\u0022] = 10\u0060);\r\nm1[10] = 20; logMessage(\u0022m1[10] = 20;\u0022, \u0060m1[\u002210\u0022] = 20\u0060);\r\nm1[[2,3]] = 30; logMessage(\u0022m1[[2,3]] = 30;\u0022, \u0060m1[\u00222,3\u0022] = 30\u0060);\r\nm1[arr45] = 40; logMessage(\u0022m1[arr45] = 40;\u0022, \u0060m1[\u00224,5\u0022] = 40\u0060);\r\nm1[{a:6,b:7}] = 50; logMessage(\u0022m1[{a:6,b:7}] = 50;\u0022, \u0060m1[\u0022[object Object]\u0022] = 50\u0060);\r\nm1[obj89] = 60; logMessage(\u0022m1[obj89] = 60;\u0022, \u0060m1[\u0022[object Object]\u0022] = 60\u0060);\r\nlogValue(\u0060m1[-1]\u0060, m1[-1]); // 0\r\nlogValue(\u0060m1[\u0022-1\u0022]\u0060, m1[\u0022-1\u0022]); // 0\r\nlogValue(\u0060m1[0]\u0060, m1[0]); // 10\r\nlogValue(\u0060m1[\u00220\u0022]\u0060, m1[\u00220\u0022]); // 10\r\nlogValue(\u0060m1[10]\u0060, m1[10]); // 20\r\nlogValue(\u0060m1[\u002210\u0022]\u0060, m1[\u002210\u0022]); // 20\r\nlogValue(\u0060m1[[2,3]]\u0060, m1[[2,3]]); // 30\r\nlogValue(\u0060m1[\u00222,3\u0022]\u0060, m1[\u00222,3\u0022]); // 30\r\nlogValue(\u0060m1[[4,5]]\u0060, m1[[4,5]]); // 40\r\nlogValue(\u0060m1[arr45]\u0060, m1[arr45]); // 40\r\nlogValue(\u0060m1[\u00224,5\u0022]\u0060, m1[\u00224,5\u0022]); // 40\r\nlogValue(\u0060m1[{a:6,b:7}]\u0060, m1[{a:6,b:7}]); // 60\r\nlogValue(\u0060m1[{a:8,b:9}]\u0060, m1[{a:8,b:9}]); // 60\r\nlogValue(\u0060m1[obj89]\u0060, m1[obj89]); // 60\r\nlogValue(\u0060m1[\u0022[object Object]\u0022]\u0060, m1[\u0022[object Object]\u0022]); // 60\r\nlogValue(\u0060m1.length\u0060, m1.length); // undefined\r\nlogValue(\u0060m1.size\u0060, m1.size); // undefined\r\nlogSeparator();\r\n\r\nlogMessage(\u0022Keys of an array are coerced into their string representations\u0022);\r\nconst m2 = []; logMessage(\u0022const m2 = [];\u0022);\r\nm2[-1] = 0; logMessage(\u0022m2[-1] = 0;\u0022, \u0060m2[\u0022-1\u0022] = 0\u0060);\r\nm2[0] = 10; logMessage(\u0022m2[0] = 10;\u0022, \u0060m2[\u00220\u0022] = 10\u0060);\r\nm2[10] = 20; logMessage(\u0022m2[10] = 20;\u0022, \u0060m2[\u002210\u0022] = 20\u0060);\r\nm2[[2,3]] = 30; logMessage(\u0022m2[[2,3]] = 30;\u0022, \u0060m2[\u00222,3\u0022] = 30\u0060);\r\nm2[arr45] = 40; logMessage(\u0022m2[arr45] = 40;\u0022, \u0060m2[\u00224,5\u0022] = 40\u0060);\r\nm2[{a:6,b:7}] = 50; logMessage(\u0022m2[{a:6,b:7}] = 50;\u0022, \u0060m2[\u0022[object Object]\u0022] = 50\u0060);\r\nm2[obj89] = 60; logMessage(\u0022m2[obj89] = 60;\u0022, \u0060m2[\u0022[object Object]\u0022] = 60\u0060);\r\nlogValue(\u0060m2[-1]\u0060, m2[-1]); // 0\r\nlogValue(\u0060m2[\u0022-1\u0022]\u0060, m2[\u0022-1\u0022]); // 0\r\nlogValue(\u0060m2[0]\u0060, m2[0]); // 10\r\nlogValue(\u0060m2[\u00220\u0022]\u0060, m2[\u00220\u0022]); // 10\r\nlogValue(\u0060m2[10]\u0060, m2[10]); // 20\r\nlogValue(\u0060m2[\u002210\u0022]\u0060, m2[\u002210\u0022]); // 20\r\nlogValue(\u0060m2[[2,3]]\u0060, m2[[2,3]]); // 30\r\nlogValue(\u0060m2[\u00222,3\u0022]\u0060, m2[\u00222,3\u0022]); // 30\r\nlogValue(\u0060m2[[4,5]]\u0060, m2[[4,5]]); // 40\r\nlogValue(\u0060m2[arr45]\u0060, m2[arr45]); // 40\r\nlogValue(\u0060m2[\u00224,5\u0022]\u0060, m2[\u00224,5\u0022]); // 40\r\nlogValue(\u0060m2[{a:6,b:7}]\u0060, m2[{a:6,b:7}]); // 60\r\nlogValue(\u0060m2[{a:8,b:9}]\u0060, m2[{a:8,b:9}]); // 60\r\nlogValue(\u0060m2[obj89]\u0060, m2[obj89]); // 60\r\nlogValue(\u0060m2[\u0022[object Object]\u0022]\u0060, m2[\u0022[object Object]\u0022]); // 60\r\nlogValue(\u0060m2.length\u0060, m2.length); // 11\r\nlogValue(\u0060m2.size\u0060, m2.size); // undefined\r\nlogSeparator();\r\n\r\n/* Keys of a Map are NOT coerced into their string representations */\r\n/* When retrieving a value from a Map, the key is compared by reference */\r\nconst m3 = new Map(); logMessage(\u0022const m3 = new Map();\u0022);\r\nm3.set(-1, 0); logMessage(\u0022m3.set(-1, 0);\u0022);\r\nm3.set(0, 10); logMessage(\u0022m3.set(0, 10);\u0022);\r\nm3.set(10, 20); logMessage(\u0022m3.set(10, 20);\u0022);\r\nm3.set([2,3], 30); logMessage(\u0022m3.set([2,3], 30);\u0022);\r\nm3.set(arr45, 40); logMessage(\u0022m3.set(arr45, 40);\u0022);\r\nm3.set({a:6,b:7}, 50); logMessage(\u0022m3.set({a:6,b:7}, 50);\u0022);\r\nm3.set(obj89, 60); logMessage(\u0022m3.set(obj89, 60);\u0022);\r\nlogValue(\u0060m3.get(-1)\u0060, m3.get(-1)); // 0\r\nlogValue(\u0060m3.get(\u0022-1\u0022)\u0060, m3.get(\u0022-1\u0022)); // undefined\r\nlogValue(\u0060m3.get(0)\u0060, m3.get(0)); // 10\r\nlogValue(\u0060m3.get(\u00220\u0022)\u0060, m3.get(\u00220\u0022)); // undefined\r\nlogValue(\u0060m3.get(10)\u0060, m3.get(10)); // 20\r\nlogValue(\u0060m3.get(\u002210\u0022)\u0060, m3.get(\u002210\u0022)); // undefined\r\nlogValue(\u0060m3.get([2, 3])\u0060, m3.get([2, 3])); // undefined\r\nlogValue(\u0060m3.get(\u00222,3\u0022)\u0060, m3.get(\u00222,3\u0022)); // undefined\r\nlogValue(\u0060m3.get([4, 5])\u0060, m3.get([4, 5])); // undefined\r\nlogValue(\u0060m3.get(arr45)\u0060, m3.get(arr45)); // 40\r\nlogValue(\u0060m3.get(\u00224,5\u0022)\u0060, m3.get(\u00224,5\u0022)); // undefined\r\nlogValue(\u0060m3.get({a:6,b:7})\u0060, m3.get({a:6,b:7})); // undefined\r\nlogValue(\u0060m3.get({a:8,b:9})\u0060, m3.get({a:8,b:9})); // undefined\r\nlogValue(\u0060m3.get(obj89)\u0060, m3.get(obj89)); // 60\r\nlogValue(\u0060m3.get(\u0022[object Object]\u0022)\u0060, m3.get(\u0022[object Object]\u0022)); // undefined\r\nlogValue(\u0060m3.length\u0060, m3.length); // undefined\r\nlogValue(\u0060m3.size\u0060, m3.size); // 7\r\nlogSeparator();\r\n\r\n// -----------------------------------------------------------------------------\r\n\r\n/* *************************** *\r\n * Actual Benchmark: Interface *\r\n * *************************** */\r\n\r\n/**\r\n * Conceptually equivalent to a dictionary mapping a pair (K1, K2) to V.\r\n * @template K1 The type of the 1st value of the key pair.\r\n * @template K2 The type of the 2nd value of the key pair.\r\n * @template V The type of the element associated with the specified key pair.\r\n */\r\nclass Cache {\r\n /**\r\n * Returns a specified element from the Cache object. If the value that is\r\n * associated to the provided key pair is an object, then you will get a\r\n * reference to that object and any change made to that object will\r\n * effectively modify it inside the Cache.\r\n * \r\n * @param {K1} key1 The 1st value of the key pair.\r\n * @param {K2} key2 The 2nd value of the key pair.\r\n * @returns {V | undefined} Returns the element associated with the specified\r\n * key pair. If no element is associated with the specified key pair,\r\n * undefined is returned.\r\n */\r\n get(key1, key2) {\r\n }\r\n\r\n /**\r\n * Adds a new element with a specified key pair and value to the Cache.\r\n * If an element with the same key pair already exists, the element will be\r\n * updated.\r\n * \r\n * @param {K1} key1 The 1st value of the key pair.\r\n * @param {K2} key2 The 2nd value of the key pair.\r\n * @param {V} value The element associated with the specified key pair.\r\n * @returns {Cache\u003CK1, K2, V\u003E} Returns this Cache object.\r\n */\r\n set(key1, key2, value) {\r\n return this;\r\n }\r\n}\r\n\r\n\r\n// -----------------------------------------------------------------------------\r\n\r\n/* ********************************** *\r\n * Actual Benchmark: Implementation 1 *\r\n * ********************************** */\r\n\r\n/**\r\n * @augments {Cache\u003CK1, K2, V\u003E}\r\n */\r\nclass TwoLevelMapDict {\r\n constructor() {\r\n /** @type {Map\u003CK1, Map\u003CK2, V\u003E\u003E} */\r\n this.map = new Map();\r\n }\r\n\r\n get(key1, key2) {\r\n const map2 = this.map.get(key1);\r\n if (undefined === map2) {\r\n return undefined;\r\n }\r\n return map2.get(key2);\r\n }\r\n\r\n set(key1, key2, value) {\r\n let map2 = this.map.get(key1);\r\n if (undefined === map2) {\r\n map2 = new Map();\r\n map2.set(key2, value);\r\n this.map.set(key1, map2);\r\n } else {\r\n map2.set(key2, value);\r\n }\r\n return this;\r\n }\r\n}\r\n\r\n// -----------------------------------------------------------------------------\r\n\r\n/* ********************************** *\r\n * Actual Benchmark: Implementation 2 *\r\n * ********************************** */\r\n\r\n/**\r\n * @augments {Cache\u003CK1, K2, V\u003E}\r\n */\r\nclass TwoLevelArrayDict {\r\n constructor() {\r\n /** @type {V[][]} */\r\n this.map = [];\r\n }\r\n\r\n get(key1, key2) {\r\n const map2 = this.map[key1];\r\n if (undefined === map2) {\r\n return undefined;\r\n }\r\n return map2[key2];\r\n }\r\n\r\n set(key1, key2, value) {\r\n let map2 = this.map[key1];\r\n if (undefined === map2) {\r\n map2 = [];\r\n map2[key2] = value;\r\n this.map[key1] = map2;\r\n } else {\r\n map2[key2] = value;\r\n }\r\n return this;\r\n }\r\n}\r\n\r\n// -----------------------------------------------------------------------------\r\n\r\n/* ********************************** *\r\n * Actual Benchmark: Implementation 3 *\r\n * ********************************** */\r\n\r\n/**\r\n * @augments {Cache\u003CK1, K2, V\u003E}\r\n */\r\nclass TwoLevelObjectDict {\r\n constructor() {\r\n /** @type {Object.\u003CK1, Object.\u003CK2, V\u003E\u003E} */\r\n this.map = {};\r\n }\r\n\r\n get(key1, key2) {\r\n const map2 = this.map[key1];\r\n if (undefined === map2) {\r\n return undefined;\r\n }\r\n return map2[key2];\r\n }\r\n\r\n set(key1, key2, value) {\r\n let map2 = this.map[key1];\r\n if (undefined === map2) {\r\n map2 = {\r\n key2: value\r\n };\r\n this.map[key1] = map2;\r\n } else {\r\n map2[key2] = value;\r\n }\r\n return this;\r\n }\r\n}\r\n\r\n// -----------------------------------------------------------------------------\r\n\r\n/* ********************************** *\r\n * Actual Benchmark: Implementation 4 *\r\n * ********************************** */\r\n\r\n/**\r\n * @augments {Cache\u003CK1, K2, V\u003E}\r\n */\r\nclass OneLevelArrayDict {\r\n constructor() {\r\n /** @type {V[]} */\r\n this.map = [];\r\n }\r\n\r\n get(key1, key2) {\r\n return this.map[[key1, key2]];\r\n }\r\n\r\n set(key1, key2, value) {\r\n this.map[[key1, key2]] = value;\r\n return this;\r\n }\r\n}\r\n\r\n// -----------------------------------------------------------------------------\r\n\r\n/* ********************************** *\r\n * Actual Benchmark: Implementation 5 *\r\n * ********************************** */\r\n\r\n/**\r\n * @augments {Cache\u003CK1, K2, V\u003E}\r\n */\r\nclass OneLevelObjectDict {\r\n constructor() {\r\n /** @type {Object.\u003C[K1, K2], V\u003E} */\r\n this.map = {};\r\n }\r\n\r\n get(key1, key2) {\r\n return this.map[[key1, key2]];\r\n }\r\n\r\n set(key1, key2, value) {\r\n this.map[[key1, key2]] = value;\r\n return this;\r\n }\r\n}\r\n\r\n// -----------------------------------------------------------------------------\r\n\r\n/* *************************** *\r\n * Actual Benchmark: Algorithm *\r\n * *************************** */\r\n\r\n/**\r\n * Returns the number of distinct ways that the integer {@link n} could be\r\n * written as a sum of integers in {@link sortedChoices}[0] (inclusive) to\r\n * {@link sortedChoices}[{@link k}] (inclusive). Each integer in\r\n * {@link sortedChoices} could be used zero or more times.\r\n * @param {number} n The integer.\r\n * @param {number} k The maximum index in {@link sortedChoices} allowed to be used.\r\n * @param {number[]} sortedChoices The integer array of choices, sorted in ascending order.\r\n * @param {Cache\u003Cnumber, number, number} cache The result cache.\r\n * @returns {number} The number of distinct ways descibed above.\r\n */\r\nfunction countWaysToSumImpl(n, k, sortedChoices, cache) {\r\n let count = cache.get(n, k);\r\n if (undefined === count) {\r\n const newN = n - sortedChoices[k];\r\n // NOTE: The (newN \u003C 0) branch should be unreachable.\r\n if (newN == 0) {\r\n count = 1;\r\n } else {\r\n count = 0;\r\n for (let i = 0; i \u003C= k \u0026\u0026 newN \u003E= sortedChoices[i]; \u002B\u002Bi) {\r\n count \u002B= countWaysToSumImpl(newN, i, sortedChoices, cache);\r\n }\r\n }\r\n cache.set(n, k, count);\r\n }\r\n return count;\r\n}\r\n\r\n/**\r\n * Returns the number of distinct ways that the integer {@link n} could be\r\n * written as a sum of integers in {@link choices}. Each integer in\r\n * {@link choices} could be used zero or more times.\r\n * @param {number} n The non-negative integer.\r\n * @param {number[]} choices The array of postive integer choices.\r\n * @param {Cache\u003Cnumber, number, number} cache The result cache.\r\n * @returns {number} The number of distinct ways descibed above.\r\n */\r\nfunction countWaysToSum(n, choices, cache) {\r\n // NOTE: If compareFn is ommited, the default one sorts the elements as string.\r\n const sortedChoices = [...choices];\r\n sortedChoices.sort((a, b) =\u003E a - b);\r\n let count = 0;\r\n for (let i = 0; i \u003C sortedChoices.length \u0026\u0026 n \u003E= sortedChoices[i]; \u002B\u002Bi) {\r\n count \u002B= countWaysToSumImpl(n, i, sortedChoices, cache);\r\n }\r\n return count;\r\n}\r\n\r\n// -----------------------------------------------------------------------------\r\n\r\n/* *************************** *\r\n * Actual Benchmark: Test Case *\r\n * *************************** */\r\n\r\nfunction randomInt(low, high) {\r\n if (high \u003C low) {\r\n throw new Error(\u0060high (${high}) is smaller than low (${low})\u0060);\r\n }\r\n return Math.trunc(Math.random() * (high - low \u002B 1)) \u002B low;\r\n}\r\n\r\nfunction randomIntArray(lengthLow, lengthHigh, low, high) {\r\n if (lengthHigh \u003C lengthLow) {\r\n throw new Error(\u0060lengthHigh (${lengthHigh}) is smaller than lengthLow (${lengthLow})\u0060);\r\n }\r\n if (high \u003C low) {\r\n throw new Error(\u0060high (${high}) is smaller than low (${low})\u0060);\r\n }\r\n const length = randomInt(lengthLow, lengthHigh);\r\n const array = new Array(length);\r\n for (let i = 0; i \u003C length; \u002B\u002Bi) {\r\n array[i] = randomInt(low, high);\r\n }\r\n return array;\r\n}\r\n\r\nfunction randomIntArrayWithUniqueElements(lengthLow, lengthHigh, low, high) {\r\n if (lengthHigh \u003C lengthLow) {\r\n throw new Error(\u0060lengthHigh (${lengthHigh}) is smaller than lengthLow (${lengthLow})\u0060);\r\n }\r\n if (high \u003C low) {\r\n throw new Error(\u0060high (${high}) is smaller than low (${low})\u0060);\r\n }\r\n const numberCount = high - low \u002B 1;\r\n if (lengthLow \u003E numberCount) {\r\n throw new Error(\u0060lengthLow (${lengthLow}) to high for range (${low} to ${high})\u0060);\r\n }\r\n if (lengthHigh \u003E numberCount) {\r\n lengthHigh = numberCount;\r\n }\r\n const size = randomInt(lengthLow, lengthHigh);\r\n const set = new Set();\r\n while (size !== set.size) {\r\n set.add(randomInt(low, high));\r\n }\r\n return [...set];\r\n}\r\n\r\nconst n = randomInt(10, 1000);\r\nconst choices = randomIntArrayWithUniqueElements(1, n - 1, 1, n - 1);","TestCases":[{"Name":"2-Level Map (Map\u003CK1, Map\u003CK2, V\u003E\u003E)","Code":"countWaysToSum(n, choices, new TwoLevelMapDict());","IsDeferred":false},{"Name":"2-Level Array (V[][])","Code":"countWaysToSum(n, choices, new TwoLevelArrayDict());","IsDeferred":false},{"Name":"2-Level Object (Object.\u003CK1, Object.\u003CK2, V\u003E\u003E)","Code":"countWaysToSum(n, choices, new TwoLevelObjectDict());","IsDeferred":false},{"Name":"1-Level Array (V[])","Code":"countWaysToSum(n, choices, new OneLevelArrayDict());","IsDeferred":false},{"Name":"1-Level Object (Object.\u003C[K1, K2], V\u003E)","Code":"countWaysToSum(n, choices, new OneLevelObjectDict());","IsDeferred":false}]}