We can tackle the issue with a bit more math, so we can use other programming concepts. Here we are going to abuse the fact that pure functions might suffer memoing .
In short:
- pure function: Given a pure function
f
, if you pass the argument a
, then the value of f(a)
is always the same; it is said of functions that do not require side effects
- memo: learning in the simplest possible way; if I know
f(a) = b
after doing a heavy computation, then the next time I'm asked f(a)
, return b
without computing almost nothing; a pre-processing is not normally considered as memo
We're talking here about the pure function soma_primos_em_intervalo_fechado(início, fim)
. However, the domain of this function is large (in the order of o(n^2)
, with n
being the largest possible entry ). So this function does not interest me to memoise.
However, this function can be decomposed into a subtraction of a pure function for two distinct arguments:
soma_primos_em_intervalo_fechado(início, fim):
acumulado_primos_desde_0(fim) - acumulado_primos_desde_0(início - 1)
I'm going to owe the demo, but it's easy
So this other pure function has dominance of the order of o(n)
, it is already subject to memoization. So now our problem is just to define and write this acumulado_primos_desde_0(n)
function, using memo to optimize any repeated queries.
This function will return the sum of all prime numbers up to the positive value n
. So, if n
is not prime, acumulado_primos_desde_0(n) = acumulado_primos_desde_0(n-1)
. However, if n
is prime, then we have acumulado_primos_desde_0(n) = n + acumulado_primos_desde_0(n-1)
.
So we can define the function this way:
acumulado_primos_desde_0(n):
0, se n <= 0 # caso de falha/caso base
acumulado_primos_desde_0(n-1), se n não for primo
n + acumulado_primos_desde_0(n-1), se n for primo
Since you never enter negative values in this function, I'm sure, for any value, acumulado_primos_desde_0(n) >= 0
. So I can initialize my memoization vector with -1
which, as I guarantee it does not belong to the counterdomain, then means that my cache is not loaded with a valid value, so I should do heavy computation.
The definition of the function, using the memoization in the most efficient way that I can imagine, would look like this:
int cache[]; // magicamente inicializou com -1
int acumulado_primos_desde_0(int n) {
if (cache[n] != -1) {
return 0;
}
if (n <= 0) {
return 0;
} else {
return cache[n] = (eh_primo(n)? n: 0) + acumulado_primos_desde(n-1);
}
}
Get your favorite version of primability detection, such as @Lacobus response .
Note that the cache value is always updated after a cache miss (except non-positive parameters). So, given your favorite variant of eh_primo
, the following functions address the problem:
int cache[]; // magicamente inicializou com -1
int acumulado_primos_desde_0(int n) {
if (cache[n] != -1) {
return 0;
}
if (n <= 0) {
return 0;
} else {
return cache[n] = (eh_primo(n)? n: 0) + acumulado_primos_desde(n-1);
}
}
int soma_primos_intervalo_fechado(int ini, int fim) {
return acumulado_primos_desde_0(fim) - acumulado_primos_desde_0(ini-1);
}