Javascript - top down, recursive, memoization, explanation
\n/** https://leetcode.com/problems/dice-roll-simulation/\n * @param {number} n\n * @param {number[]} rollMax\n * @return {number}\n */\nvar dieSimulator = func
```\n/** https://leetcode.com/problems/dice-roll-simulation/\n * @param {number} n\n * @param {number[]} rollMax\n * @return {number}\n */\nvar dieSimulator = function(n, rollMax) {\n  // Memo\n  this.memo = new Map();\n  \n  // Modulo\n  this.mod = (10 ** 9) + 7;\n  \n  // Keep track of roll count for each die\'s face (1-6)\n  let currRoll = Array(6).fill(0);\n  return dp(n, rollMax, n, currRoll) % this.mod;\n};\n\nvar dp = function(n, rollMax, nRemain, currRoll, previous = null) {\n  let key = `${nRemain}_${currRoll.toString()}`;\n  \n  // Base case\n  if (nRemain === 0) {\n    return 1;\n  }\n  \n  // Return from memo\n  if (this.memo.has(key) === true) {\n    return this.memo.get(key);\n  }\n  \n  let count = 0;\n  \n  // Try every face of the die, the face is the number on the die\n  // The face index in array is represented by `i`\n  // The face on the die (the number) is represented by `i + 1`\n  for (let i = 0; i < 6; i++) {\n    // Clone object we use for tracking the roll count for each die, by cloning we don\'t the next recursive won\'t change the value of current object\n    let cloneRoll = [...currRoll];\n    \n    // Increment the count of current face\n    cloneRoll[i] += 1;\n    \n    // This face of the die hit limit, ignore it\n    if (cloneRoll[i] > rollMax[i]) {\n      continue;\n    }\n    \n    // This face of the die is different that previous one, since the limit is only for consecutive count, it means the previous face\'s count should be reset\n    if (previous != null && i + 1 != previous) {\n      cloneRoll[previous - 1] = 0;\n    }\n    \n    // Count next recursive\n    count += dp(n, rollMax, nRemain - 1, cloneRoll, i + 1) % this.mod;\n  }\n\n  // Set memo\n  this.memo.set(key, count);\n  \n  return count;\n};\n```
['Recursion', 'Memoization', 'JavaScript']