EnzoFerber
(usa FreeBSD)
Enviado em 19/10/2015 - 15:31h
Olhe o código a seguir. Utilizei um pouco do diagrama de Young como havia dito.
Entretando, possui um sério problema: não identifica quando é impossível fazer uma combinação.
Por exemplo, ele vai entrar em loop infinito se você passar os arguementos 33 e 1 (não há primo que seja 33).
33 e 2 (@paulo1205, há dois primos realmente, mas o programa não calcula - 31 + 2),
etc...
Fica pra você implementar.
/* prime_sum.c
*
* Enzo Ferber
* 2015
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define __INLINE__ __inline__ __attribute__((__always_inline__))
int __INLINE__ is_prime(int n)
{
int i;
for (i = 2; i < n; i++)
if (!(n % i)) return 0;
return 1;
}
int __INLINE__ next_prime(int prime)
{
while (!is_prime(++prime)) ;
return prime;
}
int __INLINE__ prior_prime(int prime)
{
while(!is_prime(--prime)) ;
return prime;
}
int *new_array(int sum, int max)
{
int *p = malloc(max * sizeof *p);
int prime = 1;
register int i;
while ((prime * max) < sum)
prime = next_prime(prime);
for (i = 0; i < max; i++)
p[ i] = prime;
return p;
}
int __INLINE__ compute(int *array, int max)
{
int sum = 0;
register int i;
for (i = 0; i < max; i++)
sum += array[ i];
return sum;
}
void build_sum_vector(int *array, int sum, int max)
{
int delta, pp, i, dp;
delta = *array * max - sum;
while (delta != 0) {
for (i = 0; i < max; i++) {
delta = compute(array, max) - sum;
pp = prior_prime(array[ i]);
dp = array[ i] - pp;
if (dp == delta) {
array[ i] = pp;
return ;
} else if (dp < delta)
array[ i] = pp;
else
array[ i] = next_prime(array[ i]);
}
delta = compute(array, max) - sum;
}
}
int main(int argc, char *argv[])
{
if (argc < 3) return 0;
int sum = atoi(argv[1]);
int n = atoi(argv[2]);
int *array = new_array(sum, n);
register int i;
build_sum_vector(array, sum, n);
for (i = 0; i < n; i++)
printf("%-5d ", array[ i]);
putchar('\n');
return 0;
}
1. A função new_array() cria um vetor com n elementos (definidos pelo usuário) primos cuja soma seja a menor possível menor que a soma total fornecida pelo usuário. Ou seja, caso seja fornecido uma soma 186 e um número total de parcelas 10, o vetor será inicializado com 10 elementos 19. 19 é o menor primo que multiplicado por 10 resultará em na menor soma possível maior que 186. Dessa maneira, construí um quadrado de Young. (bem abstrato, eu sei).
2. A função build_sum_vector() vai começar analisando a diferença entre a soma fornecida pelo usuário e a soma atual dos elementos. Essa diferença eu chamo de DELTA.
3. Enquanto DELTA for diferente de zero ele vai executar o bloco que tenta definir os primos.
4. O loop interno percorre todos os elementos do array. Primeiro, ele recaldula o DELTA, depois acha o primeiro primo abaixo do elemento atual com prior_prime() e calcula a diferença entre os dois. Essa diferença entre o elemento atual e o primo anterior a dele é DELTA_PRIMO.
5. Se o DELTA_PRIMOS for igual ao DELTA, OK!, encontrou uma combinação que satisfaz os critérios definidos pelo usuário.
6. Caso contrário, se DELTA_PRIMOS for
menor que DELTA, precisamos reduzir ainda mais nossos elementos, portanto salva-se o resultado e realizamos essas operações denovo (4, 5).
7. Caso o DELTA_PRIMOS seja
MAIOR QUE DELTA, precisamos aumentar o número primo atual, e fazemos isso usando next_prime().
--
is_prime, next_prime, prior_prime e compute são bem auto explicativas.
Tenha em mente que esse programa está *LONGE* de ser eficiente.
Apenas pra você ter uma idéia de como pode fazer.
Compilação:
$ CFLAGS=-O3 make prime_sum
$ ./prime_sum 186 10
17 17 19 19 19 19 19 19 19 19
$
Qualquer coisa posta denovo,
Enzo Ferber
[]'s
[]'s
$ cat codigo.c | indent -kr -i8
$ man indent
"(...)all right-thinking people know that (a) K&R are _right_ and (b) K&R are right." - linux/Documentation/CodingStyle - TORVALDS, Linus.