/now
projects
ramblings
smol projects

sum of missing numbers

20.11.2023 2 min read

Create a function that returns the sum of missing numbers.

sumMissingNumbers([1, 3, 5, 7, 10]) ➞ 29
// 2 + 4 + 6 + 8 + 9
sumMissingNumbers([10, 7, 5, 3, 1]) ➞ 29
sumMissingNumbers([10, 20, 30, 40, 50, 60]) ➞ 1575

Crystal:

def create_range_between(i, j : Int32)
  (i + 1..j - 1).map do |n|
    n
  end
end

def sum_missing_numbers(a : Array(Int32))
  missing_nos = a.sort.each_cons_pair.reduce([] of Int32) do |acc, el|
    i, j = el
    acc.concat(create_range_between(i, j))
  end
  missing_nos.sum
end

Crystal has a nice each_cons_pair that doesn’t go out of bounds so we don’t have to care about not having a next.

Nim:

func createRangeBetween(i, j: int): seq[int] =
    collect(newSeq):
        for i in countup(i + 1, j - 1): i

func sumMissingNumbers(s: seq[int]): int =
    let sorted = s.sorted
    let missing = collect(newSeq):
        for i in 0 .. sorted.len - 2:
            createRangeBetween(sorted[i], sorted[i + 1])
    missing.foldl(a & b).sum

We avoid IndexDefect by only going up to len - 2.

Raku:

sub create-range-between($i, $j) {
    do for $i+1..$j-1 {$_}
}

sub sum-missing-numbers(@a) {
    my $sorted := @a.sort.cache;
    my $missing := do for $sorted.kv -> $k, $v {
        next if $k == @a.elems - 1; 
        create-range-between($v, $sorted[$k+1]);
    }

    [+] $missing.flat;
}

We need to cache the list, if not Raku complains that the Seq is already being consumed (or something to that effect. I honestly don’t know how to predict when these things will happen. I only know that throwing a .cache will usually sort it out). Classic for loops in Raku are “discouraged”, and I had some difficulty finding the syntax for them in the official documentation. However, I did find an example here.

loop (my $i = 1; $i <= 3; $i++) {
    say $i;
}

Just putting this here in case I ever decide I want to use one (I doubt it).

Last one, Javascript:

function createRangeBetween(i: number, j: number) {
  return Array(j - i - 1)
    .fill(null)
    .map((_, k) => i + 1 + k);
}

function sumMissingNumbers(a: number[]) {
  const sorted = [...a.sort((a, b) => a - b)];
  const missingNos = sorted.reduce((acc, curr, i) => {
    const next = sorted[i + 1];
    if (!next) return acc;
    return [...acc, ...createRangeBetween(curr, next)];
  }, [] as number[]);
  return missingNos.reduce((a, b) => a + b, 0);
}

In recent days, I’ve really come to appreciate Javascript’s reduce. I wish Nim’s foldl worked like this, but it seems to only support simple operations for now. Maybe one day.

Built with Astro and Tailwind 🚀