ICollection<TestIndividual> ist ja restriktiver als ICollection<IIndividual>.
Das heißt bei ersterem beschränkst du dich ausschließlich auf Typen die von TestIndividual erben. Bei zweiterem sind noch ganz andere Klassen erlaubt, sie müssen nur das Interface implementieren.
Wenn man auf solche Stellen trifft, muss man vorsichtig sein. Es ist meistens keine gute Idee ein Interface zu implementieren, das nicht voll unterstützt wird. Das heißt es ist zwar eine ICollection<IIndividual>, aber es unterstützt nur einen bestimmten Typ von IIndividual. Das ist aber von außen nicht zu sehen, und kann zu Fehlern in der Benutzung führen.
Man sollte sich bei sowas möglichst auf ReadOnly Zugriffe beschränken, da kann es zu keinen Konflikten kommen. Also lieber IEnumerable<IIndividual> implementieren, wenn das ausreicht.
Mich würde in dem Zusammenhang auch mal interessieren, wie das bei Abfragen aussieht.
Ich glaube mich finster erinnern zu können, dass die zurückgegebene Zeile eine Maximallänge hat. Also muss ich da immer vor dem Select nen Befehl benutzen, um die Maximallänge zu verändern?
Nö, der Odbc Provider unterstützt nur Parameter über Position, nicht über Namen. Das ? ist Platzhalter für den Parameter, und das erste ? verbindet sich mit dem ersten Parameter.
Ich seh an der Abfrage nichts falsches. Ich würde die einfach mal direkt testen, mit nem beliebigen Datenbanktool, und schauen ob das Ergebnis überhapt falsch ist.
Bei dem Beispieldatensatz ist z.B. endDate der 11.11. und dein Test war wohl am 30. 11. ... eigentlich logisch dass dort nichts zurückgegeben wird.
Das einzige was mich an NHibernate stört und was ich einfach nicht verstehe ist, warum man log4net einsetzt.
Eine Bibliothek sollte nicht so ein Eigenleben führen, dass es seine eigenen Logdateien braucht. Was wo und wie gelogt wird, sollte immernoch der Benutzer der Bibliothek entscheiden.
Na fixen ist leicht. Schwer ist das merken der Fehler. Nur ist ja die Zeit abgelaufen und es gibt nix mehr zu fixen.
Das zeigt nur wieder die Wahrheit der alten Programmiererweisheit: Lass jemand anderen dein Programm testen.
Damit wird es für alle j die kleiner als i sind erledigt. So ist es ja auch gedacht. Für alle j kleiner i wird der neue Wert genommen, für alle j größer i wird der alte Wert genommen.
Ich hab jetzt meine Lösung nicht mehr da, aber die hat auf jeden Fall funktioniert, und sah ziemlich ähnlich aus.
Und du machst einen Fehler beim Berechnen der Differenz. Du nimmst die Differenz der Normen, du musst aber die Norm der Differenz nehmen. Mal zur veranschaulichung 2 Vektoren: a = (10,10), b = (-10,-10)
Die sind offensichtlich verflucht unterschiedlich. Nach deiner Formel käme aber als Differenz der Normen 0 raus, was heißt es wäre konvergiert.
Der Differenzvektor wäre aber (20,20) oder (-20,-20). Die Norm davon ist 800. Was ziemlich weit von 0 entfernt ist. Deines könnte also durch dumme Zufälle viel eher konvergieren. Konvergenz nennt man es ja dann, wenn die echte Lösung nicht weit von der aktuellen Lösung entfernt liegt. Und das ist die Norm des Differenzvektors, nicht die Differenz der Normen.
Du musst also im Prinzip Summieren über (resArr-tmpArr)²
Außerdem würde ich empfehlen, bei eintreten der Konvergenz ( norm < dif ) einfach ein break einzuwerfen. Das ändert jetzt nichts an der Korrektheit, aber die Schleife wird eben verlassen, weil es ja nix mehr zu tun gibt.
Oh da muss man sehr weit ausholen. Vieleicht reicht es ja zu sagen, dass in deinem CPU immernoch Stücke von vor 20 Jahren drin sind. Damals hat man noch so designed, dass der Assembler Code besser lesbar und kürzer ist. Das heißt da stecken Befehle drin, die im Assembler Code gleich mehrere Aufgaben auf einmal lösen. Und heutzutage sind das Altlasten, die wegen der Rückwärtskompatibilität immernoch mitgeschleppt werden müssen und den Prozessor-Architekten große Probleme bereiten.
Man hat im Prinzip mit einem Dreimannzelt begonnen und nach und nach Etagen draufgebaut, bis zum 50-stöckigen Hochhaus von heute, dass immernoch auf dem Fundament des Zeltes steht.
Wann sollte man denn die Iterationsschleife abbrechen? Wenn ALLE Elemente des Differenzvektors (Vektor der neu Iterierten - Vektor der alten Iterierten) einen gewissen Grenzwert unterschritten haben, oder nur EINIGE von denen?
X(
Die euklidische Norm. Dort spielen alle Komponenten des Vektors eine Rolle. Und weil es unsinnig ist eine Wurzel zu ziehen, wenn man das andere einfach Quadrieren kann, betrachtet man da meist das Normquadrat.
Sqrt( a ) < e
ist äquivalent zu (zumindest in unserem Fall wo a ≥ 0 und e ≥ 0)
a < e*e
Zweiteres ist nur eben leichter und genauer zu berechnen.
Und wenn du das geschaft hast, geb ich dir noch nen Tipp wie du tmpArr komplett sparen kannst Aber bring erstmal eine Version zum laufen.
Ihr solltet mal sehen, was für ein Murx alles in euren Prozessoren steckt. Da ist das wirklich wie ein Fleck auf der Tischdecke im Vergleich zu einem brennenden Tisch.
@JunkyXL
Serialisierbare Klassen brauchen auch keinen Default-Konstruktor. Es gibt da sogar einen speziellen Konstruktor (also bestimmte Parameter), der aufgerufen wird, wenn etwas serialisiert wird. Und den kann man sogar protected/private machen und er wird trotzdem benutzt.
Du willst wahrscheinlich auf Xml-Serialisierung hinaus. Dort braucht man zwingend einen Konstruktor ohne Parameter. Das hat aber mit dem SerializableAttribut nix zu tun.
Original von xxxprod
Mir is bei dem Thema wohl die Kreativität ausgegangen. Hätt gerne meine Programmierkentnisse unter "Beweis" gestellt aber für den Inhalt der Fenster ist mir einfach nichts "Gscheites" eingefallen also hab ichs bleiben lassen.
Na wart erstmal ab, was dich bei meinem Kalender erwartet, dann reden wir weiter über Kreativität
Seh ich nicht so. In die 24 Türen kannst du doch reinbauen was du willst. Was hättest du denn beim Thema Weihnachten gemacht? Genau das hättest du auch in einer light Version in eine Tür bauen können.
Und das war mein Problem damit. Es war mir anfangs zu umfangreich.
Bzw. war es schwer ein raumfüllendes Gesamtkonzept zu finden, was in der Zeit umsetzbar ist.
Speicheroptimierung in C# fußt immer auf Wissen über den Garbage Collector.
Ich schlag vor du machst dich dahingehend schlau. Wie arbeitet der Garbage Collector, wann sammelt er, was sammelt er, und wie macht man seine Arbeit schwerer.
Ansonsten wäre auch das Thema Stack vs Heap nicht ganz uninteressant.
Aber gleich vorweg, um da was rauszuquetschen muss man sich schon ziemlich reinknien, und erhält am Ende nicht viel Nutzen. .NET Programme belegen Speicher, wenn er gebraucht wird, und geben ihn erst frei, wenn er von jemand anderem gebraucht wird. Wenns nur um pure Zahlen geht und nicht um messbare Effektivität, wirst du es da eher schwer haben.
Wenn es um nicht-doppelte Zufallszahlen geht, empfiehlt sich ein Array mit allen möglichen Zahlen zu nehmen (wenns nicht gar so viele sind... bei Bingo hält sich das ja noch in Grenzen), dieses dann zu Mischen, und dann die ersten 18 Zahlen zu nehmen.
Für Mischen gibt es viele Varianten. Eine einfache aber effektive
for( int i = 0; i < array.Length; ++i )
Swap( i, rand.Next(0,array.Length) );
Swap ist dabei das Austauschen der Elemente.
rand ist das Random Objekt.
Sorry dass ich das nochmal hochhole. Ist herbivores Schuld, der hat auf den Thread verlinkt
Im Grunde stimmt es, dass Rekursion und Iteration gleichmächtig sind. Aber passt auf, wenn ihr das in einer Prüfung sagt. Es gibt nämlich auch Definitionen von Rekursion, die nicht so mächtig sind wie das, was wir hier auf dem Computer haben.
Bzw. geht es in der Theoretischen Informatik nicht um "unsere" Rekursion, sondern um die primitive Rekursion. Die ist nur LOOP-Berechenbar und nicht Turing-berechenbar.
Der Unterschied ist, dass man mit LOOP nur Schleifen mit einer vorher festgelegten Anzahl an Iterationen machen kann. Das heißt ich kann nicht in der Schleife auswerten, ob ich abbreche. Ich muss schon bevor die Schleife betreten wird bestimmen, wie oft sie durchlaufen wird. In manchen Programmiersprachen ist die FOR-Schleife so ausgelegt (nicht in C#, ich glaube in Pascal und in Python).
Das hat jetzt nicht wirklich praktische Relevanz. Aber wie gesagt in der Prüfung könnte man da leicht auf die Nase fallen, wenn man Rekursion und Primitiv-Rekursive Funktionen durcheinander haut.
Also ich hab meine Bemühungen aus zwei Gründen gestartet:
Erstens hatte ich die zündende Idee, was ich überhaupt da rein machen könnte (mit Herbivores Denkanstoß :D)
Und zweitens, weil ich gesehen habe, dass die Resonanz nicht so übermäßig ist. Da dachte ich, ich kann euch ja nicht einfach so verhungern lassen
Meine Zeit ist eigentlich im Moment auch relativ knapp bemessen. Aber den Beitrag hatte ich jetzt ungefähr innerhalb einer Woche intensiver Arbeit tatsächlich fertiggebracht.
Und ich hab viele schöne Dinge gelernt und probiert, die ich schon immer mal probieren wollte. Nur was verrate ich frühestens, wenn das entsprechende Türchen auf ist
Ich würde mich auf jeden Fall freuen, wenn es sowas wieder gibt. Ich denke die Preise waren auch für niemanden der Auslöser was zu tun
Das was dr4g0n76 beschreibt ist auch eher die Idee hinter Backtracking.
Backtracking und Rekursion liegen ja relativ dicht beieinander. Mit Backtracking braucht man erst garnicht anfangen, wenn man Rekursion noch nicht so richtig versteht.
Paradebeispiele für Rekursionen findest du, wenn du dich mal mit binären Bäumen befasst. Speziell die verschiedenen Möglichkeiten durch einen Baum zu gehen.
Hier mal ein Beispiel eines sortierten Baumes.
D
/ \
B F
/ \ / \
A C E G
Die Frage: Wie bekommt man eine Sortierte Liste der Knoten aus dem Baum, wenn man als Start nur den Zeiger auf D hat?
Wie würdest du vorgehen? Du weißt, dass links alle Elemente kleiner sind als rechts. Also wenn du erstmal alle Elemente links richtig sortiert aufzählst, dann das aktuelle Element nennst, und dann alle Elemente rechts richtig sortiert aufzählst, ist das Problem erledigt. Und weil du weißt, dass diese Eigenschaft für alle Knoten gilt, kannst du das Prinzip überall anwenden. Also schreibst du erstmal diese Idee auf:
Beispiele in dieser Art gibt es in der Graphentheorie viele. Ich denke das ist leicht genug um einen guten Einstieg in die Denkweise Rekursion zu finden.
Das Beispiel hab ich auch gebracht, weil es der Rekursion von "hanoi" ziemlich ähnlich ist. Das Muster ist offensichtlich das gleiche, man muss nur erkennen warum.
Das Grundprinzip ist ja bei beiden: verschieb das Problem erstmal zu einem anderen (dem linken Sohn), wenn der das gelöst hat, weiß ich wies weitergeht.
In dem Baumbeispiel ist es relativ einfach. Wenn alle aufgezählt wurden, die kleiner als mein aktueller Wert sind, dann brauch ich bloß noch den aktuellen Wert schreiben und dann an den nächstbesten übergeben.
Bei der hanoi Rekursion sieht das dann so aus:
Also ich starte mit n Schiben auf dem ersten Stapel (a) und will alle auf einen anderen (c) über einen Hilfsstapel (b) kriegen, und darf nur kleinere Scheiben auf größere Scheiben legen.
Wenn ich alle außer die größte Scheibe von a nach b Schieben würde, könnte ich die größte (letzte) Scheibe einfach auf c legen. Dann müsste ich bloß noch den ganzen Stapel von b wieder nach c bewegen, mit dem Hilfsstapel a. Dass bei c schon die größte Scheibe liegt stört dabei ja nicht. Und so ist der Algorithmus zu verstehen:
void hanoi(int hoehe, char von, char nach, char ueber)
{
// Ok ich hab vieleicht keine Ahnung wie ich von "von" nach "nach" komme
// aber wenn ich alle außer die letzte nach "über" kriegen würde...
// also lass ich einfach nen anderen Deppen das erledigen
hanoi(hoehe - 1, von, ueber, nach);
// Jetzt weiß ich wies weitergeht. Muss nur noch die letzte Scheibe rüberlegen
Console.WriteLine("Scheibe '" + von + "' nach '" + nach);
// so, jetzt hab ich meine unterste Scheibe auf "nach" *schweißabwisch*
// und meine restlichen Scheiben sind bei über
// da muss ja nur noch irgendwer die restlichen Scheibe von "über"
// nach "nach" bringen und ich bin fertig
hanoi(hoehe - 1, ueber, nach, von);
}
}
So, was fehlt noch? Richtig, eine Abbruchbedingung. Das ganze würde sich endlos im Kreis drehen, und da sind wir bei dem wichtigsten, das eine Rekursion erst ermöglicht: Der Trivialfall. Meistens erkennt man den als allererstes. Es ist die Menge an Problemen, für die man sofort eine Lösung hinschreiben könnte. Bei Hanoi ist das ganz einfach dann, wenn der Turm nur aus einer einzigen Scheibe besteht. Dann ist der Fall trivial, ich leg halt die Scheibe hin und muss sonst nichts mehr tun. Ich muss nur noch den Code so auslegen, dass der Trivialfall erkannt und behandelt wird. Also frage ich hab, ob "höhe" überhaupt größer als 1 ist. Und wenn nicht, ist der Trivialfall eingetreten.
Wir haben z.B. einen Kunden, der uns .piz Dateien schickt, bzw. wir ihm schicken müssen, weil irgendein Depp meint die Mitarbeiter dürfen keine zip Dateien empfangen und man kann da auch keine Ausnahmen machen...
So fertig, gleich wirds abgeschickt Wenns nicht da ist bitte mal melden.
Und wehe das geht bei irgendwem nicht... X(
Zumindest der Quellcode sollte für einige interessant sein und so manche FAQ beantworten. Ich hoff aber mal der wird erst nach dem Wettbewerb freigegeben, sonst ist ja die ganze Überaschung dahin
Immerhin 90% von dem geschaft, was ich mit vorgestellt habe. Und für die restlichen 10% braucht man ja bekanntlich nochmal so lange.
Also ich beantworte Fragen, die mir zu doof sind, einfach nicht.
Ausnahme sind Fragen wie "Mit [beliebige Programmiersprache] konnte ich das so machen. Warum kann das C# nicht?". Besonders wenn die Programmiersprache C/C++ oder (Visual) Basic heißt... Da kann ich dann schon etwas angefressen reagieren.