Odd or Even?
Tags: kata, challenge, codewars, php
Published: 2019-11-28 15:33:59

## Task description

> Given an array of numbers, determine whether the sum of all of the numbers is odd or even.
> 
> Give your answer in string format as 'odd' or 'even'.
> 
> If the input array is empty consider it as an array with a zero.
> 
> Example:
> `odd_or_even([])` returns "even"
> `odd_or_even([0])` returns "even"
> `odd_or_even([2, 5, 34, 6])` returns "odd"
> `odd_or_even([0, -1, -5])` returns "even"
> Have fun!

## Task solution

### Tests

We want to test a couple of things:

1. Does the function provide an error for invalid input types?
2. Does the function work as expected with no items in the array?
2. Does the function work as expected with positive numbers?
3. Does the function work as expected with negative numbers?
4. Does the function return the correct value with mixed numbers?

For the tests, I have used [PHPUnit](https://phpunit.de/).

```php
class OddOrEvenTests extends TestCase {
  public function testInvalidInputThrowsTypeError() {
    $this->expectException(TypeError::class);
    odd_or_even(1);
  }
  
  public function testNegativeNumbers() {
    $this->assertEquals('even', odd_or_even([0, -1, -5]));
  }

  public function testPositiveNumbers() {
    $this->assertEquals('odd', odd_or_even([2, 5, 34, 6]));
  }

  public function testMixed() {
    $this->assertEquals('odd', odd_or_even([0, -1, -5, 2, 5, 34, 6, 2.3]));
  }

  public function testSingleNumber() {
    $this->assertEquals('even', odd_or_even([0]));
  }
  
   public function testEmpty() {
    $this->assertEquals('even', odd_or_even([]));
  }
}
```

### Implementation

```php
function addition_reducer(int $accumulator, int $item): int {
  return $accumulator + $item;
}

function odd_or_even(array $integer_array): string {
  $reduced = array_reduce($integer_array, addition_reducer, 0);
  return $reduced % 2 === 0 ? 'even' : 'odd';
}
```

The `addition_reducer` does exactly as it states when used via `array_reduce`. It will take the `$accumulator`, in our case `0`, then on each iteration of the `$integer_array`, it will add the `$item` to the `$accumulator`. Once this is done, the next item in the array will be added to the previous iterations return value, which will now be the `$accumulator`.

After transforming our array we check if the reduced value divided by 2 has no leftover value using the `%` operator. All this means is that if we want to be sure a number is divisible by any other, we could just do `number % divider === 0` and if that is true, we know it is divisible as a whole number.

All that being the case, we can run our check on our `$reduced` number returned and run the `%` operator on it with `2` as our divider, if the operation returns `0`, we know it is an even number since it is wholly divisible by 2 with no leftovers, otherwise, it must be odd.

### Sidenote 1: The `%` operator

The naming of the operator can be a bit confused I have dound, with some referring to it as `modulus` and others as `modulo`. This is understandable though since there is both a `modulus` and a `modulo` and both are interconnected. The definition of each is slightly different however and are outlined as follows: 

> The Modulus is the remainder of the euclidean division of one number by another. % is called the modulo operation.

For instance, 5 divided by 3 equals `1.6666666666666667` but the remainder is `2`. This being the case we can say:

- `5 / 3` = `1.6666666666666667`
- `5 % 3` = `2`

The modulo operator itself can be represented as `a - floor(a / b) * b`. This being the case we could write a helper function to get the same result as the `%` operator, in javascript for example we would write such a helper like so:

```javascript
function modulo(a, b) {
 return a - Math.floor(a / b) * b;
}

modulo(5, 3) // 2
```

### Sidenote 2: Reducers

Reducers take something and transform it into something else, usually they will be used on `arrays`, `objects`, `collections` or some other form of iterable. In our case we want to transform an array of numbers into just a number which is to be the summed value of each number in the array.

A reducer in such cases is just a fancy kind of loop, other such special loops include `map`, `filter`, `reduce` and much more, usually fully built in to the language. In `PHP` they are simply `array_map`, `array_filter` and `array_reduce` respectively. In `JavaScript` the are `[].map`, `[].filter` and `[].reduce`. More such special loop types exist but these are the main 3 you'll use.

If we were to reproduce the `array_reduce` line from above with a similar `foreach` based approach, we could do something like this:

```php
$items = [1, 2, -3];
$final_value = 0;
foreach($items as $item) {
 $final_value += $item;
}
echo $final_value; // 0
```

Our reducer is basically doing the same as the above code but in a more functional and descriptive manner with less lines of code required.

```php
$array = [1, 2, -3];
$initial_value = 0;
$reduced = array_reduce($array, addition_reducer, $initial_value);
echo $reduced; // 0
```

## Conclusions

Overall this task was quite easy but things like the `modulo` operator (`%`) are always fun to work with since they do something in a way you wouldn't normally approach things and yet are hyper useful in day to day programming as you will see in an upcoming post on [The Mars Rover Kata](https://katalyst.codurance.com/mars-rover) as the `%` operator will literally and figuratively be a driving force for the solution to that challenge. 

I don't think I would change anything in the implementation, I mean I could use the `array_sum` function in `PHP` to avoid the `array_reduce` and `addition_reducer` functions but I prefer to use a reducer because people coming from other languages would be more likely to recognise a reducer comparitively to a language specific function like `array_sum`. If I were to do that version though, the whole solution would look like this:

```php
function odd_or_even(array $integer_array): string {
  $reduced = array_sum($integer_array);
  return $reduced % 2 === 0 ? 'even' : 'odd';
}
```

Thanks for reading and see you in the next one!