I’ve been doing the Weekly
Challenges. The
latest
involved various sorts of filtering arrays. (Note that this ends
today.)
Task 1: Max Positive Negative
You are given an array of integers, @ints
.
Write a script to return the maximum number of either positive or
negative integers in the given array.
The obvious way would be to iterate over the array once, counting both
positives and negatives, as in this Lua:
function maxpositivenumber(a)
local pos = 0
local neg = 0
for _, c in ipairs(a) do
if c > 0 then
pos = pos + 1
elseif c < 0 then
neg = neg + 1
end
end
return math.max(pos, neg)
end
However, I mostly ended up iterating twice with something like a
filter, as in this Raku:
sub maxpositivenumber(@a) {
return max(
@a.grep({$_ > 0}).elems,
@a.grep({$_ < 0}).elems,
);
}
It's innately slightly slower; even if iteration overhead is low,
it'll test each positive integer for negativity, which the Lua version
avoids with its elseif
. But I find it distinctly more elegant. In
PostScript I don't even need any variables (though my implementation
of filter
hides some).
/maxpositivenumber {
dup
{ 0 gt } filter length exch
{ 0 lt } filter length
max
} bind def
What I'd really like is a multi-way filter that would give me both the
accepted and the rejected streams, but I don't know whether that's a
thing in any of the languages I'm using.
Task 2: Count Equal Divisible
You are given an array of integers, @ints
and an integer $k
.
Write a script to return the number of pairs (i, j)
where
a) 0 <= i < j <
size of @ints
b) ints[i] == ints[j]
c) i × j
is divisible by k
Where the language had a built-in combination calculator (Raku, Ruby)
or an easily-available module (Perl, Rust, Python) I used that. Where
I'd had to write my own (Lua, JavaScript, Kotlin, Scala), I didn't
bother. I'd had to write my own in PostScript but my build system
makes it trivial to use library functions.
Best of all was the Rust where I can run combinations off an
enumerated list, so the inner loop already has both the index and the
value of each active element:
fn countequaldivisible(a: Vec<u32>, k: usize) -> u32 {
let mut s = 0;
for c in a.iter().enumerate().combinations(2) {
if c[0].1 == c[1].1 && c[0].0 * c[1].0 % k == 0 {
s += 1;
}
}
s
}
Mostly I ran combinations on the indices and looked up the values, as
in Ruby:
def countequaldivisible(a, k)
s = 0
0.upto(a.length - 1).to_a.combination(2) do |c|
if a[c[0]] == a[c[1]] && c[0] * c[1] % k == 0 then
s += 1
end
end
return s
end
Or just had a nested loop, as in Kotlin:
fun countequaldivisible(a: List<Int>, k: Int): Int {
var s = 0
for (i in 0 .. a.size - 2) {
for (j in i + 1 .. a.size - 1) {
if (a[i] == a[j] && i * j % k == 0) {
s += 1
}
}
}
return s
}
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.