mmmPie - Interview question of the week from rendezvous with cassidoo
How can I write a piece of code that can be written quickly and trivially understood? I think it’s mostly good variable names in this case. (And I handle infinite pie!)
Interview question of the week
This week’s question: Given an array of people objects (where each person has a name and a number of pie pieces they’re hungry for) and a number for the number of pieces that the pie can be cut into, return the number of pies you need to buy.
Example:
> arr = [{ name: Joe, num: 9 }, { name: Cami, num: 3 }, { name: Cassidy, num: 4 }] > mmmPie(arr, 8) > 2 // 16 pieces needed, pies can be cut into 8 pieces, so 2 pies should be bought
My solution
Written as a stream of consciousness
Tonight, I’m going for minimal human effort to both write and read this code. The example employs a classic “word problem” feint: at no point is the name
relevant to the result of mmmPie()
.
As far as readability is concerned, I am going to suppress my inner urge to use .reduce()
and just write a for..of
loop instead.
With any division where the divisor is supplied by the implementer, I’m including a check for zero, as well as a check for negative numbers because we’re not dealing with imaginary pie. However, technically I will allow both real and negative slices needed (i.e., num
may be a fraction and also num
may be negative) because we’re treating the array of people
as an accounting of what is desired. I will add a check to ensure that the totalSlicesNeeded
is a positive number, because the result of this function should still be a value that is 0..infinity. (mmm… infinity pie…)
#mocha
function mmmPie(people, slicesPerPie) { if (slicesPerPie <= 0) return NaN; if (!isFinite(slicesPerPie)) return 1; let totalSlicesNeeded = 0; for (const { num: slicesNeeded } of people) { totalSlicesNeeded += slicesNeeded; } return Math.ceil(Math.max(totalSlicesNeeded, 0) / slicesPerPie); } mocha.setup("bdd"); const assert = chai.assert; const expect = chai.expect; const should = chai.should(); describe("Given the examples from the question", () => { const expectations = [ { input: [ [ { name: "Joe", num: 9 }, { name: "Cami", num: 3 }, { name: "Cassidy", num: 4 }, ], 8, ], output: 2, }, ]; expectations.forEach(({ input, output }) => { it(`should return ${output} for the input ${JSON.stringify(input)}`, () => { mmmPie(...input).should.equal(output); }); }); }); describe("Given additional examples", () => { const typicalPeople = [ { name: "Joe", num: 9 }, { name: "Cami", num: 3 }, { name: "Cassidy", num: 4 }, ]; it("should return NaN if the number of slices per pie is zero", () => { // Act const actual = mmmPie(typicalPeople, 0); // Assert isNaN(actual).should.be.true; }); it("should return NaN if the number of slices per pie is negative", () => { // Act const actual = mmmPie(typicalPeople, -1); // Assert isNaN(actual).should.be.true; }); it("should return 1 if the number of slices per pie is infinity", () => { // Act const actual = mmmPie(typicalPeople, Infinity); // Assert actual.should.equal(1); }); it("should return an integer when the slices per pie is a real number", () => { // Act const actual = mmmPie(typicalPeople, 8.5); // Assert actual.should.equal(2); }); it("should return an integer when the total of the slices needed is a real number", () => { // Arrange const realPeople = [ { name: "Joe", num: 9.1 }, { name: "Cami", num: 3.2 }, { name: "Cassidy", num: 4.3 }, ]; // Act const actual = mmmPie(realPeople, 8); // Assert actual.should.equal(3); }); it("should return the expected number of pies when the total slices needed adds up to a positive number", () => { // Arrange const accountants = [ { name: "Joe", num: -8 }, { name: "Cami", num: 9 }, { name: "Cassidy", num: 8 }, ]; // Act const actual = mmmPie(accountants, 8); // Assert actual.should.equal(2); }); it("should return zero when the total slices needed adds up to a negative number", () => { // Arrange const accountants = [ { name: "Joe", num: -8 }, { name: "Cami", num: 3 }, { name: "Cassidy", num: 2 }, ]; // Act const actual = mmmPie(accountants, 8); // Assert actual.should.equal(0); }); it("should return infinity when the total of the slices needed is infinity", () => { // Arrange const infinitePeople = [ { name: "Joe", num: Infinity }, { name: "Cami", num: 3 }, { name: "Cassidy", num: 4 }, ]; // Act const actual = mmmPie(infinitePeople, 8); // Assert actual.should.equal(Infinity); }); }); mocha.run();
Hah, after trying to assert my 0..infinity claim, I found that I’ll need an explicit check for when slicesPerPie
is infinity to return exactly one pie, which has infinity slices.