/* =============================================================================================
   Wilfredo Cruz Yarlequé                              wcruzy@gmail.com
   Piura, Perú, Noviembre 28 de 2024
   
   =============================================================================================
   Se conoce como constante de Kaprekar (en honor al matemático D. R. Kaprekar) al punto fijo
   de la aplicación iterativa de la denominada Operación de Kaprekar, que consiste en calcular
   la diferencia entre un número cualquiera con sus dígitos ordenados de mayor a menor y dicho
   número con el orden de sus dígitos de menor a mayor.

   La constante de Kaprekar más conocida es el 6174, que ocurre cuando el número inicial de la
   operación de Kaprekar tiene cuatro dígitos y está en base 10. Por ejemplo, con el número
   2435:

   - Se comienza con el número 2435
   - Se ordenan sus dígitos en orden descendente: 5432
   - Se ordenan sus dígitos en orden ascendente: 2345
   - Se resta el número ascendente al número descendente: 5432 - 2345 = 3087
   - Se repite el proceso con el resultado obtenido: 8730 - 0378 = 8352
   - Se continúa repitiendo el proceso: 8532 - 2358 = 6174
   - Una vez que se llega a 6174, la operación se detiene: 7641 - 1467 = 6174

   Como aplicar la operación de Kaprekar a 6174 da 6174, ese número es un punto fijo; y por
   tanto, una constante de Kaprekar

   El cero es una constante de Kaprekar trivial para todos los casos, debido a que 0 - 0 = 0

   Lógicamente, si el número que se selecciona tiene todas sus cifras iguales, llevará a la
   constante trivial.

   Fuente: Wikipedia https://es.wikipedia.org/wiki/Constante_de_Kaprekar
   ============================================================================================= */

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

void kaprekar (void);

int leer (int);

int ordenaAscendente (int);

int ordenaDescendente (int);

void main()
{
	int numero;
	int diferencia, numero1, numero2;

	kaprekar();

	numero = leer(0);
	diferencia = 0;

	while (diferencia != 6174)
	{
		numero1 = ordenaDescendente(numero);
		numero2 = ordenaAscendente(numero);
		diferencia = numero1 - numero2;
		printf("\n%4d - %4d = %4d", numero1, numero2, diferencia);
		numero = diferencia;
	}

	printf("\n\n");
}

// ---------------------------------------------
// Constante de Kaprekar
// ---------------------------------------------
void kaprekar()
{
	system("clear");
	printf("\n\n-------------------------------");
	printf("\n Constante de KAPREKAR");
	printf("\n-------------------------------\n\n");
}

// ---------------------------------------------
// Función para leer número de cuatro dígitos
// ---------------------------------------------
int leer(int numero)
{
	int sigue;

	do
	{
		sigue = 0;
		printf ("Ingrese un número de cuatro dígitos diferentes: ");
		scanf("%d", &numero);
		if (numero % 1111 == 0)
			sigue = 1;
	} while (numero < 1000 || numero > 9999 || sigue == 1);

	return numero;
}

// ---------------------------------------------
// Función para ordenar en forma ascendente
// ---------------------------------------------
int ordenaAscendente (int numero)
{
	int n[4];
	int i, j, temp;

	for (i = 0; i < 3; i++)
	{
		n[i] = numero / pow(10, 3 - i);
		numero = numero - n[i] * pow(10, 3 - i);
	}

	n[3] = numero;

	for (i = 0; i < 4; i++)
	{
		for (j = 0; j < 3 - i; j++)
			if (n[j] > n[j + 1])
			{
				temp = n[j];
				n[j] = n[j + 1];
				n[j + 1]=temp;
			}
	}

	return n[0] * 1000 + n[1] * 100 + n[2] * 10 + n[3];
}

// ---------------------------------------------
// Función para ordenar en forma descendente
// ---------------------------------------------
int ordenaDescendente (int numero)
{
	int n[4];
	int i, j, temp;

	for (i = 0; i < 3; i++)
	{
		n[i] = numero / pow(10, 3 - i);
		numero = numero - n[i] * pow(10, 3 - i);
	}

	n[3] = numero;

	for (i = 0; i < 4; i++)
	{
		for (j = 0; j < 3 - i; j++)
			if (n[j] < n[j + 1])
			{
				temp = n[j];
				n[j] = n[j + 1];
				n[j + 1] = temp;
			}
	}

	return n[0] * 1000 + n[1] * 100 + n[2] * 10 + n[3];
}