Ir ao conteúdo

C Calculo da Numerologia / Linguagem C


Ir à solução Resolvido por Midori,

Posts recomendados

Postado

Boa noite pessoas lindas, estou extremamente confuso correlação ao calculo da numerologia na linguagem C, para que vocês entendam o calculo vou anexar uma imagem explicando nesse post, bem voltando, eu entendi a lógica de criar uma matriz associativa entres letras (Alfabeto) e  numero ( de 1 a 9 ) e para complementar pesquisei na internet mais sobre o assunto só que não encontrei nada, mas basicamente o programa deve pegar o nome que a pessoa digitar, e em cima do nome fazer o calculo da numerologia, vou mandar um trecho de um código que achei na internet, a lógica aparenta ser a mesma... Desde já obrigado se me ajudarem <3.
 

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



int main(){
	
const int NUM_LETTERS = 26;

struct LetterDigit{
	char letter;
	int digit;
};
LetterDigit ld[NUM_LETTERS] = {
	{'A', 1}, {'J', 1}, {'S', 1},
	{'B', 2}, {'K', 2}, {'T', 2},
	{'C', 3}, {'L', 3}, {'U', 3},
	{'D', 4}, {'M', 4}, {'V', 4},
	{'E', 5}, {'N', 5}, {'W', 5},
	{'F', 6}, {'O', 6}, {'X', 6},
	{'G', 7}, {'P', 7}, {'Y', 7},
	{'H', 8}, {'Q', 8}, {'Z', 8},
	{'I', 9}, {'R', 9},
};

int getDigitFromLetter(char c){
	int i;

	c = toupper(c);

	for(i = 0; i < NUM_LETTERS; i ++) {
		if(c == ld[i].letter)
			return ld[i].digit;
	}

	return 0;
};
}

 

numerologia.PNG

Postado

Não entendi qual a sua dúvida. Se quer replicar aquilo tem a receita escrita lá mesmo.

 

No caso da primeira soma esse programa que conseguiu é um pouco ingênuo: a soma referente ao nome pode conseguir de modo muito mais simples, usando um único vetor com as  26 letras e repetindo os números e não o contrário como o cara fez :D .

 

Depois é só um loop somando os dígitos até ficar menor que 10.

 

Postado

Para pegar os números correspondentes não precisa de estrutura e vetor com as letras do alfabeto, é só fazer o cálculo com a diferença da letra por A (65) e módulo de 9 + 1,

 

int digito(char c){
    return ((c - 'A') % 9) + 1;
}

 

  • Curtir 1
Postado
10 horas atrás, Midori disse:

Para pegar os números correspondentes não precisa de estrutura e vetor com as letras do alfabeto, é só fazer o cálculo com a diferença da letra por A (65) e módulo de 9 + 1

 

É verdade. Não precisa. Mas a sua redação está sugerindo o inverso da realidade. Entenda que "é só fazer o cálculo..." como escreveu sugere que seria melhor, ou mais simples de algum modo, escrever digito() 
 

int digito(char c){
    return ((c - 'A') % 9) + 1;
}


E usar. Mas não é. 

 

Uma redação mais perto da realidade seria: 
 

Citação

É só usar um vetor com o valor das letras do alfabeto, mas pode até escrever uma função digito() e fazer o cálculo com a diferença de 'A' para 'A' (65) e calcular o módulo e somar 1. 



E porque?

  • essa pequena função só funciona para as letras maiúsculas. Antes de tudo tem que testar 'c' para ver se está no intervalo entre 'A' e 'Z'.
  • chamar uma função custa caro
  • testar DOIS limites custa caro
  • calcular o módulo sai caro
  • se for usar minúsculas tem que fazer mais um teste, ou mudar a função.
  • no caso dos espaços por exemplo, cujo código é 32, já sabe o que vai acontecer se chamar dígito: vai retornar (-5). Toda letra vai retornar algo para essa conta, mas o resultado só faz sentido para as 26 letras maiúsculas. Então tem que testar antes de chamar. E sai caro. A função deveria retornar 0 para qualquer coisa que não fosse uma letra alvo da tabela.
  • no geral chamar uma função já é péssimo negócio. E nesse contexto vai demorar muito mais chamar a função do que fazer a conversão.

Insistindo na função digito()

 

unsigned digito2(const char c)
{
	if ((c >= 'A') && (c <= 'Z'))
       return ((c - 'A') % 9) + 1;
  
	if ((c >= 'a') && (c <= 'z'))
       return ((c - 'a') % 9) + 1;
  
	return 0;
}

 

Agora aceita as letras, sem testar antes de chamar. Economiza uns ciclos. Não aceita letras com acento, como 'ã" em Joäo no exemplo

 

A maneira otimizada: copiar e colar a tabela abaixo

 


const char idx[256] =
{

  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 000-015
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 016-031
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 032-047
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 048-063
  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   1,   2,   3,   4,   5,   6,  // 064-079
  7,   8,   9,   1,   2,   3,   4,   5,   6,   7,   8,   0,   0,   0,   0,   0,  // 080-095
  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   1,   2,   3,   4,   5,   6,  // 096-111
  7,   8,   9,   1,   2,   3,   4,   5,   6,   7,   8,   0,   0,   0,   0,   0,  // 112-127
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 128-143
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 144-159
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 160-175
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 176-191
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 192-207
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 208-223
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  // 224-239
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0   // 240-255

}; // ARFNeto '20

 

Assim em ASCII pode usar com qualquer finalidade e letra, maiuscula, minuscula ou letras acentuadas, sem atraso no processamento e aproveitando o cache do processador...

 

Esse é o simples.

 

Como saber? Num teste simples roda pouco mais de 16X mais rápido. (6% do tempo) em relação a usar um loop e a função digito() alterada. Fiz alguns testes com 1 milhão de chamadas. Poucos na verdade. É só um exemplo.

 

Como testar? Medindo, por exemplo assim:

 

double testa_forma1(unsigned N, unsigned (*f)(const char*), const char* frase)
{
	clock_t		inicio = clock();
	unsigned t = N * 1000;
	for (unsigned i = 0; i < t; i += 1)	f(frase);
	clock_t		final = clock();
	double T = (double)(final - inicio);
	//printf("%8.2f ciclos\n", T);
	return T /= CLOCKS_PER_SEC;
}


Cada chamada chama a função f 1000N vezes com a frase. Dizem que clock_t() não é nada confiável em Windows, mas no fundo nem precisava. Mas rodei em gcc 9.3 no Linux via WSL e os resultados são semelhantes.

 

A função que usei no teste, nada criativa

 

unsigned soma_via_tabela(const char* frase)
{
#include        "saida.h"
	char* p = (char*)frase;
	unsigned s = 0;
	while (*p != 0)	s += idx[(int)(*p++)];
	return s;
}


No fundo é uma função de hash(). E por construção sem chance de colisão. f(x) = v(x);

 

Claro que saida.h é a tabela acima, e claro que eu tenho um programa que gera esse código sempre que eu preciso...

 

Eis o programa, que já postei outras vezes

 

#include "stdio.h"
int main(int argc, char** argv)
{
	FILE* saida = stdout;
	int disco   = 0; // gerou arquivo?
	char ref[256] = { 0 };
	int out = 1;
	// inserir a tabela aqui
	// inserir a tabela aqui
	if (argc > 1)
	{	saida = fopen(argv[1], "w");
		disco = 1;
	};
	fprintf(saida, "\nconst char idx[256] =\n{\n\n");
	for (int i = 0; i < 240; i = i + 1)
	{	fprintf(saida, "%3d, ", ref[i]);
		if (out % 16 == 0)
			fprintf(saida, " // %03d-%03d\n", out - 16, out - 1);
		out += 1;
	};
	// ultima linha
	for (int i = 240; i < 254; i = i + 1)
	{
		fprintf(saida, "%3d, ", ref[i]);
		out += 1;
	};
	// ultimo valor na ultima linha :) 
	fprintf(saida, "%3d, ", ref[255]);
	if (out % 16 == 0) fprintf(saida, " // %03d-%03d\n", out - 16, out - 1);
	out += 1;
	// ultimo valor
	fprintf(saida, "  0   // 240-255\n\n}; // ARFNeto '20\n");
	if (disco) fprintf(stderr, "\nGerado trecho de codigo em '%s'\n", argv[1]);
	return 0;
};	// main()

 

Para rodar bastar usar o nome e o nome do arquivo de saída. Sem um nome ele mostra a tabela na saída padrão mesmo, como em 
 

    gera tabela.h

 

que vai gerar tabela.h no diretório corrente. Para ajustar os valores é só editar entre os comentários "inserir os valores aqui" e compilar de novo. Ou editar a saída, claro. :) 

 

Para usar nesse caso aqui sem editar a saída basta  inserir

 

	for (int i = 0; i < 26; i += 1)
	{
		ref['a' + i] = i % 9 + 1;
		ref['A' + i] = i % 9 + 1;
	};	// for

 

entre os comentários.

  • Curtir 1
Postado
2 horas atrás, arfneto disse:

É verdade. Não precisa. Mas a sua redação está sugerindo o inverso da realidade. Entenda que "é só fazer o cálculo..." como escreveu sugere que seria melhor, ou mais simples de algum modo, escrever digito() 

Não que seja melhor, no primeiro post apenas letras maiúsculas e sem acentos estão sendo consideras e assim a função que postei me parece mais simples que criar um vetor/struct. Basta passar a letra como argumento e retornar o número correspondente. Claro que, assim como no caso da struct/vetor do primeiro post, algum teste antes de chamar a função é necessário para garantir que uma letra maiúscula seja passada (ele usou toupper). Outra forma que acho interessante (sem função) para usar apenas caracteres válidos (sem considerar acentos) é assim,

 

char texto[50], *p = texto;
...
while(*p){
    char c = *p & 95;
    if(c >= 'A' && c <= 'Z'){
        soma += (((c - 'A') % 9 ) + 1);
    }
    p++;
}

 

  • Curtir 1
Postado
22 minutos atrás, Midori disse:

Claro que, assim como no caso da struct/vetor do primeiro post, algum teste antes de chamar a função é necessário para garantir que uma letra maiúscula seja passada (ele usou toupper). Outra forma que acho interessante (sem função) para usar apenas caracteres válidos (sem considerar acentos) é assim,

 

Como eu te disse a função de hash é simplesmente o índice da função, e algo assim roda em 6% do tempo. Todos os sistemas usam isso. Não é ideia minha. Só estou mostrando qual é a solução ótima. E ótima não é um julgamento meu. É só matemática: são 256 possíveis valores. Você vai lá e marca o que precisa. ANTES de compilar o programa. E eu até postei um programa que gera a tabela.

 

Há muitas maneiras de escrever isso. A que usou é elegante e legível. Mas uma tabela de conversão não é para ler. é para converter. 

 

Use a função que eu postei para temporizar, por exemplo, e compare essa opção 

 

unsigned soma_via_tabela(const char* frase)
{
#include        "saida.h"
	char* p = (char*)frase;
	unsigned s = 0;
	while (*p != 0)	s += idx[(int)(*p++)];
	return s;
}

 

que não exige nenhum teste adicional, com essa 
 

char texto[50], *p = texto;
...
while(*p){
    char c = *p & 95;
    if(c >= 'A' && c <= 'Z'){
        soma += (((c - 'A') % 9 ) + 1);
    }
    p++;
}

 

e ainda imagine que precisa preencher os tais "..." no seu código ;) 

 

Veja o que tem em idx[]:

 

const char idx[256] =
{

  0,   0,   0,   0,   0,   0, ... 0,   0,   0,  // 000-015
  ...
  0,   0,   0,   0,   0,   0, ... 0,   0,   0   // 240-255

};

 

E nesse caso os "..." são apenas os outros números. E isso está no código compilado. Sem processamento. Nunca. E nem precisa digitar porque eu postei o programa de 20 linhas que gera o arquivo com o nome que você quiser.

 

Provavelmente não vai conseguir nada com outra técnica que rode em menos que 5X esse tempo. E postei uma função que mede e você pode até usar. Nos meus testes rodava em cerca de 6% do tempo ou menos...

 

Leia com atenção o programa. Não é nada sofisticado. Mesmo um iniciante não deve ter dificuldade em entender que a correspondência é de 1:1. Sem qualquer teste. 

 

 

Postado

Eu mudei o código, ficou assim, porém não consigo colocar o calculo correto da numerologia pra ele realizar :(
 

#include <stdio.h>
#include <string.h>

int main(){
	
	char name[500];
	int i, n;
	printf("Enter name: ");
	gets(name);
	
	for(i = 0; name[i] != strlen(name); i++)
	{
		n = ((strlen(name)%9)+1);
	}
	
	printf("nome: %s, resultado do calculo: %d", name, n);	
  
	return 0;
	
}


Alguma sugestão?

Postado
48 minutos atrás, GordinhoCoreano disse:

Alguma sugestão?

Uma pergunta: você leu e testou os códigos que a gente postou aqui? Entendeu? Tem alguma dúvida sobre aquilo?

 

Do modo como escreveu ainda está um pouco longe de funcionar...
 

for(i = 0; name[i] != strlen(name); i++)
{
		n = ((strlen(name)%9)+1);
}

 

Esse loop por exemplo não faz sentido. name[i] é uma letra do nome. Não há razão para comparar com o número de letras do nome, como est;a fazendo.

 

E dentro do loop está reatribuindo o valor de n toda vez. Então de pouco adianta. Ao sair do loop n vai ter o mesmo valor sempre: strlen(name) é constante. 9 é constante, 1 é constante. 

 

Para que está lendo do teclado? Só vai atrasar seus testes. Faça o simples e escreva

 

	char nome[50] = "JOAO DA SILVA";

 

e teste seu programa até dar o resultado que está lá no papel. 37, depois 19, depois 1.

 

 

  • Curtir 1
Postado

@GordinhoCoreano Bem didático e sem blá blá blá; se quiser um código mais enxuto e elegante pode perguntar.

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

typedef struct{
    char 	letra[2];
    int 	numero;
}Tnumerologia;

int procuraletra(char *letra);

int main(void)
{	
	char letra[2];
	int resultado=0, aux=0, aux2=0;
									
	while(procuraletra(letra)!=0)
		{
	
			printf("\nDigite Cada Letra do Seu Nome Seguido De Enter('&' para terminar)...: ");
	
			gets(letra);
			
			printf("\nLetra %s -> %i",letra,procuraletra(letra));
			
			aux=aux+procuraletra(letra);
			
		}	
system("cls");
	printf("\nSoma de todas a letras....: %i\n\n\n",aux);
	
	while(aux>=10)
		{
	
			aux2=(aux/10)+(aux%10);
			
			aux=aux2;
			
		}	
		
	printf("\nSeu Numero Pessoal: %i",aux);

	return 0;
}

int procuraletra(char *letra){
	int i;
	Tnumerologia vetorComDados[27]={{"A",1},{"J",1},{"S",1},
									{"B",2},{"K",2},{"T",2},
									{"C",3},{"L",3},{"U",3},
									{"D",4},{"M",4},{"V",4},
									{"E",5},{"N",5},{"W",5},
									{"F",6},{"O",6},{"X",6},
									{"G",7},{"P",7},{"Y",7},
									{"H",8},{"Q",8},{"Z",8},
									{"I",9},{"R",9},{"&",0}};
									
	for(i=0;i<27;i++)
	{
		if(!(strcasecmp(letra,vetorComDados[i].letra)))
		{
			return vetorComDados[i].numero;
		}
	}
}

 

  • Curtir 1
  • Solução
Postado
9 horas atrás, GordinhoCoreano disse:

Eu mudei o código, ficou assim, porém não consigo colocar o calculo correto da numerologia pra ele realizar

Na parte em que devia pegar a letra (letra - A) você colocou o tamanho do nome. O código pode ser assim,

 

#include <stdio.h>

int main() {
    char nome[100];
    int soma = 0, n = 0;

    printf("Nome: ");
    fgets(nome,100,stdin);
    
    while(nome[n]){
        char c = nome[n] & 95;
        if(c >= 'A' && c <= 'Z'){
            soma += (((c - 'A') % 9 ) + 1);
        }
        n++;
    }
    n = nome[n - 1] = 0;
    while(soma){
        n += (soma % 10);
        soma /= 10;
        if(!soma && n > 9){
            soma = n;
            n = 0;
        }
    }
    printf("Nome: %s, resultado do calculo: %d\n",nome, n);
    return 0;
}

 

  • Curtir 2

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...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!