JSFiddle - React, Tailwind, and code Playground

by Josh Pullen

HTML

To see the results, open this page on your computer and open the console by pressing Cmd + Option + J (on Mac) or Ctrl+Shift+J (on Windows).

JavaScript

const oneDie = [
	{ value: 1, waysToRoll: 1 },
  { value: 2, waysToRoll: 1 },
  { value: 3, waysToRoll: 1 },
  { value: 4, waysToRoll: 1 },
  { value: 5, waysToRoll: 1 },
  { value: 6, waysToRoll: 1 }
];

console.log("Set for one die: ", oneDie);

const twoDice = addSets(oneDie, oneDie);
console.log("Set for two dice: ", twoDice);

let turnSets = [
	[{ value: 0, waysToRoll: 1 }]
];
for (let i = 0; i < 11; i++) {
	turnSets.push(addSets(turnSets[i], twoDice));
}

console.log("List of sets for 0 turns -> 11 turns: ", turnSets);

// Get number of ways to hit target position (18, 20, or 21) during first 11 turns:
const hits = targetPosition => turnSets.reduce(
	(total, set) => {
		const targetItem = set.find(({ value }) => value === targetPosition);
  	if (!targetItem) return total + 0; // There are zero ways to roll 18 in this many turns
    return total + targetItem.waysToRoll;
  },
  0
);

for (let i = 1; i <= 133; i++) {
  console.log(`Number of ways to land on space ${i} in (up to) 11 turns: `, hits(i));
}

// Merge items in a set that have equal values by summing their "waysToRoll"
function mergeEqual(set) {
	return set.reduce((newSet, item) => {
  	const matchingValueIndex = newSet.findIndex(newItem => newItem.value === item.value);
    if (matchingValueIndex === -1) return [...newSet, item];
    
    return [
      ...newSet.slice(0, matchingValueIndex),
      { ...item, waysToRoll: newSet[matchingValueIndex].waysToRoll + item.waysToRoll },
      ...newSet.slice(matchingValueIndex + 1)
    ];
  }, []);
}

function addSets(setA, setB) {
	return mergeEqual(setA.flatMap(itemA => (
  	setB.map(itemB => ({
    	value: itemA.value + itemB.value,
      waysToRoll: itemA.waysToRoll * itemB.waysToRoll
    }))
  )));
}