Partition N where the count of parts and each part are a power of 2, and part size and count are restricted in JavaScript

We need to write a JavaScript function that partitions a number into chunks following specific rules:

  • The number of chunks must be a power of 2 (1, 2, 4, 8, 16, etc.)

  • Each chunk size must also be a power of 2, with a maximum limit

Understanding the Problem

Let's examine how different numbers can be partitioned:

For number 8:

[8]

This works because we have 1 chunk (power of 2) with size 8 (power of 2).

For number 9:

[8, 1]

This works because we have 2 chunks (power of 2), each with power-of-2 sizes.

For number 11, let's try different approaches:

[8, 2, 1]

This doesn't work because we have 3 chunks, and 3 is not a power of 2.

[4, 4, 2, 1]

This works because we have 4 chunks (power of 2), each with power-of-2 sizes.

Algorithm Implementation

The function uses bit manipulation and greedy partitioning to find valid combinations:

function partitionNumber(n, maximum) {
    const maxPowerOf2 = 1 << maximum;
    const m = Math.floor(n / maxPowerOf2);
    const A = new Array(maximum + 1).fill(0);
    A[maximum] = m;
    
    let num = n - m * maxPowerOf2;
    let p = 0;
    let bitCount = 0;
    
    // Process remaining bits
    while (num) {
        if (num & 1) {
            bitCount += 1;
            A[p] = 1;
        }
        num >>= 1;
        p += 1;
    }
    
    const min = m + bitCount;
    let target = 1;
    
    // Find the smallest power of 2 >= min
    while (target < min) {
        target *= 2;
    }
    
    if (target > n) return -1;
    if (target == min) return A.map((c, p) => [1 << Number(p), c]);
    if (target == n) return [[n, 1]];
    
    target = target - min;
    let i = m ? maximum : p;
    
    // Redistribute to reach target chunk count
    while (target && i > 0) {
        if (!A[i]) {
            i -= 1;
            continue;
        }
        const max = Math.min(target, A[i]);
        A[i] -= max;
        A[i-1] += 2 * max;
        target -= max;
        i -= 1;
    }
    
    return target ? -1 : A.map((c, p) => [1 << Number(p), c]);
}

// Test with different numbers
console.log("Number 11 with max power 5:");
console.log(partitionNumber(11, 5));

console.log("\nNumber 9 with max power 4:");
console.log(partitionNumber(9, 4));
Number 11 with max power 5:
[ [ 1, 1 ], [ 2, 1 ], [ 4, 2 ], [ 8, 0 ], [ 16, 0 ], [ 32, 0 ] ]

Number 9 with max power 4:
[ [ 1, 1 ], [ 2, 0 ], [ 4, 0 ], [ 8, 1 ], [ 16, 0 ] ]

How the Algorithm Works

The algorithm follows these steps:

  1. Initial Distribution: Start by using the maximum chunk size as much as possible

  2. Binary Representation: Process the remainder using binary representation to find required smaller chunks

  3. Power-of-2 Constraint: Ensure the total number of chunks is a power of 2

  4. Redistribution: If needed, split larger chunks into smaller ones to meet the chunk count requirement

Understanding the Output

The output format is an array of [chunk_size, count] pairs. For number 11:

// Output: [ [ 1, 1 ], [ 2, 1 ], [ 4, 2 ], [ 8, 0 ], [ 16, 0 ], [ 32, 0 ] ]
// This means: 1×1 + 1×2 + 2×4 + 0×8 + 0×16 + 0×32 = 1 + 2 + 8 = 11
// Total chunks: 1 + 1 + 2 = 4 (which is 2²)

let result = partitionNumber(11, 5);
let actualChunks = [];
let total = 0;

result.forEach(([size, count]) => {
    for (let i = 0; i < count; i++) {
        actualChunks.push(size);
        total += size;
    }
});

console.log("Actual partition:", actualChunks);
console.log("Sum:", total);
console.log("Number of chunks:", actualChunks.length);
Actual partition: [ 1, 2, 4, 4 ]
Sum: 11
Number of chunks: 4

Conclusion

This algorithm efficiently partitions numbers into power-of-2 sized chunks where the total chunk count is also a power of 2. It uses bit manipulation and greedy redistribution to find valid partitions while respecting the maximum chunk size constraint.

Updated on: 2026-03-15T23:19:00+05:30

210 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements