O problema real é que o sua ordenação não considera todas as possibilidades. Por exemplo, você não tem um if
verificando se o n1
é o maior número. Eu te aconselharia a separar essa parte da ordenação em um método separado e não consigo pensar no momento em um método que não ficaria muito grande comparando número por número, então simplifiquei utilizando um array
. Seu código ficaria assim:
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;
}
}
Uma observação é que a saída que você colocou na sua pergunta produz o resultado inverso já que A deveria ser crescente.
Reescrevi seu código para que ficasse um pouco mais organizado, utilizando uma nomenclatura um pouco mais clara e também dividindo em métodos. Também alterei para que a lógica não estivesse no método main
:
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
Caso não queira usar arrays
como foi adicionado na pergunta você pode mudar o método ordenar
para o seguinte e aplica-lo no primeiro exemplo, removendo os métodos que ficarão sem uso:
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;
}
Seu código final sem usar Integer.parseInt
ficaria assim:
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;
}
}