Neuer Ansatz neues Glück.
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace Zahlen
{
public partial class Form1 : Form
{
int stellen; //speichert, wie viele Stellen eingegeben worden sind.
char[] kombi; //speichert die aktuelle Kombination.
StreamWriter sw; //Sorgt fürs schreiben in Datei.
string folder; //speichert Pfad.
bool doppelt; //speichert, ob doppelte Vorkommen ignoriert werden sollen.
const string END = ".txt"; //Dateiendung.
uint counter = 0; //zählt die Zeilen.
uint filecount=0; //zählt die File-Nummerierung.
uint filemax; //speichert maximale Zeilenanzahl.
public Form1()
{
InitializeComponent();
folder = Environment.GetFolderPath(folderBrowserDialog1.RootFolder);//setzt Standardverzeichnis für Ausgabe.
textBox2.Text = folder;//Pfad wird angezeigt in der Textbox.
}
private void button1_Click(object sender, EventArgs e)
{
string s = textBox1.Text; //auslesen der Zeichen.
if (s.Trim().Length == 0) //sind Zeichen eingetragen?.
{
return;
}
doppelt = checkBox1.Checked;//sollen doppelte Einträge ignoriert werden? (Checkbox).
counter = 0;//reset.
filecount = 0;//reset.
InitSw();//einrichten des StreamWriters.
stellen=(int)numericUpDown1.Value;// wieviele Stellen?.
filemax = (uint)(500000000 / (stellen + 1));//maximale Zeilenanzahl wird berechnet, damit die Dateien nicht zu groß werden.
kombi = new char[stellen];//erzeugen des Char-Arrays, welcher die aktuelle Kombination speichert.
List<char> allowed=new List<char>();//Liste erlaubter Zeichen wird erzeugt.
allowed.AddRange(s.ToCharArray());//Liste wird mit erlaubten Zeichen befüllt.
RekCreate(0,allowed);//Das eigentliche Spektakel: Aufruf der Berechnungsfunktion.
// Als Parameter wird die Startstelle (0) und die erlaubten Zeichen angegeben (am Start alle).
sw.Close();//Schließt den StreamWirter.
sw.Dispose();//und löscht ihn.
MessageBox.Show("Fertig!");//Benachrichtigung.
}
void RekCreate(int st, List<char> allowed)//Parameter: aktuelle Stelle und die Liste der erlaubten Zeichen.
{
if (st == stellen)//wenn st, also die aktuelle Stelle = der Stellenanzahl ist, wird die aktuelle Kombi ausgegeben.
{
Ausgabe();//sorgt fürs Schreiben in Datei.
return;//Funktion wird verlassen (es kommen ja keine Stellen mehr).
}
for (int k = 0; k < allowed.Count; k++)//ansonsten werden alle erlaubten Zeichen durchgegangen.
{
kombi[st] = allowed[k];//die aktuelle Stelle erhält das aktuelle Zeichen.
if (!doppelt)//wenn doppelte zahlen nicht ignoriert werden sollen.
{
List<char> al = new List<char>();//temporäre Liste erstellen (wir sollten ja die aktuelle nicht manipulieren, da diese ja gerade durchlaufen wird).
al.AddRange(allowed); //in die temporäre die aktuelle Liste der erlaubten Zeichen kopieren .
al.Remove(allowed[k]); //gerade verwendetes Zeichen entfernen.
RekCreate(st + 1, al); //rekursiver Aufruf, stelle+1 und nur noch die freien Zeichen.
}
else//wenn doppelt ignoriert werden soll.
{
RekCreate(st + 1, allowed);//Rekursiver Aufruf, eine stelle vor.
}
}
}
void InitSw()//Einrichtung des StreamWriters.
{
File.Delete(folder + "\\" + filecount.ToString() + END);//löschen von vorheriger Berechnung.
sw = new StreamWriter(folder + "\\" + filecount.ToString() + END, true, Encoding.Default);//neue Datei zum schreiben, Name über filecount, sodass die Dateien durchnummeriert sind.
}
void Ausgabe()
{
counter++;//zählt die Zeilen (bei jeder Ausgabe +1).
if (counter > filemax)//wenn mehr Zeilen als erlaubt.
{
counter = 0;//reset.
filecount++;//Filecount wird um 1 erhöht.
sw.Close();//SchreibStream wird geschlossen.
InitSw();//neue Datei zum Schreiben wird eingerichtet.
}
sw.WriteLine(new String(kombi));
}
private void button2_Click(object sender, EventArgs e)
{
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)//öffnet die Ordnerauswahl.
{
folder = folderBrowserDialog1.SelectedPath;//zuweisung der vom User gewählten Pfads.
textBox2.Text = folder;//Anzeigeaktualisierung des Pfads.
}
}
}
}
Um Speicherproblemen vorzubeugen, werden die Ergebnisse nicht mehr gespeichert, sondern direkt in Dateien auf die Festplatte geschrieben (die ja etwas größer ist, als der RAM ^^)
Da abhängig von den Parametern ziemlich viele Daten zusammenkommen, wird die ausgabe in jeweil ca 500MB-Blöcke aufgeteilt.
Bei 8 Stellen stürzt das Programm nun nicht mehr ab, man bekommt eine 420 MB Textdatei.
Die grenzen dürften eigentlich nur von der Plattengröße abhängig sein, also Werte bis 9 Zeichen mit 11 Stellen sollten noch gehen.
Ab 12 Stellen dürften die meisten Platten zu klein sein^^.
Achja, um die Dateien zu öffnen dürften normale Editoren nicht ausreichen (sind halt nicht auf so große Dateien ausgelegt).
Nach langer Suche nach einem Freware-Editor, der das kann, bin ich auf
http://www.editpadlite.com/editpadlite.html
gestoßen.
Zum Anzeigen kann man aber auch den more Befehl in der Windows cmd verwenden.
Zusätzlich können optional doppelte Vorkommen gefiltert werden (bzw sie werden gar nicht erst erstellt).
[edit] 119 Sekunden für 7 Stellen, 0-9. 8 Stellen Speichermangel, ausgeben ginge wahrscheinlich, das Windowsterminal ist aber ultralangsam.
2 Sekunden auf meinem Q6600 (2.4 Ghz), wo wohl das meiste der Schreibzugriff auf die Platte einnehem sollte
Zum Prinzip:
Die Stellen werden von 0 bis Ende Rekursiv durchlaufen.
In einer Schleife werden alle Zeichen durchlaufen und in die aktuelle Stelle gesetzt.
Nachdem dies gemacht wurde, wird die Funktion für die nächste Stelle aufgerufen, wo es sich dann immer weiter für jedes Zeichen splitet, bis die letzte Stelle erreicht wurde.
Ist dies der Fall, wird die aktuelle Kombination in eine Datei geschrieben.
Fals man doppelte Einträge nicht drinhaben möchte, wird beim Funktionsaufruf eine Liste mit den erlaubten Zeichen übergeben.
Nach dem Setzen eines Zeichens, wird dieses aus einer kopierten Liste entfernt und diese Liste beim rekursiven aufruf übergeben, sodass das schon verwendete Zeichen nicht mehr verwendet werden kann.
@Yussuf123
Welche Erfahrungen hast du im Bereich Programmieren?
Damit ich weiß, wo ich Schwerpunkte beim Erklären setzen muss.