For detailed problem statement, head over to the bill division problem here

From the problem definition, we get two things

- Element at index
`k`

should not be considered for bill computation - Rest of the elements should be added and then share computed by dividing total by two

Bear in mind that division should be done *after* computing the total. So, below I listed few aggregators to compute the sum from array (excluding an index). There are more ways to achieve this in kotlin. Each has slight difference and some of them are improved version of other.

### 1. sumBy

```
array.withIndex().sumBy { // IndexedValue<Int>
if (it.index != k) {
it.value
} else {
0
}
}
```

Above creates an `IndexingIterable`

, emits `IndexedValue<Int>`

for each item and consumed by the `sumBy`

function

### 2. sumOf

```
array.withIndex().sumOf { // IndexedValue<Int>
if (it.index != k) {
it.value
} else {
0
}
}
```

`sumOf`

follows the same footprint of `sumBy`

. Only difference is `sumOf`

can return different result type (ex. Double or Long instead of Int). Below snippet explains the usage of each sum function.

```
val totalInt = array.sumBy { it }
val totalDouble1 = array.sumBy { it.toDouble() } //Error: Type mismatch
val totalDouble2 = array.sumByDouble { it.toDouble() }
val totalDouble3 = array.sumOf { it.toDouble() }
```

### 3. foldIndexed

```
array.foldIndexed(0) {
index, acc, value ->
acc + if (index == k) {
0
} else {
value
}
}
```

**foldIndexed** function takes in a initial value and an operation lambda to operate on the element. Notice the lambda returns the accumulated value on each iteration. Unlike sum functions which needs element to operate on, here the operation owned by the us.

### 4. reduceIndexed

```
array.reduceIndexed {
index, acc, value ->
acc + if (index == k) {
0
} else {
value
}
}
```

**reduceIndexed** is similar to foldIndexed function, and it lacks the initial value.

There are few downsides using reduce instead of fold:

- If the
`array`

is empty, reduce function will throw**UnsupportedOperationException**

*java.lang.UnsupportedOperationException: Empty array can't be reduced*

- Accumulated value result type cannot be different from the array element type

Functions listed above operates on original array and computes the result. Below ones creates a filtered list out of original array, it can be used to perform operations on it.

### 5. filterIndexed + sum()

```
array
.filterIndexed { index, _ -> index != k }
.sum()
```

### 6. fold

```
array
.filterIndexed { index, _ -> index != k }
.fold(0) { acc, value -> acc + value }
```

### 7. reduce

```
array
.filterIndexed { index, _ -> index != k }
.reduce{ acc, value -> acc + value }
```

## Solution:

Here is the complete solution to the problem.

```
fun bonAppetit(bill: Array<Int>, k: Int, b: Int): Unit {
val diff = b - bill.foldIndexed(0) {
i, total, v ->
if (i != k) {
total + v
} else {
total
}
}/2
println(if (diff == 0) {
"Bon Appetit"
} else {
diff
})
}
```

**Edit:** I left out the loop statements here to focus on aggregators. Feel free to comment if anything else turn up, I'll add it to the list.

## Discussion (0)