2525. Categorize Box According to Criteria


Problem Description

The problem presents a scenario where we have a box with given dimensions (length, width, and height) and mass. We are required to categorize the box based on its size and weight into one of four possible categories: "Bulky", "Heavy", "Both", or "Neither". A box is considered "Bulky" if any of its dimensions are greater than or equal to 10,000 units or if its volume is greater than or equal to a billion cubic units. It is considered "Heavy" if its mass is greater than or equal to 100 units. The box can also fall into the "Both" category if it meets the criteria for both "Bulky" and "Heavy", or "Neither" if it meets neither criteria. The main task is to assess the box's dimensions and mass and return the corresponding category as a string.

Intuition

The straightforward approach to solving this problem is to simulate the conditions given in the problem statement. The first step is to calculate the volume of the box, which can be done by multiplying length, width, and height. Once we have the volume, we can check if any of the dimensions reach the "Bulky" criteria or if the volume itself makes the box "Bulky".

For the "Heavy" criteria, we simply compare the mass against the threshold of 100 units. Combining these two checks, we can determine which of the four categories the box falls into.

The given solution utilizes bitwise operations to efficiently encode the state of the box based on the "Bulky" and "Heavy" criteria. A binary representation is formed by shifting and combining the Boolean results of the "Heavy" check (heavy) and the "Bulky" check (bulky). This binary number is then used as an index to access the correct category from a predefined list d. Hence, the solution is both intuitive and efficient by avoiding multiple if-else conditions and leveraging binary state representation.

Learn more about Math patterns.

Solution Approach

The implementation of the solution follows these key steps:

  1. Calculate the volume (v) of the box by multiplying length, width, and height.

  2. Determine if the box is "Bulky" by checking two conditions:

    • If any one of the dimensions (length, width, or height) is greater than or equal to 10000.
    • Or, if the volume (v) is greater than or equal to 10^9. If any of these conditions are true, set the bulky variable to 1, otherwise to 0.

    This is achieved using the expression:

    bulky = int(any(x >= 10000 for x in (length, width, height)) or v >= 10**9)

    The any() function is used here to check if at least one of the dimensions is "Bulky". It iterates through the tuple of dimensions and the volume and returns True if any element meets the "Bulky" condition.

  3. Determine if the box is "Heavy" by comparing the mass to 100. If mass is greater than or equal to 100, set heavy to 1, otherwise set it to 0.

    This is achieved using the expression:

    heavy = int(mass >= 100)
  4. Combine the heavy and bulky indicators to form a binary representation.

    • Shift the heavy indicator to the left by one bit, resulting in Heavy occupying the 2's place in a binary number (effectively corresponding to the value of 2 if true).
    • Combine (|) heavy with bulky to form a 2-bit binary number (indices ranging from 0 to 3).

    This is done using:

    i = heavy << 1 | bulky
  5. Use the index i to return the corresponding category from the predefined list d which contains the strings 'Neither', 'Bulky', 'Heavy', and 'Both'.

    The final step in the code is:

    return d[i]

The use of a bitwise shift (<<) and bitwise OR (|) allows for an elegant handling of the different combinations of heavy and bulky. Instead of using a series of if-else statements to check each combination, this solution uses the two binary digits to index directly into the list that contains the appropriate category strings. This is both a space-efficient and time-efficient solution, as there are no complex data structures involved and the runtime is constant, being independent of the size of the input.

Ready to land your dream job?

Unlock your dream job with a 2-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's consider a box with dimensions length = 11000, width = 8000, height = 6000, and mass = 150. We will walk through the solution approach to determine the category of this box.

  1. Calculate the volume (v) of the box: ( volume = length \times width \times height = 11000 \times 8000 \times 6000 = 528,000,000,000 ) This volume exceeds the billion (10^9) cubic units threshold.

  2. Determine if the box is "Bulky":

    • The length is greater than 10000, so without further checks, we know at least one dimension makes the box "Bulky."
    • Our volume calculation already exceeds 10^9, confirming the box is indeed "Bulky."

    Since we know the box is "Bulky" based on just the length or volume, we would set bulky to 1.

  3. Determine if the box is "Heavy":

    • The mass of the box is 150, which is greater than 100.

    Since the mass exceeds 100, we set heavy to 1.

  4. Combine the heavy and bulky indicators:

    • heavy is set to 1, and when shifted left by one bit, it becomes 10 in binary, which is 2 in decimal.
    • bulky is 1, and combining (with bitwise OR) it with the shifted heavy value, we get 11 in binary, or 3 in decimal.

    So, i = 2 << 1 | 1 = 3.

  5. Use the index i to return the category:

    • With i equal to 3, we select the fourth element (0-indexed) from the list d which contains ['Neither', 'Bulky', 'Heavy', 'Both'].
    • The selected category is 'Both', because the box is both "Bulky" and "Heavy".

Thus, for a box with the given dimensions and mass, the category returned by the solution would be 'Both'. The box is both bulky due to its size and heavy due to its mass.

Solution Implementation

1class Solution:
2    def categorize_box(self, length: int, width: int, height: int, mass: int) -> str:
3        # Calculate the volume of the box
4        volume = length * width * height
5      
6        # Check for the bulky condition
7        # A box is bulky if any of its dimensions are 10,000 or more, or if its volume is 1 billion or more
8        is_bulky = int(any(dimension >= 10000 for dimension in (length, width, height)) or volume >= 10**9)
9
10        # Check for the heavy condition
11        # A box is heavy if its mass is 100 or more
12        is_heavy = int(mass >= 100)
13
14        # Encode the condition using binary representation
15        # This uses bit shifting to represent two binary digits, where
16        # the left digit represents the "heavy" condition and
17        # the right digit represents the "bulky" condition
18        condition_code = (is_heavy << 1) | is_bulky
19
20        # Define the dictionary to map the condition code to the corresponding string
21        condition_dict = ['Neither', 'Bulky', 'Heavy', 'Both']
22
23        # Return the string corresponding to the condition of the box
24        return condition_dict[condition_code]
25
1class Solution {
2    /**
3     * Categorizes a box based on its dimensions and mass.
4     *
5     * @param length the length of the box
6     * @param width  the width of the box
7     * @param height the height of the box
8     * @param mass   the mass of the box
9     * @return a string that categorizes the box as "Neither", "Bulky", "Heavy", or "Both"
10     */
11    public String categorizeBox(int length, int width, int height, int mass) {
12        // Calculate the volume of the box and store it as a long to prevent overflow.
13        long volume = (long) length * width * height;
14      
15        // Determine if the box is bulky using the provided conditions.
16        boolean isBulky = length >= 10000 || width >= 10000 || height >= 10000 || volume >= 1000000000;
17      
18        // Determine if the box is heavy using the provided condition.
19        boolean isHeavy = mass >= 100;
20      
21        // Create an array of possible descriptions.
22        String[] descriptions = {"Neither", "Bulky", "Heavy", "Both"};
23      
24        // Generate the index for the descriptions array based on the bulky and heavy flags.
25        // isHeavy contributes to the higher order bit, so it's shifted left. isBulky contributes to the lower order bit.
26        int index = (isHeavy ? 1 : 0) << 1 | (isBulky ? 1 : 0);
27      
28        // Return the corresponding description from the array.
29        return descriptions[index];
30    }
31}
32
1#include <string>
2
3class Solution {
4public:
5    // This method categorizes a box based on its dimensions and mass.
6    // The categories are 'Neither', 'Bulky', 'Heavy', or 'Both'.
7    // A box is considered 'Bulky' if any of its dimensions is greater than or equal to 10000,
8    // or its volume is greater than or equal to 1 billion.
9    // A box is considered 'Heavy' if its mass is greater than or equal to 100.
10    std::string categorizeBox(int length, int width, int height, int mass) {
11        // Calculate the volume of the box as a long integer to prevent overflow
12        long volume = static_cast<long>(length) * width * height;
13      
14        // Determine whether the box is bulky
15        bool isBulky = (length >= 10000 || width >= 10000 || height >= 10000 || volume >= 1000000000);
16      
17        // Determine whether the box is heavy
18        bool isHeavy = (mass >= 100);
19      
20        // Define an array of strings to hold the potential categories
21        std::string descriptions[4] = {"Neither", "Bulky", "Heavy", "Both"};
22      
23        // Use bitwise logic to index the correct description:
24        // - Shift 'isHeavy' left by 1 bit and 'or' it with 'isBulky' to form a 2-bit index
25        int index = (isHeavy << 1) | isBulky;
26      
27        // Return the description based on the index
28        return descriptions[index];
29    }
30};
31
1/**
2 * Categorizes a box based on its dimensions and mass.
3 *
4 * @param {number} length - The length of the box in millimeters.
5 * @param {number} width - The width of the box in millimeters.
6 * @param {number} height - The height of the box in millimeters.
7 * @param {number} mass - The mass of the box in kilograms.
8 * @returns {string} A string categorization of the box: 'Neither', 'Bulky', 'Heavy', or 'Both'.
9 */
10function categorizeBox(length: number, width: number, height: number, mass: number): string {
11    // Calculate the volume of the box
12    const volume = length * width * height;
13
14    // Initialize the category index
15    let categoryIndex = 0;
16
17    // Check for 'Bulky' category criteria: any dimension or volume above the threshold
18    const maxDimensionSize = 10000; // millimeters
19    const maxVolume = 1000000000;   // cubic millimeters
20    if (length >= maxDimensionSize || width >= maxDimensionSize || height >= maxDimensionSize || volume >= maxVolume) {
21        categoryIndex |= 1; // Set the first bit if 'Bulky'
22    }
23
24    // Check for 'Heavy' category criteria: mass above the threshold
25    const maxMass = 100; // kilograms
26    if (mass >= maxMass) {
27        categoryIndex |= 2; // Set the second bit if 'Heavy'
28    }
29
30    // Determine the category based on the category index
31    const categories = ['Neither', 'Bulky', 'Heavy', 'Both'];
32    return categories[categoryIndex];
33}
34

Time and Space Complexity

The time complexity of the function categorizeBox is O(1) because the operations performed within the function do not depend on the size of the input; they consist of basic arithmetic operations, comparisons, and bitwise operations which all take constant time.

The space complexity of the function is also O(1) as it only uses a fixed amount of additional memory for variables v, bulky, heavy, i, and the constant size list d, regardless of the input size.

Learn more about how to find time and space complexity quickly using problem constraints.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:
Question 1 out of 10

What's the output of running the following function using input [30, 20, 10, 100, 33, 12]?

1def fun(arr: List[int]) -> List[int]:
2    import heapq
3    heapq.heapify(arr)
4    res = []
5    for i in range(3):
6        res.append(heapq.heappop(arr))
7    return res
8
1public static int[] fun(int[] arr) {
2    int[] res = new int[3];
3    PriorityQueue<Integer> heap = new PriorityQueue<>();
4    for (int i = 0; i < arr.length; i++) {
5        heap.add(arr[i]);
6    }
7    for (int i = 0; i < 3; i++) {
8        res[i] = heap.poll();
9    }
10    return res;
11}
12
1class HeapItem {
2    constructor(item, priority = item) {
3        this.item = item;
4        this.priority = priority;
5    }
6}
7
8class MinHeap {
9    constructor() {
10        this.heap = [];
11    }
12
13    push(node) {
14        // insert the new node at the end of the heap array
15        this.heap.push(node);
16        // find the correct position for the new node
17        this.bubble_up();
18    }
19
20    bubble_up() {
21        let index = this.heap.length - 1;
22
23        while (index > 0) {
24            const element = this.heap[index];
25            const parentIndex = Math.floor((index - 1) / 2);
26            const parent = this.heap[parentIndex];
27
28            if (parent.priority <= element.priority) break;
29            // if the parent is bigger than the child then swap the parent and child
30            this.heap[index] = parent;
31            this.heap[parentIndex] = element;
32            index = parentIndex;
33        }
34    }
35
36    pop() {
37        const min = this.heap[0];
38        this.heap[0] = this.heap[this.size() - 1];
39        this.heap.pop();
40        this.bubble_down();
41        return min;
42    }
43
44    bubble_down() {
45        let index = 0;
46        let min = index;
47        const n = this.heap.length;
48
49        while (index < n) {
50            const left = 2 * index + 1;
51            const right = left + 1;
52
53            if (left < n && this.heap[left].priority < this.heap[min].priority) {
54                min = left;
55            }
56            if (right < n && this.heap[right].priority < this.heap[min].priority) {
57                min = right;
58            }
59            if (min === index) break;
60            [this.heap[min], this.heap[index]] = [this.heap[index], this.heap[min]];
61            index = min;
62        }
63    }
64
65    peek() {
66        return this.heap[0];
67    }
68
69    size() {
70        return this.heap.length;
71    }
72}
73
74function fun(arr) {
75    const heap = new MinHeap();
76    for (const x of arr) {
77        heap.push(new HeapItem(x));
78    }
79    const res = [];
80    for (let i = 0; i < 3; i++) {
81        res.push(heap.pop().item);
82    }
83    return res;
84}
85

Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!


Load More