Ir ao conteúdo
  • Cadastre-se

C Calculo da Numerologia / Linguagem C


GordinhoCoreano
Ir à solução Resolvido por Midori,

Posts recomendados

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

Link para o comentário
Compartilhar em outros sites

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.

 

Link para o comentário
Compartilhar em outros sites

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
Link para o comentário
Compartilhar em outros sites

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
Link para o comentário
Compartilhar em outros sites

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. 

 

 

Link para o comentário
Compartilhar em outros sites

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?

Link para o comentário
Compartilhar em outros sites

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
Link para o comentário
Compartilhar em outros sites

@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
Link para o comentário
Compartilhar em outros sites

  • Solução
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
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!