Split Int Into Even Parts

tags: [math, integer, division, remainder, modulo]

Divide an unknown integer into a given number of even parts — or at least as even as they can be, and the parts are returned as an array. The sum of the parts should be the original value, but each part should be an integer, and they should be as close as possible.

Examples:

spitInt(10, 1)
→ [10]

split(10, 3)
→ [3, 3, 4]

split(20, 6)
→ [3, 3, 3, 3, 4, 4]

There is some math stuff behind this, and it involves integer division and remainders (modulo division). Let’s consider splitting 20 into 6 parts.

20 % 6 = 2

(20 - 2) / 6
   18 / 6
     3

We then fill all six positions in the array with 3: [3, 3, 3, 3, 3, 3].

The remainder is 2, which means the last two positions need to be worked some more and cannot be simply left as 3, else the total sum is 18, not 20.

The first four positions are OK, though, and their sum is 12, which means the last two positions that have to be worked some more must sum to 8, since 12 + 8 would be 20, our initial number.

8 / 2 is 4. We fill the last two elements with 4.

split int even parts v1

TypeScript

Unit Tests

import { assertEquals } from "/deps.ts"
import { splitInt } from "./splitInt_v2.ts";

Deno.test("splitInt()", async (t) => {
  await t.step("should work for 10 and 1", () => {
    assertEquals(splitInt(10, 1), [10]);
  });

  await t.step("should work for 10 and 2", () => {
    assertEquals(splitInt(10, 2), [5, 5]);
  });

  await t.step("should work for 20 and 6", () => {
    assertEquals(splitInt(20, 6), [3, 3, 3, 3, 4, 4]);
  });

  await t.step("should work for 9 and 6", () => {
    assertEquals(splitInt(9, 6), [1, 1, 1, 2, 2, 2]);
  });
});

v1

/**
 * Divide an integer into n even parts (or as evenly as they can be).
 *
 * @param num The integer number to split.
 * @param parts The number of parts to split `num` into.
 * @returns
 */
function splitInt(num: number, parts: number): number[] {
  const rem = num % parts;
  const div = Math.floor(num / parts);

  const leftoverParts = (num - (parts - rem) * div) / rem;

  return new Array(parts).fill(div).fill(leftoverParts, parts - rem);
}

export { splitInt };

v2

/**
 * Divide an integer into n even parts (or as evenly as they can be).
 *
 * @param num The integer number to split.
 * @param parts The number of parts to split `num` into.
 * @returns
 */
function splitInt(num: number, parts: number): number[] {
  const rem: number = num % parts;
  const div: number = (num - rem) / parts;

  return new Array(parts).fill(div).fill(div + 1, parts - rem);
}

export { splitInt };

References