thzinc

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.

See also