**Advent Calendar 2022**

### | **Day 19** | **Day 20** | **Day 21** |

The gift is presented by `Roger Bell_West`

. Today he is talking about his solution to **“The Weekly Challenge - 192”**. This is re-produced for **Advent Calendar 2022** from the original **post** by him.

## Equal Flips For All

I’ve been doing the **Weekly Challenges**.

**The latest** involved a binary negation and list division. (Note that this is open until `27 November 2022`

.)

## Task 1: Binary Flip

You are given a positive integer, `$n`

.

Write a script to find the binary flip.

This turns out to be: take the binary representation (with no leading zeroes), then exchange all `0s`

and `1s`

to get an inverse value.

This is clearly intended to be a problem about binary representations. But we don’t need to do that. Instead, I find the value of the `leftmost set bit`

in the input by counting repeated shift rights until there’s nothing left – e.g. `5`

is processed as `101`

, `10`

, `1`

, `0`

, so `three`

shifts. (i.e. `log base 2`

.) Then shift `1`

left that many times (getting `8`

). Subtract 1: `7`

, which gives me what in binary would be a series of `"1"`

of the same length as the original number. Then subtract the input from that (gosh, an actual legitimate `"take away the number you first thought of"`

).

This sequence is **in the OEIS** and the graph makes this approach particularly obvious.

Some languages have access to `CPU functions`

to count leading zeroes and thus get a binary magnitude that way, but I did this the same way throughout. `JavaScript`

:

```
function binaryflip(n) {
let m = n;
let r = 0;
while (m > 0) {
m >>= 1;
r += 1;
}
return (1 << r) - 1 - n;
}
```

## Task 2: Equal Distribution

You are given a list of integers greater than or equal to zero, `@list`

.

Write a script to distribute the number so that each members are same. If you succeed then print the total moves otherwise print -1.

`"Distribute"`

turns out to mean `"subtract one from a list value, adding it to another adjacent list value"`

. So this has to be done iteratively `[0 3 0] → [1 2 0] → [1 1 1] = 2 steps`

, adding and subtracting `1`

each time. If a number is higher than both its neighbours, the process is not immediately obvious, but this one seemed to work.

## Raku

```
sub equaldistribution(@list) {
```

Check that an even distribution is possible.

```
my $s = @list.sum;
if ($s % @list.elems != 0) {
return -1;
}
```

Get a target value for each element.

```
my $m = $s div @list.elems;
my $out = 0;
my @w = @list;
while (True) {
for (0..@w.elems-2) -> $i {
```

Going through the list, if this value is higher than it needs to be, move any surplus into the next element.

```
if (@w[$i] > $m) {
my $v = @w[$i] - $m;
@w[$i+1] += $v;
$out += $v;
@w[$i] = $m;
```

If it’s lower, take as much as possible from the next element (without letting it go below zero.)

```
} elsif (@w[$i] < $m) {
my $v = min($m - @w[$i], @w[$i+1]);
@w[$i+1] -= $v;
$out += $v;
@w[$i] += $v;
}
}
```

If the job’s done, exit, otherwise loop again.

```
if (@w.all == $m) {
last;
}
}
return $out;
}
```

Full code on **GitHub**.

If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.