I’ve been doing the Weekly
Challenges. The
latest
involved cumulative sums and complicated sorts. (Note that this ends today.)
Task 1: Running Sum
You are given an array of integers.
Write a script to return the running sum of the given array. The
running sum can be calculated as sum[i] = num[0] + num[1] + …. + num[i]
.
There are two fairly obvious ways to do this. One is to start an
accumulator at zero, add each entry, and copy the running total into a
new list. That let me do it variable-free in PostScript:
/runningsum {
Push onto the stack, below the input array, the opening of a new array
and a single member of velue zero.
[ exch
0 exch
For each member of the input array, add to the latest member of the
new, and make another copy, which we'll add to with the next element.
{
add dup
} forall
The last entry will be duplicated, so drop that.
pop
And end the array.
]
} bind def
But in other languages I made a copy of the input list and just added
to each member (after the first) the value of the previous member.
Thus in Raku:
sub runningsum(@a) {
my @b = @a;
for 1 .. @a.end -> $i {
@b[$i] += @b[$i-1];
}
return @b;
}
Task 2: Persistence Sort
You are given an array of positive integers.
Write a script to sort the given array in increasing order with
respect to the count of steps required to obtain a single-digit
number by multiplying its digits recursively for each array element.
If any two numbers have the same count of steps, then print the
smaller number first.
So there are two parts to this. One is a function to generate the
persistence value, which is fairly straightforwawrd. Rust:
fn persistence(a: u32) -> u32 {
let mut steps = 0;
let mut b = a;
while b > 9 {
steps += 1;
let mut p = 1;
while b > 0 {
p *= b % 10;
b /= 10;
}
b = p;
}
steps
}
Then it's a two-stage sort, by persistence value and then by
individual value, and different languages approach this in different
ways. In Rust again, sort()
is stable, and there's a
sort_by_cached_key()
which takes care of not calculating persistence
more often than we have to. (While it doesn't matter with these small
examples, it could clearly get quite expensive.)
fn persistencearray(a: Vec<u32>) -> Vec<u32> {
let mut b = a;
b.sort();
b.sort_by_cached_key(|i| persistence(*i));
b
}
Kotlin and Python also have stable sorting, but get a manual cache of
persistence values. In Lua and most of the other languages, I build a
manual cache and then do a sort with a custom comparator.
function persistencearray(a)
local b = a
Build the cache (avoiding duplications):
local c = {}
for _, v in ipairs(b) do
if c[v] == nil then
c[v] = persistence(v)
end
end
Sort with comparator:
table.sort(b, function(a, b)
if c[a] == c[b] then
return a < b
else
return c[a] < c[b]
end
end)
return b
end
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.