Your busca
method is recursive and it performs IO operations. Let's look at what the problems with IO are:
Each recursion of it opens the same file, makes it the operations and closes. Because the method is recursive, it means that you open the file a million times and close it a million times as well.
To make matters worse, this also means that you open it several times and tweak it while it is already open and being written independently in other parts of the program.
The various writes that occur independently, override each other, so that the final content of the file will not be what you want. This bunch of writing and rewriting occurring simultaneously creates a lot of confusion because these writings are competing with each other in an unspecified way, which results in undefined behavior ( undefined behavior) and result in your file is so strange and nondeterministic.
Opening, typing, and closing the same file millions of times is a very slow operation. Abuse of bw.flush()
only makes the situation even worse.
I believe this is a very curious way of reducing the life of your hard drive by writing and overwriting millions of times the same file repeatedly in the same physical position of the disk in a short time. If it is done on a pen-drive, it will be a good way to permanently damage it, since after a few thousand rewrites it will degrade and you will begin to have defective areas on your pen drive.
In addition to the IO issue, there are other things we can note:
count
is a public attribute. I think you should have read in a lot of places, explanations of why this is a bad idea and bad programming practice.
Your algorithm is set to quantidade = 6
. Changing this value will break the algorithm because the size of the resultado
array is also set to 6 and bw.write
writes exactly 6 elements in the file.
The% coded% code is something boring to deal with. The name of the flattened file too.
The variable (33 - 6)
can be replaced with quantidade
.
You are abusing line breaks by concatenating resultado.length
. Remember that "\n"
and System.out.println
already add line breaks. So unless you really want to print the numbers just on the odd lines and leave the even lines blank, this bw.newLine()
is something that's over.
It is more readable and recommendable to declare arrays as \n
instead of int[] nomeDaVariavel
. The reason for this is that in the first form you have the full variable type followed by the variable name, which is the default form and that occurs in all other ways of declaring variables in Java. While in the second form you have a part of the type of the variable followed by the name of the variable followed by the other part of the type of the variable, which is confusing, since the information about the type of the variable is fragmented into two distinct locations .
Why use int nomeDaVariavel[]
if you're already saving everything to a file? A lot of people do not know this, but System.out.println
can be a very slow and cumbersome operation to use.
Then, after fixing all those problems listed above, here is the resulting code below (only the file name was different on my machine, but I put the same file name as yours in the code below) :
package gerasorte2;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Combinacoes {
private static final class Buscador implements AutoCloseable {
private final int[] numeros;
private final int[] resultado;
private int count = 0;
private final FileWriter fw;
private final BufferedWriter bw;
private boolean fechado;
private Buscador(int[] numeros, int quantidade, String arquivo) throws IOException {
if (arquivo == null) throw new IllegalArgumentException("O arquivo não pode ser nulo.");
if (numeros == null) throw new IllegalArgumentException("O conjunto de números não pode ser nulo.");
if (numeros.length == 0) throw new IllegalArgumentException("O conjunto de números não pode ser vazio.");
if (quantidade <= 0) throw new IllegalArgumentException("A quantidade de números a sortear deve ser maior que zero.");
if (quantidade > numeros.length) throw new IllegalArgumentException("Não se pode sortear mais do que todos os números do conjunto.");
this.resultado = new int[quantidade];
this.numeros = numeros;
this.fw = new FileWriter(arquivo);
this.bw = new BufferedWriter(fw);
this.fechado = false;
}
@Override
public void close() throws IOException {
fechado = true;
bw.close();
fw.close();
}
private int busca() throws IOException {
busca(0, numeros.length - resultado.length, 0);
return count;
}
private String arrayToString() {
StringBuilder sb = new StringBuilder(3 * resultado.length);
sb.append(resultado[0]);
for (int i = 1; i < resultado.length; i++) {
sb.append(" ").append(resultado[i]);
}
//sb.append("\n");
return sb.toString();
}
private void busca(int inicio, int fim, int profundidade) throws IOException {
if (fechado) throw new IOException();
if (profundidade + 1 >= resultado.length) {
for (int x = inicio; x <= fim; x++) {
resultado[profundidade] = numeros[x];
count++;
String s = arrayToString();
//System.out.println(s);
bw.write(s);
bw.newLine();
//bw.flush();
}
} else {
for (int x = inicio; x <= fim; x++) {
resultado[profundidade] = numeros[x];
busca(x + 1, fim + 1, profundidade + 1);
}
}
}
}
public static int busca(int[] numeros, int quantidade, String arquivo) throws IOException {
try (Buscador comb = new Buscador(numeros, quantidade, arquivo)) {
return comb.busca();
}
}
public static void main(String[] args) throws IOException {
int[] numeros = {3, 4, 5, 7, 8, 15, 16, 17, 18, 22, 24, 26, 28, 30, 32, 33, 34, 36, 37, 39, 41, 43, 44, 45, 47, 48, 50, 54, 56, 57, 58, 59, 60};
int c = busca(numeros, 6, "C:/Users/Usuario/Documents/Vander/mega.txt");
System.out.println("Total de combinações: " + c);
}
}
I tested the code, and it worked perfectly. And it was fast too:
-
It took only 2 seconds to make all 1,107,568 combinations and save them to the file on my machine.
-
If you uncomment the System.out.println
line, it gets much slower, and takes between 2 minutes and 2 minutes and a half on my machine. However, this depends a lot on the type of console that is receiving the output or where it is redirected (I circled it inside NetBeans).
-
Its original version, besides generating the file in the wrong way and abusing the hard drive, should probably take about 15 minutes on my machine. I did not have the patience or the courage to execute it to the end.
Oh, and if you want to put System.out.println
more or insist on using \n
for each line, just uncomment the lines of them. I do not recommend nor do I see a need in either of them however.