Ir ao conteúdo
  • Cadastre-se

C encontre pares de numeros amigos


Ir à solução Resolvido por jaireugenio,

Posts recomendados

boa tarde.

meu professor passou uma atividade onde tenho que encontra os pares de números amigos, mas meu código ficar repetindo o primeiro par e nunca procura os outros. 

#include<stdio.h>
#include<stdlib.h>
 
int amigo(int n1,int n2){
    int div1=1,div2=1,soma1=0,soma2=0;
    while(n1>=div1*2){
        if(n1%div1==0){
            soma1=soma1+div1;
        }
        div1++;
    }
    while(n2>=div2*2){
        if(n2%div2==0){
            soma2=soma2+div2;
        }
        div2++;
    }
    if(soma1==n2 && soma2==n1){ //neste caso sao amigos
        return 1;
    }
    return 0;
}
int main(){
   
   int x, y,f=220,k, num1,num2;
   scanf("%d", &x);
   for(y=1; y<=x; y++){ //repetir a quant de amigos a procurar
       num1=f;
       num2=num1;
       while(num1){
           while(num2){
                //printf("%d %d\n",num1, num2);
                num2++;
                if(amigo(num1,num2)==1){ 
                    f=num1;k=num2;
                    printf("(%d,%d)",num1,num2);
                    num1=0;num2=0;
                }
           }
           num1++;
       }
       
       
       
   }
}

main (1).zip

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@jaireugenio    seu programa está em loop infinito , por que você colocou a condição de saida do while como "num1"  igual a zero  , e isso nunca acontece pois sempre que é zero recebe incremento  .

while(num1)  /// repita enquanto for diferente de zero
{
  while(num2)
  {
    if(amigo(num1,num2)==1)
    { 
      f = num1;
      k = num2;
      printf("(%d,%d)",num1,num2);
      num1 = 0; /// num1 recebe valor zero
      num2 = 0;
    }
    num1++; /// incrementa, e assim nunca sairA desse Loop etherno
  }
}

 

Link para o comentário
Compartilhar em outros sites

@devair1010 alguma dica para resolver esse problema? de td forma q mexo o código para de mostra até o primeiro par.

 

 

 

olhei esse código com um cara que estava tendo uma questão parecida com a minha e dei uma adaptada, agora o único problema e q ele ficar repetindo os pares

#include <stdio.h>
int main ()
{
    int n, divisor, r, soma1, soma2, y, x;
    scanf("%d", &x);
    if(x>3){y=x*1500;}
    else y=x*1000;
    for (n = 2; n <= y; n++)
    {        
        soma1 = 1;
        for (divisor = 2; divisor <= n/2; divisor++)
        {            
            if (n % divisor == 0) soma1+=divisor; //calcula a soma dos divisores
        }
        soma2 = 1;
        if (soma1 != n) for (divisor = 2; divisor <= soma1/2; divisor++)
        {            
            if (soma1 % divisor == 0) soma2+=divisor; //calcula a soma dos divisores
        }
        if (soma2 == n) //verificar se a soma dos divisores eh igual ao numero
        {
            printf("(%d,%d)\n",n, soma1);
        }
        
    }
    return 0;
}

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@jaireugenio   para esse código não repetir os mesmos números você pode colocar uma variável que armazena os números encontrados e assim evitar imprimi los novamente ,  porém não sei se esses números encontrados pelo programa são realmente números amigos ,  e com essa modificação seu código ficou assim  :

#define     _WIN32_WINNT 0x600
#define     _h GetStdHandle(STD_OUTPUT_HANDLE)
#include    <stdio.h>
#include    <conio.h>
#include    <iso646.h>
#include    <stdlib.h>
#include    <string.h>
#include    <windows.h>
#include    <math.h>
#include    <time.h>
#include    <stdbool.h>
#include    <locale.h>
char cor( int, int );
int main(int argc, char* argv[] )
{
    srand(time(NULL));
    int letra,fundo;
    CONSOLE_SCREEN_BUFFER_INFO _c                            ;
    if( GetConsoleScreenBufferInfo     ( _h, & _c )          )
    {
        letra = (   _c.wAttributes & 0xFF )            & 0x0F;
        fundo = ( ( _c.wAttributes & 0xFF ) >> 4    )  & 0x0F;
    }
    cor(12,14);
    setlocale(LC_ALL,"");
    ///-------------------------------------------------------

    int n, divisor, r, soma1, soma2, y, x;
    int flag = 0;
    scanf("%d", &x);
    if(x>3)
    {
        y=x*1500;
    }
    else
      y=x*1000;
    for (n = 2; n <= y; n++)
    {
        soma1 = 1;
        for (divisor = 2; divisor <= n/2; divisor++)
        {
            if (n % divisor == 0) soma1+=divisor; //calcula a soma dos divisores
        }
        soma2 = 1;
        if (soma1 != n)
          for (divisor = 2; divisor <= soma1/2; divisor++)
          {
            if (soma1 % divisor == 0) soma2+=divisor; //calcula a soma dos divisores
          }
        if (soma2 == n && flag != n) //verificar se a soma dos divisores eh igual ao numero
        {
          printf("  (%7d,%7d)  \n",n, soma1);
          flag = soma1; /// armazena para q não repita esses mesmos num's
        }

    }

    for(int f=0; f<10; f++) Beep(rand()%3000,rand()%150+150);

    ///-------------------------------------------------------
    cor(letra,fundo);
    printf("\n\n\n");
    return   0;
}
char cor( int L, int F )
{
    SetConsoleTextAttribute( _h, L +( F << 4 ) );
}

 

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Uma solução depende da adição (ou soma) dos divisores.

 

Se fosse para mim, tu me satisfarias com uma função, uma que determine aquela soma.

 

Isto abaixo tem potencial para declarar essa função.

Em 13/04/2024 às 17:18, jaireugenio disse:
    while(n2>=div2*2){
        if(n2%div2==0){
            soma2=soma2+div2;
        }
        div2++;
    }

~x~

Em 13/04/2024 às 17:18, jaireugenio disse:
if(soma1==n2 && soma2==n1){ //neste caso sao amigos

Só que não; porque há n1 == n2 ou n1>n2 e neste caso eles não são amigos ou são amigos repetidos.

 

Suponho que uma solução seja a determinação de pares amigos, porém teu código-fonte me inspira muito mais uma checagem: checa-se n1 e n2 são amigos. Isso me parece pouco certo!

 

Espero mais por uma determinação do amigo a partir de um argumento como ordinal.

 

Por exemplo:

amigos (1);/*
            * Isto produzirá 220 284,
            * o primeiro par de amigos
            */

 

Suponho que assim teu professor ficará satisfeito — eu ficaria 🙂 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Eu concordo 👍

Em 14/04/2024 às 15:23, devair1010 disse:

Para esse código não repetir os mesmos números você pode colocar uma variável que armazena os números encontrados e assim evitar imprimi los novamente

 

E, supostamente, será a partir do 10⁠º número amigável que o custo do cálculo aumentará; há outra estratégia para minuir o tempo de produção, gravar no disco (tabela.txt) os novos números gerados e servi-lo como a tabela de consulta e agilizar a produção naquela função para índices menores que os que já existem |

 

Por exemplo

amigos (10);/*
             * Isto gera e grava (.txt) 10 números amigavéis
             * e produz somente o 10o número no simulador
             */

 

Se chamasse a função para índices ≤ 10, sua resposta viria do arquivo (.txt). Enquanto, para índices maiores que 10, a ação é gravar no arquivo todos os números até o índice no argumento, e produzi-lo.

 

É algo que, sem pressa, qualquer um consegue essa expressão em tempo (resposta); -- uma resposta que, para mim, é\seria das boas.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Em 14/04/2024 às 15:23, devair1010 disse:

porém não sei se esses números encontrados pelo programa são realmente números amigos

Abaixo, trago-lhes a lista com os 40 primeiros números amigáveis — para simples conferência.

 

amigos.txt

01. 220 	280
02. 1184 	1210
03. 2620 	2924
04. 5020 	5564
05. 6232 	6368
06. 10744 	10856
07. 12285 	14595
08. 17296 	18416
09. 63020 	76084
10. 66928 	66992
11. 67095 	71145
12. 69615 	87633
13. 79750 	88730
14. 100485 	124155
15. 122265 	139815
16. 122368 	123152
17. 141664 	153176
18. 142310 	168730
19. 171856 	176336
20. 176272 	180848
21. 185368 	203432
22. 196724 	202444
23. 280540 	365084
24. 308620 	389924
25. 319550 	430402
26. 356408 	399592
27. 437456 	455344
28. 469028 	486178
29. 503056 	514736
30. 522405 	525915
31. 600392 	669688
32. 609928 	686072
33. 624184 	691256
34. 635624 	712216
35. 643336 	652664
36. 667964 	783556
37. 726104 	796696
38. 802725 	863835
39. 879712 	901424
40. 898216 	980984

 

  • Amei 1
Link para o comentário
Compartilhar em outros sites

Amizade entre números
 

Esse nome é um tanto estranho e não corresponde à noção de amizade: Um número é dito amigo se a soma de seus divisores é igual à soma dos divisores do valor dessa soma.

Assim, se um número é amigo ele tem um único amigo. Nada social. E aparentemente um número não pode ser amigo dele mesmo, caso do óbvio 1 e do 28 por exemplo, já que 28 tem 1,2,4,7 e 14 como divisores e a soma é... 28.

 

Claro que a amizade é comutativa, já que a igualdade é comutativa. O primeiro par de amigos seria [220,284], sem considerar [1,1] e [28,28]:

  • os divisores de 220 são 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 e 110, e a soma é 284
  • os divisores de 284 são 1, 2, 4, 71 e 142, e a soma é 220

Assim se `a` é amigo de `b`, então `b` é amigo de `a`. E eles não tem outros amigos...

 

De volta ao código original

 

int amigo(int n1, int n2)
{
    int div1 = 1, div2 = 1, soma1 = 0, soma2 = 0;
    while (n1 >= div1 * 2)
    {
        if (n1 % div1 == 0) { soma1 = soma1 + div1; }
        div1++;
    }
    while (n2 >= div2 * 2)
    {
        if (n2 % div2 == 0) { soma2 = soma2 + div2; }
        div2++;
    }
    if (soma1 == n2 && soma2 == n1)
    {  // neste caso sao amigos
        return 1;
    }
    return 0;
}


Isso parece que está certo na determinação da relação, mas a lógica nem tanto. Não sou eu que vou corrigir isso, mas considere:

Se um número é amigo está claro de quem ele é amigo. Ou tem um ou não tem nenhum.

Não é nada esperto procurar um por um. Veja o caso do tal 220: a soma é 284. A única chance de ser esse um número amigo é de a soma dos divisores de 284 dar 220. E é.

 

Então esse loop no programa não tem muito sentido:

 

int main()
{
    int x, y, f = 220, k, num1, num2;
    scanf("%d", &x);
    for (y = 1; y <= x; y++)
    {  // repetir a quant de amigos a procurar
        num1 = f;
        num2 = num1;
        while (num1)
        {
            while (num2)
            {
                // printf("%d %d\n",num1, num2);
                num2++;
                if (amigo(num1, num2) == 1)
                {
                    f = num1;
                    k = num2;
                    printf("(%d,%d)", num1, num2);
                    num1 = 0;
                    num2 = 0;
                }
            }
            num1++;
        }
    }
    return 0;
}


De nada adianta testar

 

	amigo(num1, num2) 

 

para todos os pares possíveis se só tem uma possível solução...

 

exemplo

 

Essa função retorna a soma dos divisores de um número. Note que em C size_t é melhor que int. Não há sinal nesses números.

 

size_t soma_div(size_t val)
{
    size_t n_div = 1;
    size_t soma  = 1;
    // os pares a*b
    size_t div = 2;
    size_t q   = 0;
    do {
        q = val / div;
        if (q * div == val)
        {   // quadrado perfeito?
            if (q != div) soma += div;
            soma += q;
        }
        div += 1;
    } while (q >= div);
    return soma;
}


 

Se ela retorna a soma então essa outra

 

size_t is_friend(size_t val)
{
    size_t soma = soma_div(val);
    if (soma <= val) return 0;
    if (soma_div(soma) == val) return soma;
    return 0;
}


retorna 0 se o número não é amigo, ou retorna o número amigo. Mais simples de ler e entender. E evita a repetição dos pares, e também casos como o do 28, amigo de si mesmo. Basta uma linha a mais.


exemplo completo

 

#define DEF_LIMITE 81 

#include<stdio.h>
#include <stdlib.h>

size_t is_friend(size_t val);
size_t soma_div(size_t n);

int main(int argc, char** argv)
{
    size_t n_pares = 10;
    size_t temp    = 0;
    if (argc > 1)
    {  // limita o total de pares para não ter que esperar muito
        // nem pensar em overflow
        temp = atoi(argv[1]);
        if ((temp != 0) && (temp < DEF_LIMITE)) n_pares = temp;
    }
    printf(
        "\nListando os primeiros %llu pares de numeros "
        "amigos\n\n",
        n_pares);
    size_t outro = 0;
    size_t N     = 2;
    for (size_t par = 0; par < n_pares;)
    {
        outro = is_friend(N);
        if (outro != 0)
            {
                printf(
                    "%4llu:  [%llu,%llu]\n", 1 + par, N,
                    outro);
                ++par;
            };
        ++N;  // proximo candidato
    };  // for
    return 0;
}

size_t is_friend(size_t val)
{
    size_t soma = soma_div(val);
    if (soma <= val) return 0;
    if (soma_div(soma) == val) return soma;
    return 0;
}

inline size_t soma_div(size_t val)
{
    size_t n_div = 1;
    size_t soma  = 1;
    // os pares a*b
    size_t div = 2;
    size_t q   = 0;
    do {
        q = val / div;
        if (q * div == val)
        {
            // quadrado perfeito?
            if (q != div) soma += div;
            soma += q;
        }
        div += 1;
    } while (q >= div);
    return soma;
}

 

saída do exemplo

C:\Clube\p.exe

Listando os primeiros 10 pares de numeros amigos

   1:  [220,284]
   2:  [1184,1210]
   3:  [2620,2924]
   4:  [5020,5564]
   5:  [6232,6368]
   6:  [10744,10856]
   7:  [12285,14595]
   8:  [17296,18416]
   9:  [63020,76084]
  10:  [66928,66992]

C:\Clube\p.exe 80

Listando os primeiros 80 pares de numeros amigos

   1:  [220,284]
   2:  [1184,1210]
   3:  [2620,2924]
   4:  [5020,5564]
   5:  [6232,6368]
   6:  [10744,10856]
   7:  [12285,14595]
   8:  [17296,18416]
   9:  [63020,76084]
  10:  [66928,66992]
  11:  [67095,71145]
  12:  [69615,87633]
  13:  [79750,88730]
  14:  [100485,124155]
  15:  [122265,139815]
  16:  [122368,123152]
  17:  [141664,153176]
  18:  [142310,168730]
  19:  [171856,176336]
  20:  [176272,180848]
  21:  [185368,203432]
  22:  [196724,202444]
  23:  [280540,365084]
  24:  [308620,389924]
  25:  [319550,430402]
  26:  [356408,399592]
  27:  [437456,455344]
  28:  [469028,486178]
  29:  [503056,514736]
  30:  [522405,525915]
  31:  [600392,669688]
  32:  [609928,686072]
  33:  [624184,691256]
  34:  [635624,712216]
  35:  [643336,652664]
  36:  [667964,783556]
  37:  [726104,796696]
  38:  [802725,863835]
  39:  [879712,901424]
  40:  [898216,980984]
  41:  [947835,1125765]
  42:  [998104,1043096]
  43:  [1077890,1099390]
  44:  [1154450,1189150]
  45:  [1156870,1292570]
  46:  [1175265,1438983]
  47:  [1185376,1286744]
  48:  [1280565,1340235]
  49:  [1328470,1483850]
  50:  [1358595,1486845]
  51:  [1392368,1464592]
  52:  [1466150,1747930]
  53:  [1468324,1749212]
  54:  [1511930,1598470]
  55:  [1669910,2062570]
  56:  [1798875,1870245]
  57:  [2082464,2090656]
  58:  [2236570,2429030]
  59:  [2652728,2941672]
  60:  [2723792,2874064]
  61:  [2728726,3077354]
  62:  [2739704,2928136]
  63:  [2802416,2947216]
  64:  [2803580,3716164]
  65:  [3276856,3721544]
  66:  [3606850,3892670]
  67:  [3786904,4300136]
  68:  [3805264,4006736]
  69:  [4238984,4314616]
  70:  [4246130,4488910]
  71:  [4259750,4445050]
  72:  [4482765,5120595]
  73:  [4532710,6135962]
  74:  [4604776,5162744]
  75:  [5123090,5504110]
  76:  [5147032,5843048]
  77:  [5232010,5799542]
  78:  [5357625,5684679]
  79:  [5385310,5812130]
  80:  [5459176,5495264]

 

É mais simples --- e esperado --- usar a linha de comando para argumentos óbvios, e ter um padrão para quando o cara não digita nada. Esse exemplo assume 10 pares se o cara não digitar nada, e limita em 80 o total máximo, porque demora e o total de pares nada muda para o programa.

  • Amei 1
  • Triste 1
Link para o comentário
Compartilhar em outros sites

11 horas atrás, arfneto disse:

Essa função retorna a soma dos divisores de um número. Note que em C size_t é melhor que int. Não há sinal nesses números.

 

size_t soma_div(size_t val)
{
    size_t n_div = 1;
    size_t soma  = 1;
    // os pares a*b
    size_t div = 2;
    size_t q   = 0;
    do {
        q = val / div;
        if (q * div == val)
        {   // quadrado perfeito?
            if (q != div) soma += div;
            soma += q;
        }
        div += 1;
    } while (q >= div);
    return soma;
}

 

 

[OPINIÃO]

Suponho que isso satisfará o professor, e no mínimo tirará do autor do tópico uma oportunidade de aprender algo com erros (e de qualquer outro também).

 

Hoje em dia, considero essa categoria de postagem um atraso.

 

Mas, solução é boa.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

[ligeiramente off-topic 🙂 @Ansi C Sabe o que é a "coleção schaum"?   

 

image.thumb.png.33a1dd6a3c417a8b94f7ea1bf9849f2e.png

Passados 10 dias da pergunta achei que podia ter uma referência aqui sobre essa questão e sobre o modo de escrever isso.

 

Na minha opinião você está diminuindo a capacidade dos iniciantes.

 

Sempre tem os caras que não vão nem tentar fazer antes de tentar copiar de toda possível parte.

 

O forum é uma possível parte, por definição e missão.

 

As pessoas vem para o forum --- e empresas que anunciam no site --- por essa razão.

 

Stack Overflow e o Stack Exchange em geral são a referência do planeta para isso.

 

2 horas atrás, Ansi C disse:

no mínimo tirará do autor do tópico uma oportunidade de aprender algo com erros (e de qualquer outro também)

 

Mas tem gente que aprende com referências. 

 

Em 22/04/2024 às 09:48, devair1010 disse:

obrigado , creio que você teve muito dificuldade para obter essa listas , pois já pesquisei bastante e não encontrei em nenhum lugar uma lista igual a essa , mas apenas informações sobre como adquirir um para de número amigos

 

Pode usar o exemplo que eu escrevi e salvar tal lista para até onde size_t comporta. Para números maiores pode só reescrever esse programa em uma linguagem que tenha inteiros de maior tamanho, como Python ou java, ou escrever (ou usar de alguém) uma biblioteca de aritmética para inteiros em C. Não é complicado.

  • Obrigado 1
  • Triste 1
Link para o comentário
Compartilhar em outros sites

1 hora atrás, arfneto disse:

Mas tem gente que aprende com referências.

Você quis dizer com exercícios resolvidos?

 

Ah! Não tem não, mas essa é sua opinião e respeito.

Apesar de discordar dela:

 

 

Em 22/04/2024 às 09:48, devair1010 disse:

apenas informações sobre como adquirir um para de número amigos

Para a maioria já é o suficiente ter o como determinar 1 par - e fica como exercício expressar o 'como adquirir um par de números  ... 

 

Especificamente, expressar com a C - sem pressa qualquer um faz essa "missão" 😄 

 

 

1 hora atrás, arfneto disse:

Não é complicado.

Ai sim, eu concordo.

  • Curtir 1
  • Haha 1
Link para o comentário
Compartilhar em outros sites

  • Solução
Em 14/04/2024 às 15:23, devair1010 disse:

@jaireugenio   para esse código não repetir os mesmos números você pode colocar uma variável que armazena os números encontrados e assim evitar imprimi los novamente ,  porém não sei se esses números encontrados pelo programa são realmente números amigos ,  e com essa modificação seu código ficou assim  :

#define     _WIN32_WINNT 0x600
#define     _h GetStdHandle(STD_OUTPUT_HANDLE)
#include    <stdio.h>
#include    <conio.h>
#include    <iso646.h>
#include    <stdlib.h>
#include    <string.h>
#include    <windows.h>
#include    <math.h>
#include    <time.h>
#include    <stdbool.h>
#include    <locale.h>
char cor( int, int );
int main(int argc, char* argv[] )
{
    srand(time(NULL));
    int letra,fundo;
    CONSOLE_SCREEN_BUFFER_INFO _c                            ;
    if( GetConsoleScreenBufferInfo     ( _h, & _c )          )
    {
        letra = (   _c.wAttributes & 0xFF )            & 0x0F;
        fundo = ( ( _c.wAttributes & 0xFF ) >> 4    )  & 0x0F;
    }
    cor(12,14);
    setlocale(LC_ALL,"");
    ///-------------------------------------------------------

    int n, divisor, r, soma1, soma2, y, x;
    int flag = 0;
    scanf("%d", &x);
    if(x>3)
    {
        y=x*1500;
    }
    else
      y=x*1000;
    for (n = 2; n <= y; n++)
    {
        soma1 = 1;
        for (divisor = 2; divisor <= n/2; divisor++)
        {
            if (n % divisor == 0) soma1+=divisor; //calcula a soma dos divisores
        }
        soma2 = 1;
        if (soma1 != n)
          for (divisor = 2; divisor <= soma1/2; divisor++)
          {
            if (soma1 % divisor == 0) soma2+=divisor; //calcula a soma dos divisores
          }
        if (soma2 == n && flag != n) //verificar se a soma dos divisores eh igual ao numero
        {
          printf("  (%7d,%7d)  \n",n, soma1);
          flag = soma1; /// armazena para q não repita esses mesmos num's
        }

    }

    for(int f=0; f<10; f++) Beep(rand()%3000,rand()%150+150);

    ///-------------------------------------------------------
    cor(letra,fundo);
    printf("\n\n\n");
    return   0;
}
char cor( int L, int F )
{
    SetConsoleTextAttribute( _h, L +( F << 4 ) );
}

 

calma lá cara, eu programa a pouco mais de uma semana as únicas bibliotecas q sei são stdio e math, então não entendi  a maior parte do seu código resolvi essa questão desse jeito

 

#include <stdio.h>

int main ()

{

int n, divisor, r, soma1, soma2, y, x;

scanf("%d", &x);

if(x>3){y=x*1500;}

else y=x*1000;

for (n = 2; n <= y; n++)

{

soma1 = 1;

for (divisor = 2; divisor <= n/2; divisor++)

{

if (n % divisor == 0) soma1+=divisor; //calcula a soma dos divisores

}

soma2 = 1;

if (soma1 != n) for (divisor = 2; divisor <= soma1/2; divisor++)

{

if (soma1 % divisor == 0) soma2+=divisor; //calcula a soma dos divisores

}

if (soma2 == n && n < soma1) //verificar se a soma dos divisores eh igual ao numero

{

printf("(%d,%d)\n",n, soma1);

}

}

return 0;

}

 

teria vários problemas  nesse código se fosse minha intenção procura tds os números amigos mas como eu tenho q acha até no máximo 9 pares, esse código dá conta do recado.

  • Obrigado 2
Link para o comentário
Compartilhar em outros sites

Em 14/04/2024 às 15:23, devair1010 disse:

 para esse código não repetir os mesmos números você pode colocar uma variável que armazena os números encontrados e assim evitar imprimi los novamente

 

Sim, se pode usar um vetor para isso, mas também pode mostrar o par apenas na primeira ou segunda vez em que ele aparece, já que os elementos são diferentes em cada par. 

 

@jaireugenio use o botão code, como está explicado no primeiro post desse forum. 

 

Veja a diferença

 

Em 14/04/2024 às 09:54, jaireugenio disse:

um cara que estava tendo uma questão parecida com a minha e dei uma adaptada, agora o único problema e q ele ficar repetindo os pares

 

Pois é: esse é o código de "um cara", como você citou, usando o tal botão code:

 

#include <stdio.h>
int main()
{
    int n, divisor, r, soma1, soma2, y, x;
    scanf("%d", &x);
    if (x > 3) { y = x * 1500; }
    else
        y = x * 1000;
    for (n = 2; n <= y; n++)
    {
        soma1 = 1;
        for (divisor = 2; divisor <= n / 2; divisor++)
        {
            if (n % divisor == 0)
                soma1 += divisor;  // calcula a soma dos
                                   // divisores
        }
        soma2 = 1;
        if (soma1 != n)
            for (divisor = 2; divisor <= soma1 / 2;
                 divisor++)
            {
                if (soma1 % divisor == 0)
                    soma2 += divisor;  // calcula a soma dos
                                       // divisores
            }
        if (soma2 == n)  // verificar se a soma dos
                         // divisores eh igual ao numero
        {
            printf("(%d,%d)\n", n, soma1);
        }
    }
    return 0;
}

 

O código "adaptado" como você disse

 

#include <stdio.h>

int main()
{
    int n, divisor, r, soma1, soma2, y, x;
    scanf("%d", &x);
    if (x > 3) { y = x * 1500; }
    else
        y = x * 1000;
    for (n = 2; n <= y; n++)
    {
        soma1 = 1;
        for (divisor = 2; divisor <= n / 2; divisor++)
        {
            if (n % divisor == 0)
                soma1 += divisor;  // calcula a soma dos
                                   // divisores
        }
        soma2 = 1;
        if (soma1 != n)
            for (divisor = 2; divisor <= soma1 / 2;
                 divisor++)
            {
                if (soma1 % divisor == 0)
                    soma2 += divisor;  // calcula a soma dos
                                       // divisores
            }
        if (soma2 == n &&
            n < soma1)  // verificar se a soma dos divisores
                        // eh igual ao numero
        {
            printf("(%d,%d)\n", n, soma1);
        }
    }
    return 0;
}

 

A sua adaptação:

 

Essa é a tela do IDE do Visual Studio mostrando as diferenças entre o programa de "um cara que estava tendo uma questão parecida com a minha" como disse, e o seu programa solução:

 

image.png.05c0031890c16fa4543a1764af20f06c.png

 

acrescentou o comentário e a condição no if. Muito bem.

 

Do post #9:

 

image.png.acc5f0f6516be815077fa9632eaf0e54.png

 

E aaí está a condição.

 

Sobre o código FINAL

 

Bom que conseguiu adaptar o programa e chegar a uma solução, mudando apenas 2 linhas!

 

    if (x > 3) { y = x * 1500; }
    else
        y = x * 1000;

 

Sabe explicar de onde vem esses números? Não seria mais simples contar os pares, de um em um? Seu professor pode querer saber...

 

Sei que é a solução de "um cara" mas você ao copiar podia usar chaves de um modo mais consistente. Não precisa delas em nenhuma das condições, mas se vai usar use duas ou nenhuma...

 

    if (x > 3)
        y = x * 1500;
    else
        y = x * 1000;

// ou

	if (x > 3)
	{ 
		y = x * 1500;
	}
	else
	{
		y = x * 1000;
	}

 

  • leia o manual: scanf() retorna um int. TESTE. Seu professor pode teclar um 'x' lá só pra ver se você pensou nisso.
  • é muito chato ficar olhando para uma tela onde não tem nada escrito e imaginar que tem que digitar um número inteiro positivo entre 1 e 9 ( inclusive). Já pensou em escrever isso numa mensagem, usando aquele comando printf explicando o que o cara deve digitar? Leu o que eu expliquei sobe ser esperado digitar o número JUNTO com o nome do programa?
  • para que serve 'r'? Seu professor pode querer saber. Veja as mensagens de seu compilador.

 

1 hora atrás, jaireugenio disse:

eria vários problemas  nesse código se fosse minha intenção procura tds os números amigos mas como eu tenho q acha até no máximo 9 pares, esse código dá conta do recado

 

Sabe o que acontece se o cara digitar por exemplo 500? Testou "seu" programa?

 

 

  • Obrigado 1
  • Haha 1
Link para o comentário
Compartilhar em outros sites

4 horas atrás, jaireugenio disse:

eu programa a pouco mais de uma semana

Eu compreendi você "assim que bati com os olhos..."

 

Enfim,

 

de fato, o programa produziu - para mim, somente isso bastaria. Modifiquei-o sutilmente nos nomes das variáveis com termos que considero didáticos - o programa permanece (o mesmo).

 

/*
* FÓRUM CLUBE DO HARDWARE --- CdH
*
* @jaireeugenio
* Membro Junior
* 2024
*/
#include <stdio.h>
int main (){
  int divisor ,soma ,amigo ,x= 3;
  
  scanf ("%d",&x);
  x*= (x>3)? 1500 : 1000;

  for (int numero= 2 ; numero<=x ; numero++) {
    amigo= 1;
    for (divisor= 2; divisor<=(numero/ 2); divisor++) {
      if ((numero% divisor)==0) amigo+= divisor; //calcula a soma dos divisores
      }
    soma= 1;
    if (amigo!=numero)
      for (divisor= 2; divisor<=(amigo/ 2); divisor++) {
        if ((amigo% divisor)==0) soma+= divisor;
        }
    if (numero==soma && numero<amigo) {
       printf("(%d,%d)\n",numero,amigo);
       }
    }
  putchar ('\n');
  return 0;
  }

 

*Prefiro um contador à expressão x. 🙂 

 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@jaireugenio     desculpe , por esses comandos esquisitões , mas eles são comandos simples e não fazem nada demais  não,   apenas manipula som e cores no console, e aqui no codeblock's esse esboço de Algorítimo com essa estrutura e várias bibliotecas já é criado automáticamente ao iniciar um novo arquivo ou projeto, e na hora de postar não removi esses comandos , e nesse código eles poderiam ser excluídos e não afetaria em nada o funcionamento de seu código ,  e você disse que precisa encontrar 9 números ,  porém nesse novo código que postou , se na entrada for informado "9" , só mostrará "7" e sendo que para mostrar os 9 números precisa informar "43" logo na entrada ,  aqui seu código para apresentar também a Quantidade encontrada :

 

#include <stdio.h>
int main ()
{
    int    n     = 0, divisor = 0;
    size_t soma1 = 0, soma2   = 0;
    size_t y     = 0, x       = 0;
    size_t cont  = 0, r       = 0;
    printf("Encontrar Quantos nUmeros Amigos ");
    scanf("%d", &x);
    if( x > 3 )
        y = x * 1500;
    else
        y = x * 1000;
    for (n = 2; n <= y; n++)
    {
        soma1 = 1;
        for (divisor = 2; divisor <= n/2; divisor++)
        {
            if (n % divisor == 0) soma1+=divisor; //calcula a soma dos divisores
        }
        soma2 = 1;
        if (soma1 != n)
            for (divisor = 2; divisor <= soma1/2; divisor++)
            {
                if (soma1 % divisor == 0)
                    soma2 += divisor; //calcula a soma dos divisores
            }
        if (soma2 == n && n < soma1) //verificar se a soma dos divisores eh igual ao numero
        {
            cont += 1;
            printf(" %d -> (%7d,%7d)\n",cont, n, soma1);
        }
    }
    return 0;
}

 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

53 minutos atrás, devair1010 disse:

nesse novo código que postou , se na entrada for informado "9" , só mostrará "7" e sendo que para mostrar os 9 números precisa informar "43" logo na entrada

 

Olá @devair1010

 

Somente isso

É, o que é: x não representa, explicitamente, a quantia de números amigos solicitados — como aparentemente supunhas —, mas sim, x representa com os coeficientes a definição de y, sendo y um máximo de n (o amigo do amigo)

 

 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites


Essa condição é, digamos, uma bobagem:

 

   if (x > 3)
        y = x * 1500;
    else
        y = x * 1000;

 

Esse programa foi, segundo o autor (post #3), baseado em

Citação

"um cara que estava tendo uma questão parecida com a minha e dei uma adaptada, agora o único problema e q ele ficar repetindo os pares"

 

Provavelmente isso foi copiado desse post no Stack Overflow, de 2017.

 

Só que lá o objetivo era listar os números até um limite 😄 
 

Escreva o programa para calcular todos os números friends de 2 para N.

Exemplo:

Se a entrada for N = 1500 a saída deverá ser: (284, 220), (1210, 1184)

 

Só que, sem entender a diferença entre os enunciados, o "cara" copiou até o 1500, a constante exemplo do programa original. Depois, vendo que a conta não batia alguém colocou uma "correção de curso" e usou `1000` para `x<3`. Veja na planilha:

planilha.jpg.1828754b09c93fffa33efe7f9ab933dc.jpg

 

O problema é que para x = 2 o original daria `4500` e acabaria mostrando 3 números e não dois, já que    
 

        2620 < 4500 < 5020


 

Mas parou aí. Não houve preocupação em parar o programa em 9 números, ou mesmo em parar o programa um dia...

 

Claro que a mesma preocupação não apareceu para testa os valores digitados e nem para decidir sobre o final do programa em 9 ou `N` pares de amigos.

 

sobre essa nova versão @devair1010


Claro que temos progressos, tem até uma educada mensagem avisando o usuário do que ele deve digitar...

 

Mas: 

 

  • deixou o tal `r` lá sem uso, apesar do compilador ter avisado
  • criou um contador mas não apagou essa fórmula bobinha e simplesmente usou `cont` para... contar os números já listados, sem fazer o simples e parar o programa na hora certa
  • não corrigiu os erros nos especificadores de `printf` para os valores que foram trocados de `int` para `size_t`
  • não declarou `n` no próprio corpo do `for`, algo que foi corrigido em `C` ainda nos anos 80. Ou mesmo `divisor`
  • entenda esse código:
        for (divisor = 2; divisor <= n / 2; divisor++)
        {
            if (n % divisor == 0) soma1 += divisor; //calcula a soma dos divisores
        }
        soma2 = 1;
        if (soma1 != n)
            for (divisor = 2; divisor <= soma1 / 2; divisor++)
            {
                if (soma1 % divisor == 0)
                    soma2 += divisor; //calcula a soma dos divisores
            }


   é claro que é o mesmo código nos dois for: dado um número retorna a soma de seus divisores. Evite a todo custo repetir código assim, logo na linha de baixo. Use funções, como eu mostrei. Isso se chama de princípio  DRY na literatura: Don't Repeat Yourself.

 

Do exemplo que eu escrevi:
 

size_t is_friend(size_t val)
{
    size_t soma = soma_div(val);
    if (soma <= val) return 0;
    if (soma_div(soma) == val) return soma;
    return 0;
}


É mais simples de entender, e continua tendo a função `soma()` para outros usos.

E considera o par na primeira vez em que aparece, `[a,b]` quando `a<b` e já despreza o egocêntrico caso dos números que são amigos deles próprios, como `6` e `28`.

 

  •  Use a linha de comando. é muito chato rodar o programa e ficar esperando ele perguntar algo se já sabe o que ele vai perguntar.
  • como eu já disse, `scanf()` retorna um `int`. Use. É mais esperto. Se o cara digitar `x` seu programa vai fazer o que? `scanf` é --- dá pra ver pelo nome --- um _scanner_ e é normal não ler nada.
  • O esperado em `C` desde o `Unix` é receber os argumentos na linha de comando e ter um padrão para o caso de o usuário não digitar nada, ou chamar uma função mostrando como usar. `usage()` é o nome clássico dessa função desde os anos 70. Imagine se o compilador perguntasse a cada vez: Quantos programas deseja compilar? Forneça o nome dos programas, um por linha e tecle ENTER...

    Outro EXEMPLO

 

  Mudando um pouco do que escreveram, para ter algo mais configurável e correto:

 

  • Usando isso, que é o mesmo código, não precisa repetir o loop, e fica muito mais legível a determinação de números amigos:
inline size_t soma_div(const size_t val)
{
    size_t soma = 1;
    for (size_t divisor = 2; divisor <= val / 2; divisor += 1)
        if (val % divisor == 0)
            soma += divisor;
    return soma;
}

size_t eh_amigo(size_t val)
{
    size_t soma = soma_div(val);
    if (soma <= val)
        return 0;
    if (soma_div(soma) == val)
        return soma;
    return 0;
}


Claro que se salvasse os números que tem amigos poderia salvar a inútil computação dele na segunda vez...

 

main() para o exemplo

 

Na prática esse é o programa principal. Só isso:

 

    for (size_t par = 0, N = 2, outro = 0; par < n_pares;)
    {
        if ((outro = eh_amigo(N)) != 0)
            printf("%4llu:  [%llu,%llu]\n", 1 + par, N, outro), ++par;
        ++N; // proximo candidato
    }; // for

 

A saída desse exemplo

 

Supondo o programa como amigos.exe...

C:\Clube do Hardware>_  ./amigos

Listando os primeiros 9 pares de numeros amigos

   1:  [220,284]
   2:  [1184,1210]
   3:  [2620,2924]
   4:  [5020,5564]
   5:  [6232,6368]
   6:  [10744,10856]
   7:  [12285,14595]
   8:  [17296,18416]
   9:  [63020,76084]

Fim
C:\Clube do Hardware>_  ./amigos 1

Listando os primeiros 1 pares de numeros amigos

   1:  [220,284]

Fim
C:\Clube do Hardware>_  ./amigos 3

Listando os primeiros 3 pares de numeros amigos

   1:  [220,284]
   2:  [1184,1210]
   3:  [2620,2924]

Fim
C:\Clube do Hardware>_  ./amigos 13

Listando os primeiros 13 pares de numeros amigos

   1:  [220,284]
   2:  [1184,1210]
   3:  [2620,2924]
   4:  [5020,5564]
   5:  [6232,6368]
   6:  [10744,10856]
   7:  [12285,14595]
   8:  [17296,18416]
   9:  [63020,76084]
  10:  [66928,66992]
  11:  [67095,71145]
  12:  [69615,87633]
  13:  [79750,88730]

Fim


Tendo um valor padrão --- e um limite interno --- e aceitando outros valores direto na linha de comando fica muito menos chato de usar. E pode usar em um script. Nunca escreva programas interativos. Só atrasa. E é chato.

 

Programa completo

 

#define LIMITE_PADRAO 9
#define MAX_PARES 80

#include <stdio.h>
#include <stdlib.h>

inline size_t soma_div(const size_t val);
size_t eh_amigo(size_t val);

int main(int argc, char **argv)
{
    size_t n_pares = LIMITE_PADRAO;
    size_t temp = 0;
    if (argc > 1)
    {
        temp = atoi(argv[1]);
        if ((temp != 0) && (temp <= MAX_PARES))
            n_pares = temp;
    }
    printf("\nListando os primeiros %llu pares de numeros "
           "amigos\n\n",
           n_pares);
    for (size_t par = 0, N = 2, outro = 0; par < n_pares;)
    {
        if ((outro = eh_amigo(N)) != 0)
            printf("%4llu:  [%llu,%llu]\n", 1 + par, N, outro), ++par;
        ++N; // proximo candidato
    }; // for
    printf("\nFim\n");
    return 0;
}

inline size_t soma_div(const size_t val)
{
    size_t soma = 1;
    for (size_t divisor = 2; divisor <= val / 2; divisor += 1)
        if (val % divisor == 0)
            soma += divisor;
    return soma;
}

size_t eh_amigo(size_t val)
{
    size_t soma = soma_div(val);
    if (soma <= val)
        return 0;
    if (soma_div(soma) == val)
        return soma;
    return 0;
}


 

  

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Em 24/04/2024 às 11:22, jaireugenio disse:

as únicas bibliotecas q sei são stdio e math, [...]

Isso acima, insinua-me um estudo a pagar na solução do exercício, se tem no apontamento, então, é requisito.

 

Dica

Apresente-o uma solução que vem com a função `sqrt

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!