Balancing Complexity: A Tale of Array Includes vs. Negation
Tags: javascript, computerscience, programming
Published: 2023-06-02 17:51:34

## The Farmer's Robotic Helper

Developers are constantly balancing complexity and flexibility. Imagine you're a farmer with an assortment of fruits: apples, bananas, oranges, and pears. You have a robotic helper which sorts the fruits into two bins, the Regular Bin and the Premium Bin. Apples and bananas can go into **both** bins, while oranges and pears are **exclusive** to the Premium Bin. Each morning, the robot picks up a random fruit and needs to decide which bin it should go to.

As the farmer, you're tasked with writing the software that guides the robot's decision-making. You can choose between two main approaches.

## The Negation Approach

One way is to code the robot to identify where a fruit cannot go. If the fruit is not an orange and not a pear, it can be placed in the Regular Bin.

```jsx
if (fruit !== 'orange' && fruit !== 'pear') {
  regularBin.add(fruit);
}
```

This approach is simple and flexible. To add a new fruit, you simply avoid adding a new condition. However, it's not immediately clear which fruits can go to the Regular Bin - you have to infer this from what they're not. As the farm diversifies its fruits maintaining this function is easier when there are fewer premium fruits being added. 

## The Array Includes Approach

Alternatively, you can list the fruits that go to each bin in an array, and check if the fruit is in that array.

```jsx
const regularBinFruits = [ 'apple', 'banana'];

if(regularBinFruits.includes(fruit)){
  regularBin.add(fruit);
}

```

This approach is more explicit and understandable. It's clear which fruits can go to the Regular Bin. However, it's slightly more complex in terms of code, and adding new fruit requires updating the array. When the farm adds any regular fruit, the farmer has to update the array. When the farm adds premium fruits, no change is needed. 

There are other possible solutions to this problem. Here are a couple of them:

1. **Use a dictionary or a map**: This approach can be very efficient especially when you have a large number of categories or items. Instead of using an array or a negation logic, you can map each item to a certain value (true/false, or 0/1, or any other meaningful value). This way, you can check the membership of an item in constant time. Here is an example:

```jsx
let regularBinFruits = { 'apple': true, 'banana': true };

if(regularBinFruits[fruit]){
  regularBin.add(fruit);
}
```

2. **Use a switch-case structure**: This might be a good choice if you have a small number of items and each item requires a different set of actions. However, it can become cumbersome if you have a large number of items.

```jsx
switch(fruit) {
  case 'apple':
  case 'banana':
    regularBin.add(fruit);
    // break is omitted to allow fallthrough
  case 'orange':
  case 'pear':
    premiumBin.add(fruit);
    break;
  default:
    // handle unknown fruit
    break;
}
```

## Conclusion

At its core, this dilemma of categorizing items -- whether they're fruits for a farmer's robot or variables in a software program -- is a foundational problem in both computer science and mathematics. It deals with set theory, conditional logic, and algorithmic complexity. These subjects are often surrounded by academic jargon that can make them seem daunting.

However, as we've seen through the practical examples in this blog post, these concepts are not as complex as they might initially appear. They're essentially about making decisions based on whether or not certain conditions are met. Do I put this apple in the regular bin or the premium bin, or both? 

In each case, we've seen that there are different approaches you can take, each with its own trade-offs. The negation approach is simple and flexible but can be less explicit. The array includes approach is more explicit but slightly more complex and less flexible. Other solutions, like using a map or a switch-case structure, offer their own sets of advantages and disadvantages.

In the end, the best solution always depends on the specific context and requirements of your problem. The key is to understand your use case and choose the solution that best meets your needs. And remember, while these problems can be expressed in academic terms, they're fundamentally about making decisions -- something we all do every day. So don't be intimidated by the jargon. You're more than capable of understanding and applying these concepts.