Klasse identifizieren mit 3 Variablen
gepostet vor 16 Jahre, 7 Monate von Otteros
Ich weiß nicht ob sich schon mal Gedanken über das Problem gemacht hat, aber ich mach sie mir.
Ich habe folgendes Problem:
In einer Schleife werden 3 Variablen zufällig Werte zugewiesen und damit eine Klasse instanziert, aber es darf keine Klasseninstanz doppelt vorkommen.
Meine Idee war folgende (alles wird in Java geschrieben):
Ich mach ein doppeltes HashMap:
HashMap>
wobei Variable A der Index des ersten HashMap ist und und Variable B der des Zweiten und Variable C dann der Inhalt des zweiten, wobei mir grad auffällt, ich muss den Inhalt des zweiten als List oder ähnlichem machen, da ja 1/2 Variablen übereinstimmen dürfen, aber nicht alle 3.
Mir gefällt die Idee nicht besonders, deswegen frag ich mal, ob jemand eine bessere Idee hat.
MfG Otto
gepostet vor 16 Jahre, 7 Monate von Kampfhoernchen
Ich weiß ich werde die Frage bereuen: aber wozu das ganze?
gepostet vor 16 Jahre, 7 Monate von Otteros
*Ich dich nicht anfecht* Wenn du schon fragst, dann bekommst du auch eine Antwort (vll hätte ichs am Anfang mit reinschreiben sollen):
Ich machs nicht wie in anderen Browsergames: eine 2 dimensionalen Weltraum, sondern einen 3 dimensionalen und ich kann ja schlecht 2 dinge an der selben Stelle erstellen (geht hierbei um die Systeme), da sie sich ja sonnst gegenseitig "vernichten" würden.
Ich will mir nämlich grad ein Programm schreiben, um Planeten/Systeme usw. zu erzeugen.
gepostet vor 16 Jahre, 7 Monate von TheUndeadable
In C# würde ich es folgendermaßen machen:
Dictionary
Tuple wäre eine Klasse mit 3 Integers und eigenen Vergleichsoperationen.
Damit könntest du eine einmalige Belegung erzwingen.
gepostet vor 16 Jahre, 7 Monate von cherry
Mach Dir ein Array int a[x][y][z], initialisieren es mit 0. Zusaetzlich kannst Du Dir einen Counter machen int count = 0;
Lass Deinen Zufallsalgorithmus laufen und fuer jede Zahlenkombination x,y,z die Du berechnest mach a[x][y][z]++. Wenn a[x][y][z] == 0 war zaehle count um eins hoch.
Mach das so lange bis count den gewuenschten Wert hat (die Anzahl der Objekte die Du erzeugen willst).
Jetzt laeufst Du durch Dein Array und erzeugst fuer jedes a[x][y][z] > 0 ein Objekt mit den Indices als Parameter.
Der Algorithmus braucht keine seltsame Hash Tabelle (keine Hash funktion) weil Du direkt adressierst. Das Problem dass die Laufzeit gegen Ende enorm zunimmt, da die anzahl der freien Plaetze sich reduzieren ist damit jedoch nicht geloest.
Du kannst dir basierend darauf noch andere spassige Sachen ausdenken - verschiedene Objekte etc.
gepostet vor 16 Jahre, 7 Monate von Otteros
@TheUndeadable: von C# hab ich leider keine Ahnung
@cherry: die Idee klingt gut, vor allem, wenn ich das auf das 2te objekt übersetze, dann spar ich mir eine Klasse überhaupt klar zu schreiben.
EDIT: das mit der Laufzeit sollte eher weniger das Problem sein da es Millionen oder mehr von Möglichkeiten gibt, davon aber nur ein ganz kleiner Bruchteil genutzt wird
gepostet vor 16 Jahre, 7 Monate von cherry
Ahhhh. Natuerlich!
Entscheide fuer jeden der 3 Parameter mit Hilfe eines Zufallsgenerators ob ein Objekt erzeugt werden soll oder nicht. Problem solved. Laufzeit O(N).
gepostet vor 16 Jahre, 7 Monate von Otteros
Original von cherry
Ahhhh. Natuerlich!
Entscheide fuer jeden der 3 Parameter mit Hilfe eines Zufallsgenerators ob ein Objekt erzeugt werden soll oder nicht. Problem solved. Laufzeit O(N).
Mir ist grad unklar, was du damit meinst
gepostet vor 16 Jahre, 7 Monate von cherry
Also Du loopst ueber Deine 3 Koordinaten
for(x=0;x
for(y=0;y
for(z=0;z
und rechnest fuer jeden Punkt aus ob ein Objekt erzeugt werden soll oder nicht, mit Hilfe des Zufallsgenerators. Wenn der Zufallsgenerator sagt ja: hier soll ein Objekt hin erzeugst du es.
gepostet vor 16 Jahre, 7 Monate von Otteros
ahh, verstanden, aber dann kann ich die zahl der zu erstellenden Objekte nur mit einer max. Grenze beeinflussen, aber nicht wirklich eine genaue Zahl festlegen, wobei das mir auch sehr gut gefällt, da ich so immer eine unterschiedliche dichte hab etc. also die Idee ist zum Vorhaben die Möglichkeit, die mir am besten gefällt.
Danke
MfG Otto
NACHTRAG:
Also performant ist das mit den schleifen absolut nicht, aber vermutlich weil ich mit zahlen von -99999 bis 99999 stark übertreibe
ich geh lieber auf kleinere zahlen, sind bei 100 nur 16min, wenn man von 100Rechenschritten/s ausgeht
NACHTRAG2:
bei den zahlen von -500 bis 500 dauerts knapp 10min
gepostet vor 16 Jahre, 7 Monate von Fornax
Wenn ich dich richtig verstanden habe suichst du das. Habe ich von einer Klasse von mir kopiert und angepasst, müsste funktionieren:
class Koordinate implements Comparable{
int x = 0;
int y = 0;
int z = 0;
public boolean compareX(int x){
return this.x.equals(x);
}
public boolean compareY(int y){
return this.y.equals(y);
}
public boolean compareZ(int z){
return this.z.equals(z);
}
public boolean compareKoordinate(Koordinate k){
return this.compareX(k.x) && this.compareY(k.y) && this.compareY(k.y);
}
public int hashCode(){
return this.x*10000 + this.y*100 + this.z;
}
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(!(obj.getClass().getName().equals(this.getClass().getName()))){
return false;
}
if(obj == this || ((obj.hashCode() == this.hashCode()) && ((Koordinate)obj).compareKoordinate(this))){
return true;
}
return false;
}
public String toString(){
return "\""+this.x+"\":"+this.y+":"+this.z;
}
}
HashSet meinSet = new HashSet();
gepostet vor 16 Jahre, 7 Monate von duschendestroyer
vorsicht!
deine Hash funktion hat kollisionen wenn koordinaten werte über 100 annehmen dürfen
// ich hoffe ich seh das gerade richtig es ist ja schon spät
gepostet vor 16 Jahre, 7 Monate von cherry
Original von Otteros
NACHTRAG:
Also performant ist das mit den schleifen absolut nicht, aber vermutlich weil ich mit zahlen von -99999 bis 99999 stark übertreibe
ich geh lieber auf kleinere zahlen, sind bei 100 nur 16min, wenn man von 100Rechenschritten/s ausgeht
NACHTRAG2:
bei den zahlen von -500 bis 500 dauerts knapp 10min
Hmmm, ja.
Du musst halt abwaegen. Wenn Du wenige Objekte hast (relativ zum Platz gesehen) und damit potentiell wenig Kollisionen ist wahrscheinlich die erste Methode besser, da Du nur etwa N mal ne Zufallszahl berechnen musst (wenn N die Anzahl der gewuenschten Objekte ist).
Wenn Du fast jedes Feld fuellst ist sicher die zweite Methode besser wegen Laufzeit O(N).
Wenn Du wirklich 20000x20000x20000 Felder hast kannst Du Dir vielleicht auch einen schnelleren pseudeo-random Zahlengenerator schreiben. Vielleicht muessen Deine Zahlen nicht so enorm zufaellig sein..
gepostet vor 16 Jahre, 7 Monate von Fornax
Ja, klar gibt es Kollisionen. Das ist nur ein Beispiel, das relativ schnell Laufen sollte.
Der Programmierer muss selbst wissen, wie er den Hash am besten bildet. Und ab INT_MAX/3 muss es unweigerlich zu Kollisionen kommen. Doch dafür wird dann die equals-Methode benutzt - die auch noch angepasst werden kann.
gepostet vor 16 Jahre, 7 Monate von Otteros
Aber equal will ich nicht nutzen, da ich die auf alle bereits vorhandenen Objekte anwenden muss. Die Idee hat ich auch schon, fand se aber net besonders brauchbar, wenn ich immer alle Objekte durchgehen muss und wir reden hier nicht von INT_MAX/3 sondern von beliebig gewählten Zahlen.
Original von cherry
Wenn Du wirklich 20000x20000x20000 Felder hast kannst Du Dir vielleicht auch einen schnelleren pseudeo-random Zahlengenerator schreiben. Vielleicht muessen Deine Zahlen nicht so enorm zufaellig sein..
Mir reicht ein zufall von 1 oder 0, aber das gibts je net(hab zumindest nirgends eine Methode für gefunden), aktuell behelf ich mir so: ich addiere 4 Zufallszahlen (macht das ganze zwar langsam, bin aber zufrieden mit) und wenn das dann größer 3.9 ist, dann wird ein System erstellt (das Tempo wird aktuell auch von der DB gebremmst, da die auf meinem USB-Stick läuft und der anscheinen nur 1.1 ist *nachdenk, warum vor kurzem erst bestellt* also bischen was ist mit der db noch rauszuholen und PrepairedStatements helfen da auch net wirklich was zu beschleunigen, wozu sie eigentlich da sind und bei 4000 einträgen sollte da schon was möglich sein). Bei 1000^3 möglichkeiten kommen gut 4100 Systeme raus und ich finde das reicht, ich werde vermutlich keine größeren Zahlen nehmen, da es
a) sonnst zu viele Systeme werden und
b) mir reicht eine Berechnungszeit von 10-15min. und wenns dann nur so klein ist, störts mich auch nicht
gepostet vor 16 Jahre, 7 Monate von Fornax
In wie weit du Zahlen binär auslesen kannst, weiß ich nicht, aber sowas müsste gehen (pseudo):
int zahl = zufallszahl(INT_MIN, INT_MAX)
int[] array = new int[]();
array[0] = getBinärOnPosition(0, zahl)
array[1] = getBinärOnPosition(1, zahl)
array[2] = getBinärOnPosition(2, zahl)
Somit hast du 32 mal "zufällige" Einsen und Nullen
gepostet vor 16 Jahre, 7 Monate von Otteros
Also über Umwege kann ichs zumindest, ob es dafür noch Methoden gibt ka.
Aber die Zufallszahlen sind alle eine double Zahl, ich hab noch keine Methode gefunden, mit der ich int Zahlen erzeugen kann, lass mich aber gerne (wäre mir sogar sehr recht) eines besseren belehren.
Ups, ich glaub wir beide reden von was anderem, ich von der frage, ob man einen neu erstellt oder net, du von den zufälligen Positionen, da brauch ich natürlich mehr Zahlen.
gepostet vor 16 Jahre, 7 Monate von TheUndeadable
Aber die Zufallszahlen sind alle eine double Zahl, ich hab noch keine Methode gefunden, mit der ich int Zahlen erzeugen kann, lass mich aber gerne (wäre mir sogar sehr recht) eines besseren belehren.
de.wikibooks.org/wiki/Java_Standard:_Randomrand.nextInt();
Zum C#: Ich meinte natürlich, dass du das auf Java portieren musst. Aber Fornax hatte exakt die gleiche Idee wie ich.
deine Hash funktion hat kollisionen wenn koordinaten werte über 100 annehmen dürfen
Der Hash ist nur eine Hilfsfunktion, damit das Dictionary, bzw Hashset weiß, in welchem Korb es das Element einordnen soll. Damit kann die Zugriffszeit drastisch verkleinert werden.
msdn2.microsoft.com/en-us/library/xfhwa508.aspx - Die Java-Implementierung ist ähnlich bis gleich.
The speed of retrieval depends on the quality of the hashing algorithm of the type specified for TKey.
gepostet vor 16 Jahre, 7 Monate von Otteros
Danke, ihr habt mir echt geholfen, wenn ich eine gute Möglichkeit gefunden hab für das ganze, werd ich mich nochmal melden.