The real problem is that your ordering does not consider all possibilities. For example, you do not have a if
checking whether the n1
is the largest number. I would advise you to separate that part of the ordering into a separate method and I can’t think at the moment of a method that wouldn’t get too large comparing number by number, so I simplified it using a 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 observation is that the output you put in your question produces the opposite result since To should be crescent.
I rewrote your code to make it a little more organized, using a little clearer nomenclature and also dividing it into methods. I also altered it so that the logic wasn’t in the method 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
If you don’t want to use arrays
as it was added in the question you can change the method ordenar
to the following and apply it in the first example by removing methods that will be 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;
}
}
Please avoid long discussions in the comments; your talk was moved to the chat
– Maniero