The real problem is that your ordering does not consider all possibilities. For example, you do not have if
checking that n1
is the largest number. I would advise you to separate this part of the ordering into a separate method and I can not think of a method that would not look great by comparing number by number, so I simplified using array
. Your code would look like this:
import java.util.Arrays;
import java.util.Scanner;
public class Kaprekar {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("");
int n0 = in.nextInt();
do {
int cr = ordenar(n0);
int dr = inverter(cr);
int rr = dr - cr;
System.out.println("N=" + n0 + " A=" + cr + " B=" + dr + " A-B=" + rr);
n0 = rr;
} while (n0 != 6174);
}
private static int ordenar(int numero) {
int[] listaNumero;
listaNumero = inteiroParaArray(numero);
Arrays.sort(listaNumero);
return arrayParaInt(listaNumero);
}
private static int inverter(int numero) {
StringBuilder construtor;
String invertido;
String texto;
texto = String.format("%04d", numero); // Completa com 0
construtor = new StringBuilder(texto);
invertido = construtor.reverse().toString();
return Integer.parseInt(invertido);
}
private static int[] inteiroParaArray(int numero) {
String numeroString = String.valueOf(numero);
int[] resultado = new int[numeroString.length()];
int indice;
for (indice = 0; indice < numeroString.length(); indice++) {
resultado[indice] = numeroString.charAt(indice) - '0';
}
return resultado;
}
private static int arrayParaInt(int[] numeros) {
StringBuilder numeroString = new StringBuilder();
int resultado;
for (int numero : numeros) {
numeroString.append(numero);
}
resultado = Integer.parseInt(numeroString.toString());
return resultado;
}
}
One note is that the output you put into your question produces the inverse result since A should be growing . >
I rewrote your code to make it a bit more organized, using a slightly clearer nomenclature and also dividing it into methods. I also changed so that the logic was not in the main
method:
import java.util.Arrays;
import java.util.Scanner;
public class Kaprekar {
public static void main(String[] args) {
Kaprekar kaprekar = new Kaprekar();
kaprekar.ler();
}
public void ler() {
Scanner entrada;
String lido;
entrada = new Scanner(System.in);
/* Utilizei nextLine para que você possar validar se realmente é um inteiro
* ou não, afinal se o usuário digitar algo que não seja número será retornado
* um erro ilegível */
lido = entrada.nextLine();
try {
this.validar(lido);
while (!lido.equals("6174")) {
int milhar;
int centena;
int dezena;
int unidade;
int[] listaCrescente;
int[] listaDecrescente;
int crescente;
int decrescente;
int subtracao;
// Pega os valores numéricos para serem utilizados na ordenação de acordo com a posição
milhar = Character.getNumericValue(lido.charAt(0));
centena = Character.getNumericValue(lido.charAt(1));
dezena = Character.getNumericValue(lido.charAt(2));
unidade = Character.getNumericValue(lido.charAt(3));
listaCrescente = new int[]{milhar, centena, dezena, unidade};
// Ordena o array de forma crescente
Arrays.sort(listaCrescente);
listaDecrescente = inverter(listaCrescente);
crescente = this.arrayParaInt(listaCrescente);
decrescente = this.arrayParaInt(listaDecrescente);
subtracao = decrescente - crescente;
System.out.println("N=" + lido
+ " A=" + this.mostrarFormatado(crescente)
+ " B=" + this.mostrarFormatado(decrescente)
+ " A-B=" + this.mostrarFormatado(subtracao));
lido = String.valueOf(subtracao);
}
} catch (NumberFormatException ex) {
System.out.println("O valor lido não é um número");
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
/**
* Valida o que foi incluído pelo usuário
*
* @param lido
* @throws Exception
*/
private void validar(String lido) throws Exception {
Integer.parseInt(lido); // Retornará um NumberFormatException que será tratado no método que chamou
if (lido.length() != 4) {
throw new Exception("O valor lido " + lido + " não tem 4 caracteres");
}
}
/**
* Inverte o array de inteiro
*
* @param base
* @return Um novo array invertido
*/
private int[] inverter(int[] base) {
int[] resultado = new int[base.length];
int indiceBase;
int indiceRetorno;
indiceRetorno = 0;
// Percorre o array de base de trás pra frente
for (indiceBase = (base.length - 1); indiceBase >= 0; indiceBase--) {
resultado[indiceRetorno] = base[indiceBase];
indiceRetorno++;
}
return resultado;
}
/**
* Transforma um array de inteiro um novo inteiro
*
* @param numeros
* @return Um inteiro com as posições do array
*/
private int arrayParaInt(int[] numeros) {
StringBuilder numeroString = new StringBuilder();
int resultado;
for (int numero : numeros) {
numeroString.append(numero);
}
resultado = Integer.parseInt(numeroString.toString());
return resultado;
}
/**
* Mostra um inteiro formatado com 4 dígitos
*
* @param numero
* @return
*/
private String mostrarFormatado(int numero) {
return String.format("%04d", numero);
}
}
EDIT 1
If you do not want to use arrays
as added in the question you can change the method ordenar
to the following and apply it in the first example, removing methods that will be left unused:
private static int ordenar(int numero) {
int a = numero / 1000;
int b = ((numero - a * 1000) / 100);
int c = ((numero - a * 1000 - b * 100) / 10);
int d = numero - a * 1000 - b * 100-c * 10;
int tmp;
if (a > b) { tmp = a; a = b; b = tmp; }
if (c > d) { tmp = c; c = d; d = tmp; }
if (a > c) { tmp = a; a = c; c = tmp; }
if (b > d) { tmp = b; b = d; d = tmp; }
if (b > c) { tmp = b; b = c; c = tmp; }
return a * 1000 + b * 100 + c * 10 + d;
}
Your final code without using Integer.parseInt
would look like this:
import java.util.Scanner;
public class Kaprekar {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("");
int n0 = in.nextInt();
int ultimoResultado;
do {
int cr = ordenar(n0);
int dr = inverter(cr);
int rr = dr - cr;
System.out.println("N=" + n0 + " A=" + dr + " B=" + cr + " A-B=" + rr);
ultimoResultado = n0;
n0 = rr;
} while (n0 != ultimoResultado);
}
private static int ordenar(int numero) {
int a = numero / 1000;
int b = ((numero - a * 1000) / 100);
int c = ((numero - a * 1000 - b * 100) / 10);
int d = numero - a * 1000 - b * 100-c * 10;
int tmp;
if (a > b) { tmp = a; a = b; b = tmp; }
if (c > d) { tmp = c; c = d; d = tmp; }
if (a > c) { tmp = a; a = c; c = tmp; }
if (b > d) { tmp = b; b = d; d = tmp; }
if (b > c) { tmp = b; b = c; c = tmp; }
return a * 1000 + b * 100 + c * 10 + d;
}
private static int inverter(int numero) {
int a = numero / 1000;
int b = ((numero - a * 1000) / 100);
int c = ((numero - a * 1000 - b * 100) / 10);
int d = numero - a * 1000 - b * 100-c * 10;
return d * 1000 + c * 100 + b * 10 + a;
}
}