# RogerBW's Blog

The Weekly Challenge 235: One, Zero 24 September 2023

I’ve been doing the Weekly Challenges. The latest involved spotting sequences, and duplicating list entries. (Note that this ends today.)

You are given an array of integers.

Write a script to find out if removing ONLY one integer makes it strictly increasing order.

The obvious way to do this would be to copy the input list, remove each element in turn, then test to see whether what's left is sorted. So I thought I'd do it a different way.

If there is an element that's preventing the list from being in ascending order, it'll be equal to or higher than the next one. And if removing it will leave the list in order, the difference between them will be less than the difference between it and the previous one.

(Debian/stable now has Python 3.11, so I get `pairwise` that was introduced in 3.10. Many of these languages have some kind of windowing function to let me take each adjacent pair of list elements automatically, but like hashes and other relatively recent innovations the syntax varies a great deal between languages. The most sophisticated is probably Raku's `rotor`.)

Python:

``````def removeone(a):
``````

Error count:

``````  ec = 0
``````

Latest difference (pre-loaded in case the first entry is the problem):

``````  le = 1 + a - a
for s in pairwise(a):
``````

If the later value is no higher than the earlier:

``````    if s <= s:
``````

Increment the error count.

``````      ec += 1
``````

If there's there's more than one error, or the step down from this to next is bigger than the step up from the previous value, this list won'd be ordered by removing this one.

``````      if ec > 1 or s - s >= le:
return False
``````

Set the step up from this to next.

``````    le = s - s
``````

If nothing went horribly wrong, the list is valid.

``````  return True
``````

(A list that is strictly increasing will generate zero errors.)

You are given an array of integers.

Write a script to duplicate each occurrence of ZERO in the given array and shift the remaining to the right but make sure the size of array remain the same.

Rather than inserting extra elements, it seems to me cleaner to iterate over the input, pushing an extra zero onto the output when one occurs in the input. When the output gets too long, exit and truncate it. In Raku:

``````sub duplicatezeros(@a) {
my @out;
``````

For each input value:

``````    for @a -> \$t {
``````

Append it to the output.

``````        @out.push(\$t);
``````

And stick on another zero if needed.

``````        if (\$t == 0) {
@out.push(\$t)
}
``````

If we've got enough entries, bail out. (Not strictly necessary.)

``````        if (@out.elems >= @a.elems) {
last;
}
}
``````

If we've got too many entries, trim them back.

``````    if (@out.elems > @a.elems) {
@out.splice(@a.elems);
}
return @out;
}
``````

And I've added Scala to my suite of languages, so you lucky lot get to see Roger's first ever Scala program. (It doesn't have a `break`, by design, so rather than build a branching variable I just drop the inner test, let the output list grow to its full length, then trim for output.)

``````def duplicatezeros(a: List[Int]): List[Int] = {
var out = new ListBuffer[Int]
for (t <- a) {
out += t
if (t == 0) {
out += t
}
}
if (out.length > a.length) {
out = out.dropRight(out.length - a.length)
}
return out.toList
}
``````

Full code on github.