I’ve been doing the Weekly
Challenges. The
latest
involved spotting sequences, and duplicating list entries. (Note that
this ends today.)
Task 1: Remove One
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[1] - a[0]
for s in pairwise(a):
If the later value is no higher than the earlier:
if s[1] <= s[0]:
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[0] - s[1] >= le:
return False
Set the step up from this to next.
le = s[1] - s[0]
If nothing went horribly wrong, the list is valid.
return True
(A list that is strictly increasing will generate zero errors.)
Task 2: Duplicate Zeros
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.
Comments on this post are now closed. If you have particular grounds for adding a late comment, comment on a more recent post quoting the URL of this one.