m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2017-07-10 15:18:11 -0400
committerMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2017-07-10 15:18:45 -0400
commit7af1277c30d4942bd109e03c1991d81eb89b49fc (patch)
tree8c88f55fb90fa3f45f707295e76efb0ee54491ee
parentcbfed7099a748c586d984611e9b46ecc55ea3b68 (diff)
Implement dice subtraction
-rw-r--r--__tests__/dice.test.js45
-rw-r--r--src/dice.js13
2 files changed, 47 insertions, 11 deletions
diff --git a/__tests__/dice.test.js b/__tests__/dice.test.js
index 75fd06a..df945f8 100644
--- a/__tests__/dice.test.js
+++ b/__tests__/dice.test.js
@@ -1,4 +1,4 @@
-const { d, add } = require('../src/dice.js')
+const { d, add, subtract } = require('../src/dice.js')
const defaultNumberRolls = 500
const defaultError = 0.2
@@ -119,18 +119,21 @@ const testDie = (die, testSpecs, numberRolls = defaultNumberRolls) => {
}
}
-const basicDieTestSpecs = (number, sides) => {
+const basicDieTestSpecs = (number, sides, negative = false) => {
+ const multiplier = negative ? -1 : 1
+ const low = negative ? -(number * sides) : number
+ const high = negative ? -number : number * sides
return {
diceCount: number,
average: {
- average: (number * (sides + 1)) / 2
+ average: (number * (sides + 1)) / 2 * multiplier
},
variance: {
variance: (number * (sides * sides - 1)) / 12
},
bounds: {
- low: number,
- high: number * sides,
+ low: low,
+ high: high,
expectExtrema: number * sides < 50
}
}
@@ -138,7 +141,9 @@ const basicDieTestSpecs = (number, sides) => {
const combinedDiceTestSpecs = (dieSpecs) => {
const individualTestSpecs =
- dieSpecs.map(spec => (basicDieTestSpecs(spec.number, spec.sides)))
+ dieSpecs.map(spec => (
+ basicDieTestSpecs(spec.number, spec.sides, spec.negative)
+ ))
const combineSpecField = (fieldGetter) => {
return individualTestSpecs.reduce((total, spec) => {
@@ -158,7 +163,7 @@ const combinedDiceTestSpecs = (dieSpecs) => {
low: combineSpecField(spec => (spec.bounds.low)),
high: combineSpecField(spec => (spec.bounds.high)),
expectExtrema: dieSpecs.map(spec => (Math.pow(spec.sides, spec.number)))
- .reduce(times) < 50
+ .reduce(times) < 50
}
}
}
@@ -170,14 +175,20 @@ const describeBasicDie = (number, sides, numberRolls = defaultNumberRolls) => {
})
}
-const describeCompoundDice = (diceSpecs, numberRolls = defaultNumberRolls) => {
- const dieString = diceSpecs.reduce((string, spec, index) => (
+const getDieString = diceSpecs => (
+ diceSpecs.reduce((string, spec, index) => (
string + `${spec.number}d${spec.sides}` +
- (index < diceSpecs.length - 1 ? ' + ' : '')
+ (index < diceSpecs.length - 1 ?
+ (diceSpecs[index + 1].negative ? ' - ' : ' + ')
+ : '')
), '')
+)
+const describeCompoundDice = (diceSpecs, numberRolls = defaultNumberRolls) => {
+ const dieString = getDieString(diceSpecs)
const die = diceSpecs.slice(1).reduce((die, spec) => {
- return add(die, d(spec.number, spec.sides))
+ const combinator = spec.negative ? subtract : add
+ return combinator(die, d(spec.number, spec.sides))
}, d(diceSpecs[0].number, diceSpecs[0].sides))
describe(dieString, () => testDie(die, combinedDiceTestSpecs(diceSpecs),
@@ -198,3 +209,15 @@ describe('add', () => {
{ number: 1, sides: 1 }
])
})
+
+describe('subtract', () => {
+ describeCompoundDice([
+ { number: 1, sides: 6 },
+ { number: 1, sides: 4, negative: true }
+ ])
+ describeCompoundDice([
+ { number: 3, sides: 6 },
+ { number: 2, sides: 8, negative: true },
+ { number: 1, sides: 1, negative: true }
+ ])
+})
diff --git a/src/dice.js b/src/dice.js
index bc75cb7..c45bafc 100644
--- a/src/dice.js
+++ b/src/dice.js
@@ -16,10 +16,23 @@ const add = (die1, die2) => {
}
}
+const negative = (die) => {
+ return () => {
+ return die().map(value => -value)
+ }
+}
+
+const subtract = (die1, die2) => {
+ return () => {
+ return die1().concat(negative(die2)())
+ }
+}
+
const roll = (die) => {
return die().reduce((a, b) => (a + b))
}
exports.d = d
exports.add = add
+exports.subtract = subtract
exports.roll = roll